# Java quickstart

> How do I write Java scripts in Windmill? Create, test and deploy Java scripts with Maven dependency management.

In this quick start guide, we will write our first script in [Java](https://www.java.com/).

![Editor for Java](./java_exec.png "Script in Java")

This tutorial covers how to create a simple script through Windmill web IDE. See the dedicated page to [develop scripts locally](../../../advanced/4_local_development/index.mdx).

Scripts are the basic building blocks in Windmill. They can be [run and scheduled](../../../triggers/index.mdx) as standalone, chained together to create [Flows](../../../flows/1_flow_editor.mdx) or displayed with a personalized User Interface as [Apps](../../7_apps_quickstart/index.mdx).

Scripts consist of 2 parts:

- [Code](#code): for Java scripts, it must have at least a **public** static main method inside a Main class.
- [Settings](#settings): settings & metadata about the Script such as its path, summary, description, [JSON Schema](../../../core_concepts/13_json_schema_and_parsing/index.mdx) of its inputs (inferred from its signature).

From the Home page, click **New** and select **Script**. This will take you to the first step of script creation: [Metadata](../../../script_editor/settings.mdx#metadata).

## Settings

![New script](./java_settings.png "New script")

As part of the [settings](../../../script_editor/settings.mdx) menu, each script has metadata associated with it, enabling it to be defined and configured in depth.

- **Summary** (optional) is a short, human-readable summary of the Script. It will be displayed as a title across Windmill. If omitted, the UI will use the `path` by default.
- **Path** is the Script's unique identifier that consists of the [script's owner](../../../core_concepts/16_roles_and_permissions/index.mdx), and the script's name. The owner can be either a user, or a group ([folder](../../../core_concepts/8_groups_and_folders/index.mdx#folders)).
- **Description** is where you can give instructions through the [auto-generated UI](../../../core_concepts/6_auto_generated_uis/index.mdx) to users on how to run your Script. It supports markdown.
- **Language** of the script.
- **Script kind**: Action (by default), [Trigger](../../../flows/10_flow_trigger.mdx), [Approval](../../../flows/11_flow_approval.mdx), [Error handler](../../../flows/7_flow_error_handler.md) or [Preprocessor](../../../core_concepts/43_preprocessors/index.mdx). This acts as a tag to filter appropriate scripts from the [flow editor](../../6_flows_quickstart/index.mdx).

This menu also has additional settings on [Runtime](../../../script_editor/settings.mdx#runtime), [Generated UI](#generated-ui) and [Triggers](../../../script_editor/settings.mdx#triggers).

Now click on the code editor on the left side.

## Code

Windmill provides an online editor to work on your Scripts. The left-side is
the editor itself. The right-side [previews the UI](../../../core_concepts/6_auto_generated_uis/index.mdx) that Windmill will
generate from the Script's signature - this will be visible to the users of the
Script. You can preview that UI, provide input values, and [test your script](#instant-preview--testing) there.

![Editor for Java](./java_exec.png "Editor for Java")

As we picked `Java` for this example, Windmill provided some
boilerplate. Let's take a look:

```java
//requirements:
//com.google.code.gson:gson:2.8.9
//com.github.ricksbrown:cowsay:1.1.0

public class Main {
  public static class Person {
    private String name;
    private int age;

    // Constructor
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
  }

  public static Object main(
    // Primitive
    int a,
    float b,
    // Objects
    Integer age,
    Float d,
    Object e,
    String name,
    // Lists
    String[] f
    // No trailing commas!
    ){
    Gson gson = new Gson();

    // Get resources
    var theme = Wmill.getResource("f/app_themes/theme_0");
    System.out.println("Theme: " + theme);

    // Create a Person object
    Person person = new Person( (name == "") ? "Alice" : name, (age == null) ? 30 : age);

    // Serialize the Person object to JSON
    String json = gson.toJson(person);
    System.out.println("Serialized JSON: " + json);

    // Use cowsay
    String[] args = new String[]{"-f", "dragon", json };
    String result = Cowsay.say(args);
    return result;
  }
}

```

In Java you need `Main` public class and public static `main` function.
Return type can either be an `Object` or `void`. Any primitive java type can be automatically converted to `Object`.

 There are a few important things to note about the `Main`.

- The arguments are used for generating
  1.  the [input spec](../../../core_concepts/13_json_schema_and_parsing/index.mdx) of the Script
  2.  the [frontend](../../../core_concepts/6_auto_generated_uis/index.mdx) that you see when running the Script as a standalone app.
- Type annotations are used to generate the UI form, and help pre-validate
  inputs. While not mandatory, they are highly recommended. You can customize
  the UI in later steps (but not change the input type!).

Packages can be installed through [Coursier](https://get-coursier.io/). Just add the dependencies you need at the top of the file, one per line in the format `groupId:artifactId:version`:

```java
//requirements:
//com.google.code.gson:gson:2.8.9
//com.github.ricksbrown:cowsay:1.1.0
```
It supports [Maven](https://maven.apache.org/what-is-maven.html) and [Ivy](https://ant.apache.org/ivy/) repositories.

### Private Maven registries

On [Enterprise Edition](/pricing), you can configure private Maven repositories from [Instance settings](../../../advanced/18_instance_settings/index.mdx#registries) -> Registries -> Maven `settings.xml`.

Provide the full content of a Maven `settings.xml` file. Windmill writes this file to the Java home `.m2/settings.xml` directory, allowing Coursier to use your configured servers, mirrors, and repository URLs when resolving dependencies. If the setting is cleared, the `settings.xml` file is removed.

Example `settings.xml` content:

```xml
<settings>
  <servers>
    <server>
      <id>my-private-repo</id>
      <username>deploy-user</username>
      <password>my-secret-token</password>
    </server>
  </servers>
  <profiles>
    <profile>
      <id>private</id>
      <repositories>
        <repository>
          <id>my-private-repo</id>
          <url>https://maven.example.com/releases</url>
        </repository>
      </repositories>
    </profile>
  </profiles>
  <activeProfiles>
    <activeProfile>private</activeProfile>
  </activeProfiles>
</settings>
```

## Instant preview & testing

Look at the UI preview on the right: it was updated to match the input
signature. Run a test (`Ctrl` + `Enter`) to verify everything works.

## Generated UI

From the Settings menu, the "Generated UI" tab lets you customize the script's arguments.

The UI is generated from the Script's main function signature, but you can add additional constraints here. For example, we could use the `Customize property`: add a regex by clicking on `Pattern` to make sure users are providing a name with only alphanumeric characters: `^[A-Za-z0-9]+$`. Let's still allow numbers in case you are some tech billionaire's kid.

![Advanced settings for Java](./ui_java.png "Advanced settings for Java")

## Run!

We're done! Now let's look at what users of the script will do. Click on the [Deploy](../../../core_concepts/0_draft_and_deploy/index.mdx) button
to load the script. You'll see the user input form we defined earlier.

Note that Scripts are [versioned](../../../core_concepts/34_versioning/index.mdx#script-versioning) in Windmill, and
each script version is uniquely identified by a hash.

Fill in the input field, then hit "Run". You should see a run view, as well as
your logs. All script runs are also available in the [Runs](../../../core_concepts/5_monitor_past_and_future_runs/index.mdx) menu on
the left.

![Run in Java](./run_java.png "Run in Java")

You can also choose to [run the script from the CLI](../../../advanced/3_cli/index.mdx) with the pre-made Command-line interface call.

## Caching

Every binary and dependency on Java is cached on disk by default. Furthermore if you use the [Distributed cache storage](../../../core_concepts/38_object_storage_in_windmill/index.mdx#instance-object-storage-distributed-cache-for-python-rust-go), it will be available to every other worker, allowing fast startup for every worker.

## What's next?

This script is a minimal working example, but there's a few more steps that can be useful in a real-world use case:

- Pass [variables and secrets](../../../core_concepts/2_variables_and_secrets/index.mdx)
  to a script.
- Connect to [resources](../../../core_concepts/3_resources_and_types/index.mdx).
- [Trigger that script](../../../triggers/index.mdx) in many ways.
- Compose scripts in [Flows](../../../flows/1_flow_editor.mdx), [low-code apps](../../../apps/0_app_editor/index.mdx) or [full-code apps](../../../full_code_apps/index.mdx).
- You can [share your scripts](../../../misc/1_share_on_hub/index.md) with the community on [Windmill Hub](https://hub.windmill.dev). Once
  submitted, they will be verified by moderators before becoming available to
  everyone right within Windmill.

Scripts are immutable and there is an hash for each deployment of a given script. Scripts are never overwritten and referring to a script by path is referring to the latest deployed hash at that path.

For each script, a UI is autogenerated from the JSON schema inferred from the script signature, and can be customized further as standalone or embedded into rich UIs using the [App builder](../../7_apps_quickstart/index.mdx).

In addition to the UI, sync and async [webhooks](../../../core_concepts/4_webhooks/index.mdx) are generated for each deployment.
