# Script bodies

Most `.install4j` elements with executable Java code use the same compilation model. This page covers what's pre-imported, how to add your own imports, and what implicit parameters the script can reference.

## Java language level

Script bodies are compiled against the project's effective minimum Java version, not a fixed level. Resolution order:

1. The `javaMinVersion` attribute on the project's root `<application>` element, if set.
2. Otherwise, the major version of the bundled JRE (`<jreBundles>`).
3. Otherwise, the floor: Java 1.8. install4j refuses to build with `javaMinVersion < 1.8`.

Read the project's `javaMinVersion` first and use language features the standard way for that level. The 1.8 floor already gives you generics with `<>`, lambdas, method references, and Streams — use them, no raw types, no anonymous inner classes where a lambda fits.

## Where script bodies appear

Script-body elements (text content is Java, whitespace-significant — never reformat):

- `<condition>` — gates whether the surrounding action/screen runs; return `boolean`
- `<validation>` — Form-screen "Next" gate; return `boolean`
- `<preActivation>`, `<postActivation>` — Screen lifecycle; void
- `<initScript>` — Per-form-component init; void
- `<visibilityScript>` — Per-form-component visibility; return `boolean`

`ScriptProperty`-typed properties (declared via `ScriptPropertyDescriptor` in a BeanInfo) are also script bodies, but they live inside `<serializedBean>` and use a wrapper structure — not a flat `<property type="string">`. The script body goes inside the wrapper's `value` property:

```xml
<property name="script">
  <object class="com.install4j.api.beans.ScriptProperty">
    <property name="value" type="string">// script body here
return true;</property>
  </object>
</property>
```

Examples of `ScriptProperty`-typed properties: `RunScriptAction.script`, `ConsoleHandlerFormComponent.consoleScript`, and the various script-typed properties on custom beans. Return type is whatever the descriptor declared. See `reference/serialized-bean-format.md` for the full encoding rules.

## Default imports

These packages are imported automatically — use simple class names, do not write `java.io.File` when `File` will resolve:

```
java.util.*
java.io.*
javax.swing.*
com.install4j.api.*
com.install4j.api.beans.*
com.install4j.api.context.*
com.install4j.api.events.*
com.install4j.api.screens.*
com.install4j.api.actions.*
com.install4j.api.formcomponents.*
com.install4j.api.update.*
com.install4j.api.windows.*
com.install4j.api.unix.*
```

So `File`, `IOException`, `FileWriter`, `Map`, `List`, `ArrayList`, `JTextField`, `InstallerContext`, `UninstallAction`, `Screen`, `FormComponent`, `UpdateChecker`, `WinRegistry`, etc. resolve unqualified.

Notably **not** in the default set: `java.awt.*` (so `Color`, `EventQueue` need an explicit import), `java.net.*`, `java.nio.*`, `java.lang.reflect.*`, `java.time.*`, `java.util.regex.*`, `java.util.stream.*`, `org.w3c.dom.*`. For these, either fully-qualify or add an `import` at the top of the body.

## Adding imports

Place `import` statements at the top of the script body. They are extracted before the body is wrapped in a method. Both regular and `import static` work.

```xml
<validation>
import java.awt.Color;
import java.awt.EventQueue;
import static java.lang.Math.max;

EventQueue.invokeLater(() -> {
    JTextField textField = (JTextField) formEnvironment.getFormComponentById("12").getConfigurationObject();
    textField.setBackground(Color.RED);
});
return true;
</validation>
```

Prefer this over fully-qualified names — it keeps the body readable and matches what the install4j IDE generates. Don't sprinkle `java.io.File`, `java.io.FileWriter` through the body when `File`/`FileWriter` are already imported.

## Implicit parameters

The wrapper method receives these by name (no need to declare; they're parameters in scope). Which ones depend on the enclosing element's bean kind:

| Bean kind | Implicit parameters |
|---|---|
| Action (install) | `InstallerContext context`, `InstallAction action` |
| Action (uninstall) | `UninstallerContext context`, `UninstallAction action` |
| Form screen (`<validation>` / `<preActivation>` / `<postActivation>`) | `InstallerContext context`, `InstallerScreen screen`, `FormEnvironment formEnvironment` |
| Other screen (`<preActivation>` / `<postActivation>`) | `InstallerContext context`, `InstallerScreen screen` |
| Uninstaller screen | `UninstallerContext context`, `UninstallerScreen screen` |
| Form component (`<initScript>` / `<visibilityScript>`) | `InstallerContext context`, `FormComponent component`, `FormEnvironment formEnvironment`, `<ConfigurationObjectClass> configurationObject` (when the component has a backing Swing component — e.g. `JTextField` for `TextfieldComponent`) |

`formEnvironment.getFormComponentById("…")` is the canonical way to reach sibling form components; see `samples/formScreen/jdkSelection.install4j` for working examples.

## Return values

Whatever the descriptor declares. `boolean` for conditions/visibility/validation. `void` for activation hooks. For `ScriptProperty`-typed properties (custom beans), the return type is whatever the BeanInfo's `ScriptPropertyDescriptor.create(..., returnType, ...)` specified — e.g. `String` for a script that produces a label.

Always end with `return …;` if the return type is non-void; missing `return` is a script compile error, not a silent default.

## Helpers from your `<customCode>`

If a script body needs to call into a helper class you've added under `<customCode>`, that helper must be in a **named package** (`package com.example.installer;`) and the script body must `import` it (or use the FQN):

```xml
<validation>
import com.example.installer.AdoptiumApi;

if (!AdoptiumApi.isReachable()) {
    Util.showErrorMessage("Cannot reach Adoptium download server.");
    return false;
}
return true;
</validation>
```

Default-package classes work for `<beanClass>` references but **cannot** be imported here — Java 9+ forbids importing default-package types into a named package, and script bodies are emitted into a named package.
