Categories
Atbash release

Release of Atbash Runtime v0.4

The Atbash runtime version 0.4 continues on exploring the Jakarta EE Core profile. With the release of version 0.3, the product provided the specifications of the Core profile in a modular runtime. This modularity is improved in this version and besides the specifications of the Core profile, there is now support for security, through the MicroProfile JWT Auth specifications, and data by integrating the MicroStream data solution.

The runtime is still starting very fast and can be used on JDK 11, JDK 17, JKD 18, and JDK 19 ea.

Security support

As mentioned in an earlier post the MicroProfile JWT Auth specification, is a good candidate to secure the REST endpoints that hold a central position in the Core Profile.

Since the time that the blog about the security in the Core profile was written, many additions were added to the underlying library that provides the JWT support in the Runtime. The library is updated to include many smaller improvements but also the check that a JWT token with an unencoded body should not be accepted.
Although specified in the JWT Specification, this is not included in the MicroProfile version.

Data Solution

The Core profile does not include any specification around data. The JDBC specification is part of the JVM itself. So that could be used, but over the years, many other solutions were presented to reduce the code overhead. The JPA specification is very broadly used in the Java enterprise world. But also many no-SQL solutions are popular and also a specification is in progress.

But for Atbash Runtime the MicroStream solution is included. It provides you with an ultra-fast data solution where data is stored as Java objects within the heap and binary stored in external storage so that data survive a process restart.

The integration is in an experimental phase and will be improved in the following versions, including some concepts that can be found in the integrations provided by MicroStream itself.

Activate modules

The two additional modules, the security and data one, are not active by default. When you download the Zip file of the runtime, see the download section, the modules are included but not active.

There are two options to

-m microstream
-p full

BOM and API artifacts

When you create an application, as a developer you need a dependency that brings in all the classes and interfaces that are part of the API of the specifications. Since this version 0.4, several artefacts are available to bring in just those specifications that you want to use in your applications.

You can add the following entry in the maven project file

        <dependency>
            <groupId>be.atbash.runtime.api</groupId>
            <artifactId>core-api</artifactId>
            <version>0.4</version>
            <scope>provided</scope>
        </dependency>

And have the classes related to Servlet, CDI, JAX-RS, JSON-P, JSON-B, and MicroProfile config available in your project. Just as with the Jakarta dependencies, the scope should be specified as provided as the Atbash runtime has already these classes available.

Another dependency is the full-api that provides the specifications that are included in the core-api, also the specification of MicroProfile JWT Authentication and classes of MicroStream are available.

To accommodate the creation of a customised runtime, see next section, a BOM artifact is available. This allows you to individually add the dependencies you need.

Add the BOM artifact to the dependencyManagement section and select the dependencies that you need for your application.

      <dependencyManagement>
          <dependency>
              <groupId>be.atbash.runtime.api</groupId>
              <artifactId>bom</artifactId>
              <version>${atbash.runtime.version}</version>
              <scope>import</scope>
              <type>pom</type>
          </dependency>
      </dependencyManagement>


      <dependencies>
          <dependency>
              <groupId>jakarta.ws.rs</groupId>
              <artifactId>jakarta.ws.rs-api</artifactId>
              <scope>provided</scope>
          </dependency>
      </dependencies>

Custom Packager

As mentioned, the default download of Atbash Runtime contains all modules but only those modules of the Core profile are active by default. With the Custom packager, you can create a version of the runtime with only those modules that you need. It allows you also to create a version where some additional modules like the Security or MicroStream module are active by default. Although with a simple script that sets some command line parameters, is also doing exactly the same.

The Packager is not made available for download in a binary form but you can easily build it from code. Check out the code from Github, and launch a mvn package using JDK 11. Within the packager directory, you will find some more information on using the packager at this page.

Download

You can download the abash Runtime version 0.4 zip from this URL: https://bit.ly/3QhTbqP. After that, you can unzip it and execute the JAR file in the top-level directory.

