Java SE Bootstrap API In Jakarta REST 3.1
By Jim Ma | December 24, 2021
After JavaEE was moved under Eclipse Foundation, we started seeing many changes on the specifications; the Jakarta Restful Webservice specification group in particular is fairly active. With Jakarta REST 3.1, there will be a lot of new features included and the Java SE Bootstrap API is among the most important ones. In this post, we’ll go through this new api with some examples and explain RESTEasy will do to support this new feature.
Java SE Bootstrap API
As the API name suggests, this allows a restful application to start in the Java SE
environment. When using this api, an embedded http server will be started and
an application automatically deployed on it to serve the incoming restful request.
The key interface of this feature classes is the SeBootStrap
.
public interface SeBootstrap {
...
/**
* Starts the provided application using the specified configuration. Creates application instance
* from class using default constructor. Injection is not supported.
*
* <p>
* This method is intended to be used in Java SE environments only. The outcome of invocations in Jakarta EE container
* environments is undefined.
* </p>
*
* @param clazz The application class.
* @param configuration Provides information needed for bootstrapping the application.
* @return {@code CompletionStage} (possibly asynchronously) producing handle of the running application
* {@link SeBootstrap.Instance instance}.
* @see Configuration
* @since 3.1
*/
static CompletionStage<Instance> start(final Class<? extends Application> clazz, final Configuration configuration) {
return RuntimeDelegate.getInstance().bootstrap(clazz, configuration);
}
It allows setting the application class and other http server configuration; the implementation will take care of other things and start the restful application. It’s very simple to start an application without packaging and deploying to a Jakarta EE container server like WildFly, Tomcat or Glassfish if you don’t use other Jakarta EE features. This is very convenient especially when you want to test the functionalities of the created restful resource class.
Java SE bootstrap api provides a configuration to accept the different options to configure the http server like protocol, host, port, ssl configuration and rootPath. Please check this example for more details.
RESTEasy Bootstrap API Support
Since RESTEasy 2.3.x, there is embedded container introduced for a test environment or a simple production enviroment without any servlet dependencies. Several embedded container implementations of the server plugin api interface are available:
- Undertow
- JDK HTTP Server
- Netty
- Reactor-Netty
- Vert.x
All these embedded container implements RESTEasy’s EmbeddedJaxrsServer interface. Each embedded container provides the implementation to start/stop the container and “deploy” the deployment. Here is a Netty embedded container example code to demonstrate how the restful service is started through these APIs and interacts with a client sending requests:
NettyJaxrsServer server = null;
Client client = null;
try
{
ResteasyDeployment deployment = new ResteasyDeploymentImpl();
Application app = new TestApplication();
deployment.setApplication(app);
server = new NettyJaxrsServer();
server.setDeployment(deployment);
server.setHostname("localhost");
server.setPort(8080);
server.start();
// call resource
final String path = "/rest-test/echo";
client = ClientBuilder.newClient();
String url = String.format("http://%s:%d%s", server.getHostname(), server.getPort(), path);
Response response = client.target(url).queryParam("text", ECHO).request().get();
assertTrue(response.getStatus() == HttpResponseCodes.SC_OK);
String msg = response.readEntity(String.class);
assertEquals(ECHO, msg);
}
finally
{
if (client != null)
{
client.close();
}
if (server != null)
{
server.stop();
}
}
As you can see, these APIs basically provide the same functionality offered by the SeBootStrap API. Implementing the new Jakarta REST API is hence a matter of adaptapting the RESTEasy JDK HTTPServer embedded container to the SeBootStrap API and properly modifying the ResteasyProviderFactoryImpl:
@Override
public CompletionStage<SeBootstrap.Instance> bootstrap(Application application,
SeBootstrap.Configuration configuration) {
return CompletableFuture.supplyAsync(new Supplier<SeBootstrap.Instance>()
{
@Override
public SeBootstrap.Instance get()
{
SunHttpJaxrsServer server = new SunHttpJaxrsServer();
server.setPort(configuration.port());
server.setHost(configuration.host());
server.setRootResourcePath(configuration.rootPath());
if (configuration.sslContext() != null)
{
SSLParameters sslParams = configuration.sslContext().getDefaultSSLParameters();
if (configuration.sslClientAuthentication() == SeBootstrap.Configuration.SSLClientAuthentication.NONE)
{
sslParams.setNeedClientAuth(false);
}
if (configuration.sslClientAuthentication() == SeBootstrap.Configuration.SSLClientAuthentication.OPTIONAL)
{
sslParams.setWantClientAuth(true);
}
if (configuration.sslClientAuthentication() == SeBootstrap.Configuration.SSLClientAuthentication.MANDATORY)
{
sslParams.setNeedClientAuth(true);
}
server.setSSLContext(configuration.sslContext());
}
server.setProtocol(configuration.protocol());
ResteasyDeployment deployment = new ResteasyDeploymentImpl();
deployment.setApplication(application);
server.setDeployment(deployment);
server.start();
return new SeBootstrap.Instance()
{
@Override
public SeBootstrap.Configuration configuration()
{
return configuration;
}
@Override
public CompletionStage<StopResult> stop()
{
return CompletableFuture.supplyAsync(new Supplier<StopResult>() {
@Override
public StopResult get()
{
server.stop();
return new StopResult() {
@Override
public <T> T unwrap(Class<T> nativeClass)
{
//TODO:implement this;
return null;
}
};
}
});
}
@Override
public <T> T unwrap(Class<T> nativeClass)
{
return null;
}
};
}
});
}
All these changes are pushed to ee10 branch and main change happens in class ResteasyProviderFactoryImpl.
This features is still in development phase and fixes / improvements might still be required. If you want to have a taste of what’s coming with this new api, please check out this branch and play with this api a bit. When you get any issues or questions, please talk with us on Github Discussions.
Useful Links
YourKit supports open source projects with innovative and intelligent tools for monitoring and profiling Java and .NET applications. YourKit is the creator of YourKit Java Profiler, YourKit .NET Profiler, and YourKit YouMonitor