This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Shell 3.3.3!spring-doc.cn

Building

This section covers how to build a Spring Shell application.spring-doc.cn

Starters

  1. Spring Shell Startersspring-doc.cn

Name Description

spring-shell-starterspring-doc.cn

Basic Spring Shell modulesspring-doc.cn

spring-shell-starter-jansispring-doc.cn

With JLine jansi providerspring-doc.cn

spring-shell-starter-jnispring-doc.cn

With JLine jni providerspring-doc.cn

spring-shell-starter-jnaspring-doc.cn

With JLine jna providerspring-doc.cn

spring-shell-starter-ffmspring-doc.cn

With JLine ffm provider (requires JDK22+)spring-doc.cn

spring-shell-starter-testspring-doc.cn

Spring Shell testing supportspring-doc.cn

Terminal Providers

Interacting with an underlying terminal where your program is running has traditionally been relatively complex process while it may look like there’s not that much happening as it’s all just text.spring-doc.cn

Remember all those old manual typewriters or matrix printers? A character is printed where a cursor is which then need to be moved if printing in a different position. In a nutshell that’s how current terminal emulators work.spring-doc.cn

To access and understand existing terminal emulator environment better JLine can use native code via its own shared libraries. JLine detects which providers are present and then makes a choice which one to use. Traditionally there’s been 3 providers, jansi, jni and jna which should all provide same functionalities.spring-doc.cn

Our starters can be used to spesifically pick some of these JLine providers.spring-doc.cn

FFM

With JDK22 a Foreign Function and Memory API came out from a preview which is supposed to be a replacement for JNI providing much better and safer native API.spring-doc.cn

Starting from 3.4.x we’ve added a support to compile Spring Shell application with JLine ffm terminal provider. This obviously mean that application needs to be run with JDK22+. There is a new JDK intermediate release every 6 months and long term support(LTS) release every 2 years. Until there’s an existing LTS release Spring Shell can align with Spring Framework we will use latest JDK release. Obviously this means that you may need to upgrade your JDK in an inconvenient time if you choose to use ffm. We’re also bound to JDK version JLine itself uses to compile its ffm parts.spring-doc.cn

FFM itself will cause jvm to print warnings when some part of it are used. These warnings are obviously annoying with terminal applications as it may interfere and cause a little bit of a mess. In future JDK versions these warnings will also be added for an older JNI modules and at some point these warnings will be changed into hard errors. User will be required to enable these native "unsafe" parts manually.spring-doc.cn

JVM option for this in a command line is:spring-doc.cn

--enable-native-access=ALL-UNNAMED

If you have a jar file you can have this setting in its META-INF/MANIFEST.MF.spring-doc.cn

Enable-Native-Access: ALL-UNNAMED

Which can be added during a build i.e. if using gradle:spring-doc.cn

tasks.named("bootJar") {
    manifest {
        attributes 'Enable-Native-Access': 'ALL-UNNAMED'
    }
}
What comes for enabling native parts in a JDK, JLine has been proactive and already has a check for this and will throw error if native access is not enabled.

Native Support

Support for compiling Spring Shell application into a GraalVM binary mostly comes from Spring Framework and Spring Boot where feature is called AOT. Ahead of Time means that application context is prepared during the compilation time to being ready for GraalVM generation.spring-doc.cn

Building atop of AOT features from a framework Spring Shell has its own GraalVM configuration providing hints what should exist in a binary. Usually trouble comes from a 3rd party libraries which doesn’t yet contain GraalVM related configurations or those configurations are incomplete.spring-doc.cn

It is requred to use GraalVM Reachability Metadata Repository which provides some missing hints for 3rd party libraries. Also you need to have GraalVM installed and JAVA_HOME pointing to that.

For gradle add graalvm’s native plugin and configure metadata repository.spring-doc.cn

plugins {
	id 'org.graalvm.buildtools.native' version '0.9.16'
}

graalvmNative {
	metadataRepository {
        enabled = true
	}
}

When gradle build is run with ./gradlew nativeCompile you should get binary under build/native/nativeCompile directory.spring-doc.cn

For maven use spring-boot-starter-parent as parent and you’ll get native profile which can be used to do a compilation. You need to configure metadata repositoryspring-doc.cn

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
                <configuration>
                    <metadataRepository>
                        <enabled>true</enabled>
                    </metadataRepository>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>
If you rely on spring-boot-starter-parent it manages native-maven-plugin version which is kept up to date.

When maven build is run with ./mvnw native:compile -Pnative you should get binary under target directory.spring-doc.cn

If everything went well this binary can be run as is instead of executing boot application jar via jvm.spring-doc.cn