As of this release, you can also verify the download to make sure it is unaltered and identical to the version that I have built. This is the procedure to verify the signature.

openssl dgst -sha256 -verify atbash-runtime-signature.pem -signature atbash-runtime-0.4.zip.sig atbash-runtime-0.4.zip

The future

The main work will be targeted at a real Jakarta EE 10 Core Profile product based on Jetty 12. Additional features around the observability of the runtime will also be added on top of this 0.4 version.

Enjoy.

Categories
Atbash Jakarta EE Testing

Jakarta EE Integration Testing

Testing your application is very important but also difficult to do. Unit tests are relatively easy to create but it can be difficult to run them with realistic values. So developers sometimes use unrealistic values and constructs just to have the code coverage above the company-required threshold.

Integration testing is even more difficult as you need additional systems, like a database, with a predefined set of data to have repeatable tests. So some test frameworks solve this problem by creating specific artefacts for the test, containing parts of your application and fake and mocked other parts. But you are no longer testing your end product anymore and merely are testing that specific test artefact.

With the availability of the Testcontainers framework, developers can again test the real application by deploying it in a container using the runtime that will be used in production. External dependencies like databases can also be set up easily within a container and initialised with the required dataset for each test. At last, we can actually perform some true integration testing.

Now that we have used it for some time, we see that we always use certain code snippets over and over again in our tests.

– Starting the container with the runtime and your application

– Calling the endpoints of our web application and verifying the structure and response codes

– Setting up remote debugging of our application to find out what is going wrong in our tests.

And so on.

The idea of the Atbash Integration testing framework for Jakarta EE is to provide all those snippets in a reusable dependency so that we can quickly and in a uniform way create integration tests for our Jakarta EE applications. As the focus these days of applications are micro services or at least applications that provide REST endpoints, the focus of the testing framework is also for these applications.

Pieces of the Puzzle

The framework is built as a JUnit 5 extension that brings together all the pieces so that you as a developer can very easily start testing your application. Testing a ‘Hello World’ application is as simple as the Hello World application itself.

@ContainerIntegrationTest(runtime = SupportedRuntime.PAYARA_MICRO)
public class HelloPayaraIT extends AbstractContainerIntegrationTest {


  @RestClient
  public HelloService helloService;

  @Test
  void sayHello() {
    String value = helloService.sayHello("JUnit");
    Assertions.assertThat(value).isEqualTo("Hello JUnit");
  }
}

The test starts the container with Payara Micro, deploys your application, and calls the ‘Hello World’ endpoint to verify if the response is as expected. As already mentioned, the Testcontainers framework is used and with the help of Apache CXF, Jackson, and the MicroProfile Rest Client specification, endpoints can be called very easily by defining an interface with the contract of your endpoint(s).

Deploy the Application

You don’t need to do anything. The extension looks for the war file in the target directory and makes sure it ends up in the Docker image that is created on the fly.

In future versions, the search logic will be made more flexible so that it can be used when you don’t use the default structure or Gradle for example.

Define the Runtime

The framework supports Payara Micro, OpenLiberty, and WildFly as Jakarta EE runtime. You can also use Glassfish but there are several limitations with it. See more on that later on.

The runtime that the framework will use, is determined as the value of the ‘runtime’ member of the @ContainerIntegrationTest annotation. You can also live this value to its default and specify the runtime through the JVM System Properties be.atbash.test.runtime. This is especially handy if you are developing a Jakarta EE library or framework and want to test it out on multiple runtimes easily.

The JUnit5 extension creates a specific Docker image for each runtime based on the official Docker image. The tag number of that base image is taken from a default (look at the documentation to find out which number it is) or you can specify it also as a JVM System property.

When this property specifies not only the tag number, but the entire Docker Image identification like payara/micro:5.2022.2 it uses it as the base image. In the example, we use the JDK8 version of Payara Micro 5.2022.2 instead of the default JDK11 version that is chosen by the framework.

