# Spring Boot

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](/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](/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](/docs/toolchain/testing).

## Development loop

After a source or resource change, rebuild and restart:

```shell
elide build :app
elide run
```

Unchanged tasks are skipped, so a rebuild recompiles only what changed. Run `elide test` before committing. Elide does
not reload a running Spring application; restart it after each rebuild.

## 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](/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.

Java sources compile with `-parameters`, as Spring Boot's Maven parent and Gradle plugin do, so
`@RequestParam` and `@PathVariable` names resolve without explicit values.

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](/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](/docs/toolchain/jvm/kotlinc) describes compiler plugins and toolchain selection.

## Adopt an existing application

For an existing project, [`elide adopt`](/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](/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](/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](/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](/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.

## Limitations

- Spring's Maven and Gradle plugins do not run: no nested-JAR repackaging, build info, SBOM or Boot container images.
- Native executables need Spring AOT processing, which an Elide build does not perform.
- No live reload; restart the application after rebuilding.
- Custom build plugins, generated sources and multi-module builds need manual migration and validation.

## See also

- [Micronaut](/docs/toolchain/jvm/micronaut), the other JVM application framework Elide builds
- Keep an existing build: the [Maven plugin](/docs/build-tools-maven), the [Gradle plugin](/docs/build-tools-gradle)
  or [Bazel rules](/docs/build-tools-bazel)
- [Shared test containers](/docs/toolchain/testing#shared-test-containers) for Testcontainers services in tests
- [Build an HTTP service](/docs/http-service) for serving with Elide's own runtime
- [Native Image](/docs/toolchain/jvm/native-image) and [JVM containers](/docs/toolchain/jvm/containers)
- [JAR assembly and application distributions](/docs/toolchain/jvm/jar)
- [Adopt an existing project](/docs/toolchain/usage/adopt)
- [Dependencies](/docs/toolchain/dependencies) and the [manifest reference](/docs/elide-pkl-reference)
- [JVM toolchain](/docs/toolchain/jvm)
