# Spring Boot

> Build, run and test Spring Boot applications with elide.pkl: declare starters, package a JVM distribution, and adopt an existing application.

Build Spring Boot applications with `elide build`, run them with `elide run`, and execute their JUnit tests with
`elide test`. The project manifest declares Spring starters, the application's main class and its packaged artifacts.

## Start a new application

Generate a Java application with a runnable JVM distribution and an optional context test:

```shell
elide init --plain --skip-defaults --skip-run --template spring project_name=my-app
elide install
elide build :app
elide test
elide run
```

Run initialization in an empty project directory. Use `package=dev.acme` and `main_class=Application` to customize
Java names, or `tests=false` to omit the test. See [Project setup](https://elide.help/docs/projects) for interactive initialization.

## Configure an Elide build

For a concrete starting point, use the Java [Spring REST Service sample at this revision](https://github.com/spring-guides/gs-rest-service/tree/3f4cef01152596c19bc4d37939409358812b1421/complete).
Put this manifest in its `complete/` directory. It preserves that sample's Java 17 target and Spring Boot 4.0.8
dependencies; use your own main class and dependency versions when adapting it to another application.

```pkl
amends "elide:project.pkl"
import "elide:Jvm.pkl" as Jvm

name = "rest-service-complete"
version = "0.0.1-SNAPSHOT"

dependencies {
  spring {
    version = "4.0.8"
    starter { "webmvc" }
    testStarter { "webmvc-test" }
  }
}

jvm {
  main = "com.example.restservice.RestServiceApplication"
  target = 17
  java {
    source = 17
    release = 17
  }
}

artifacts {
  ["jar"] = new Jvm.Jar {
    name = "rest-service"
  }
  ["app"] = new Jvm.JvmApplication {
    name = "rest-service"
    from { "jar" }
    options {
      archives { "zip" }
    }
  }
}
```

## Run and test

From the directory containing `elide.pkl`:

```shell
elide install
elide build :app
elide test
elide run
```

`elide build :app` compiles the application, builds its JAR and assembles the distribution with runtime dependencies.
Use `elide build` to build every declared artifact. `elide run` launches the application's configured main class
from that distribution. For this sample, check `http://localhost:8080/greeting` from another terminal.

The distribution lives in `.dev/artifacts/install/rest-service/`, with JARs in `lib/` and start scripts in `bin/`.
Its ZIP archive is written to `.dev/artifacts/distributions/`. To launch the installed tree directly on a machine
with a compatible JDK:

```shell
.dev/artifacts/install/rest-service/bin/rest-service
```

On Windows, use `bin/rest-service.bat` inside the distribution. See [JAR assembly](https://elide.help/docs/toolchain/jvm/jar) for distribution
options, JVM flags and additional files.

JUnit tests in `src/test/java` use the production resources and test dependencies. Elide provides a JUnit runner by
default. If the application pins its own JUnit platform, disable `jvm.features.testing` and declare a compatible
`junit-platform-console` in `testPackages`; see [Testing](https://elide.help/docs/toolchain/testing).

## Dependencies and resources

`starter { "webmvc" }` expands to `org.springframework.boot:spring-boot-starter-webmvc:4.0.8` in production
dependencies. `testStarter` adds the corresponding starter to test dependencies. Use the starter names offered by
your Spring Boot version, and keep the version aligned with the original build.

Declare non-starter artifacts, such as database drivers or `spring-boot-devtools`, in the ordinary
[Maven dependency buckets](https://elide.help/docs/toolchain/dependencies#maven-buckets). Preserve the versions and scopes selected by your
original build; the shorthand only adds starter coordinates. It does not execute Spring's build plugins.

Conventional `src/main/java`, `src/main/resources` and `src/test/java` directories need no `sources` declaration.
Keep `application.properties` or `application.yml` in `src/main/resources`; Elide includes those resources on
the application's classpath and in its JAR. Use [source sets](https://elide.help/docs/toolchain/source-sets) for a different layout.

For Kotlin, also preserve the compiler version, reflection dependency and Spring/all-open plugin configuration.
The [Kotlin compiler reference](https://elide.help/docs/toolchain/jvm/kotlinc) describes compiler plugins and toolchain selection.

## Adopt an existing application

For an existing project, [`elide adopt`](https://elide.help/docs/toolchain/usage/adopt) can generate the manifest. Commit the project and run its
original build first, then start the interactive migration:

```shell
elide adopt
```

Choose **Elide build**. Review the generated main class, Java target, dependency versions and scopes, resources,
tests and artifacts. Run `elide build`, `elide test` and `elide run`, and check the application's readiness endpoint.
The [adoption guide](https://elide.help/docs/toolchain/usage/adopt) documents harness selection and non-interactive use.

Java Spring Petclinic and Spring REST Service projects are covered by the adoption evaluations. Custom plugins,
generated sources and multi-module builds need their own validation; see [Which projects it fits](https://elide.help/docs/toolchain/usage/adopt#which-projects-it-fits).

Compare resolved dependencies with `elide classpath --json main:runtime test:runtime`, and use explicit Maven
[version resolutions](https://elide.help/docs/toolchain/dependencies#maven-version-resolutions) when the application needs a particular version.

## Packaging and native images

The manifest above produces an ordinary JAR and a JVM application distribution. Spring Boot's nested-dependency
executable JAR layout comes from its [repackage goal](https://docs.spring.io/spring-boot/maven-plugin/packaging.html).
Use an external Maven or Gradle build for Spring-specific tasks such as that packaging format, build metadata,
SBOM generation or Boot container tasks.

Compiling a Spring application to a native executable also requires Spring's AOT processing and reachability
metadata. Declaring an Elide [Native Image artifact](https://elide.help/docs/toolchain/jvm/native-image) does not run those Spring build tasks.
Keep the application's configured native build and follow
[Spring's native application guide](https://docs.spring.io/spring-boot/how-to/native-image/developing-your-first-application.html)
for its AOT lifecycle and toolchain requirements.

## See also

- [JAR assembly and application distributions](https://elide.help/docs/toolchain/jvm/jar)
- [Adopt an existing project](https://elide.help/docs/toolchain/usage/adopt)
- [Dependencies](https://elide.help/docs/toolchain/dependencies) and the [manifest reference](https://elide.help/docs/elide-pkl-reference)
- [JVM toolchain](https://elide.help/docs/toolchain/jvm)