The System property can also be used to select a Jakarta EE 9.x or even Jakarta EE 10 based version of the runtime and not the default Jakarta EE 8 ones. This is possible because for the integration tests we only call the application endpoints and there is no direct dependency of the test framework on the Jakarta version that is used within your application.

Also, Glassfish is supported but with a few limitations since there is no official Docker image available. This means I had to use the Docklands image from Adam Bien but it only has an image that is based on JDK8. This image lacks the possibility to have a remote debugging session. See more on that later on in the text.

Call the Endpoints

The second major point of the framework is the simple way how endpoints of your application can be called. The JVM itself can be used for this with the URL class and the openConnection() method for example. But it is rather cumbersome, especially if you do need to create the JSON and read the response, and especially can be tricky since the host and port where the application is running are determined by Testcontainers and the Docker Client.

Although Testcontainers is used under the hood, the developer that writes the test is, as little as possible, confronted with it. For that reason, I choose to make use of the MicroProfile Rest Client to call the application endpoints. The only thing we need to do is to define the ‘contract’ of the endpoint as an interface.

@Path("/hello")
public interface HelloService {

  @GET
  @Path("{name}")
  String sayHello(@PathParam("name") String name);
}

Based on this definition, Apache CXF can create a proxy that actually calls the endpoint of your application. The JUnit5 extension knows or can find out from Testcontainers the URL on which your application is accessible. And with the help of Jackson, you as a developer are also not confronted with creating and reading JSON content. Automatic conversion to Java instances is performed.

The proxy can be ‘injected’ into your test class by using the @RestClient annotation of MicroProfile.

Behind the scenes, some low-level handling and reflection are going on. To avoid the usage of setAccessible() method, the test class and the field where the rest Client is injected must be declared with the scope ‘public’. So that we can avoid warnings and problems by the JVM when performing this low-level stuff.

Some Other Features

Besides the main features described above to automatically deploy your application in a specially created Docker container using the runtime of your choice and making it easy to call endpoints of the application, there are a few other useful features.

Remote debugging

When your test fails, it is very handy that you can start a debugging session to follow the code execution to the point where it goes wrong. When performing integration tests, a remote debugging session will be the fastest and easiest way to find the problem. The integration testing framework has support for remote debugging with a simple option. Just set the debug member of the annotation to true.

@ContainerIntegrationTest(runtime = SupportedRuntime.PAYARA_MICRO, debug = true)

When the container starts, the JVM will wait due to the suspend=y option until the debugger is attached. So when you see the message that Testcontainers is waiting until the container is started, connect the debugger to localhost:5005 (or the host the container is accessible on, you see already some messages in the log where the container is). The start-up continues and comes to the point where you have placed a breakpoint in your application code.

Logging

First of all, make sure you configure a logging output framework like Logback as described in the Testcontainers documentation. The framework has two additional features to show the container log for a specific test.

When a test fails due to a java.lang.AssertionError error, an URL that could not be found (proxy received a status 404) or there was an internal server error detected, the entire container log is shown as part of the test output.

You also can specify the value liveLogging = true resulting in showing the container logs during the execution of the test. It appears as the runtime log is written out ‘immediately’ when generated by the runtime but there is a very small delay.

@ContainerIntegrationTest(runtime = SupportedRuntime.PAYARA_MICRO, liveLogging = true)

Planned Features

The current version of the framework (see Github and Maven Central) already allows to perform an integration test with the Jakarta runtimes but there are already some improvements in the pipeline to cover more use case scenarios.

– Support for database containers and defining the initial data set easily

– Support for integration with other (micro)service(s) that also start as a Docker container during the test.

Atbash Training and Support

Do you need a specific training session on integration testing with a Jakarta runtime or want some help in setting up integration tests? Have a look at the training support that I provide on the page https://www.atbash.be/training/ and contact me for more information.

Enjoy

Categories
Atbash Jakarta EE

Testing the Jakarta EE Core Profile with Atbash Runtime.

What is the Core Profile?

The Jakarta EE specifications have already two profiles, the Full profile, and the Web profile. The Web Profile contains a set of specifications that are geared toward the typical Web Applications. It groups the typical Web Application specifications like Servlet, REST, JSON, JPA, Faces, Security, etc …

The Full profile contains all the Java Enterprise specifications and adds to the above list specifications like WebServices, Messaging, the full EJB specification, connectors, etc …

But the trend in the last years is, mainly due to the move to the cloud, to have smaller runtimes that only need a limited set of specifications.

The MicroProfile specifications are built on top of a limited set of Jakarta specifications, JAX-RS, CDI, JSON-P, and JSON-B.
MicroProfile, although many specifications are useful in all architectural cases, has a focus on microservices and smaller runtime. This has led to the idea to have a specific profile within Jakarta EE that groups a, specific adapted set of specifications in a Core Profile.

The goal of the profile is defined as (see here https://jakarta.ee/specifications/coreprofile/10/)

To provide a profile that contains a set of Jakarta EE Specifications targeting smaller runtimes suitable for microservices and ahead-of-time compilation.

Which specifications?

The idea, since the Core profile is not yet available, is to combine the following specifications

  • Jakarta Servlet
  • Jakarta REST (JAX-RS)
  • Jakarta CDI lite
  • Jakarta JSON-P
  • Jakarta JSON-B
  • Jakarta Configuration

The CDI lite specification focuses around using build-time Compatible Extensions so that the runtime can be used in Ahead-of-time compilation scenarios like GraalVM. When there are no runtime discovery features and everything is known at compile-time, it makes the native compilation much easier.

The Jakarta Configuration specification will be based on the current MicroProfile Configuration specification and is hopefully, after several attempts to standardise this within Java Enterprise, finally available.

What is Atbash Runtime?

The Core Profile is not yet available and will not be available in May 2022, the expected release date of Jakarta EE 10. Mainly because the Jakarta Configuration specification is not ready yet, and the work related to Jakarta EE 10 took more time so there was not enough time available to perform some work around this new Profile.

The idea of Jakarta specifications is also that it is based on some experience and not only on some theoretical assumptions. That was the basis of my idea to create a runtime that contains the specifications of the Core Profile.

The work started some 6 months ago in my spare time and the goal was to create a runtime that combines the mentioned specifications. At that time, only Jakarta EE 9.1 was available. So the current version of Atbash Runtime, version 0.3, is based on

  • Jakarta Servlet 5.0
  • Jakarta CDI 3.0
  • Jakarta REST 3.0
  • Jakarta JSON-P 2.0
  • Jakarta JSON-B 2.0
  • MicroProfile Config 3.0

And it combines the following frameworks

  • Jetty 11.0.8
  • Jersey 3.0.4
  • Weld 4.0.3
  • Jackson Databind 2.13.1
  • Custom implementation of MicroProfile Config based on SmallRye Config.

How can I try it out?

First of all, you can download the zip file to install the runtime from this download URL. It is only 13.3 Mb in size.

Unzip this into a directory of your choice. It will create several JAR files in a directory structure.

Start your application with

java -jar atbash-runtime.jar path-to/application.war

And the application is available on port 8080 (default, can be changed by command line parameter). The runtime is built with JDK 11 and tested on JDK 11, 17, and 18.

Besides this instance mode, there is also a domain mode so that you can remotely access the runtime to, for example, deploy applications on a running process.

It has a modular structure that will be explored more in future versions and has typical extras like an embedded mode, Arquillian adaptor, Docker image, and integration testing framework based on TestContainers.

You can read more about them in the user guide.

What is next?

The following ideas are on my table to experiment more with this runtime and the idea of a Core Profile Runtime

  • Upgrade to the Jakarta EE 10 versions of the specifications now that they become available.
  • Add security like the MicroProfile JWT specification.
  • Add some data access including the fast Java-native object graph persistence provided by MicroStream.

And of course, your ideas and feedback are valuable for the realisation of the Core profile with Jakarta EE.

Enjoy.