Categories
Atbash Testing

Support for Database and Jakarta EE 10 within Jakarta EE Integration Testing Framework

In this release of the Atbash Integration testing framework, we continued improving the support for creating customised Docker images that run your application under test but also added 2 major features, support for databases and Jakarta EE 10.

Depending on the target version of your application, you can use version 1.2.0 if you are building a Jakarta EE 8 application, or 2.2.0 if your application depends on Jakarta EE 10. More on that later in this blog.

In previous blogs, we covered the basics of using the Integration testing framework. You can have a look at this blog for the introduction and the functionality that was provided in version 1.0.

With the second release, we added the option to use a custom Docker build file that will be used for the container with the application. And we added support for using Wiremock to mock the response of remote services. More details can be found in this blog.

Update : Presentation at Jakarta Tech Talks which can be viewed on YouTube channel.

Customised Build file

In this release, we continued adding support for customising the container that runs your application and that you want to test. You had already the option to supply a custom Docker Build file where the framework only adds the appropriate Docker ADD command to add the WAR file. Now you also can customise the build file just before it will be sent to the Docker engine for processing.

There is a DockerImageAdapter interface that can be implemented by the developer to adjust a few lines of the build file, including the default build file provided by the framework.

This allows for simple additions that are future-compatible with possible changes that will be made to the default build file in future versions.

Implementations of the interface are picked up by the ServiceLoader mechanism within Java. So don’t forget to define your class name in the appropriate service file.

Since there might be more than one implementation within the classpath, you can order them by adding a @Priority annotation. The implementations with a low value are called first. If no priority value is specified, a default value of 100 is taken. And of course, when multiple implementations have the same value, the exact order is undefined for the matching priority values.

When you only need to add some environment variables to the container, there is no need anymore to define a custom build file. You can make use of the AdditionalEnvParameters class. Within an implementation of the DockerImageAdapter you can access this class as follows

   public String adapt(String dockerFileContent, TestContext testContext) {
      AdditionalEnvParameters envParameters = testContext.getInstance(AdditionalEnvParameters.class);
        if (envParameters == null) {
            AdditionalEnvParameters envParameters = new AdditionalEnvParameters();
            testContext.addInstance(envParameters);
        }
        envParameters.add(key, value);

   }

The TestContext is an object that is added in this release and can be consulted for various information about the test that is running.
It holds for example the ContainerAdapterMetaData instance that holds all data about the test that is currently running.

And with the AdditionalEnvParameters.add(), you can add key-value pairs to the environment variable for the container.

Support for a database

In this version, it is now possible to define a database container and provide the configuration as a data source for the JPA functionality of your application.

To have this functionality, make sure you perform the following steps.

  • Add the Atbash Integration testing Database artefact to your project.
  • Add the @DatabaseContainerIntegrationTest annotation to the test class. The class must also extend from AbstractDatabaseContainerIntegrationTest.
  • Add the Database test container of your choice as a project dependency. This determines the database that will be started alongside the container with your application.
  • Add the JDBC Driver as the test scope. This must be a driver that works with the selected database. The driver is used for 2 purposes, it is added to the container with the application to provide access to the database and it allows during the setup of the test to prepare the database in a known state for the test. You can also access the database tables during the test through this Driver and DBUnit which is proved automatically.

Once these things are in place, a test execution performs the following tasks.

  • Determine the Database container to start by looking at which JDBC database container is on the classpath.
  • Determinate JDBC driver
  • Add the JDBC Driver to the application container in a runtime-specific way.
  • Start the database container
  • Provide the connection settings as environment variables to the application container
  • Create the tables required for the test by executing a SQL script that the developer provided
  • Add the data to the tables by reading the Excel file.

A variable is prepared that allows you to access the database tables during the execution of your test. For this, the functionality of the DBUnit library is used. This allows you to check that a call to an application endpoint resulted in the expected database changes.

Have a look at the examples https://github.com/atbashEE/jakarta-integration-testing/tree/main/example/database to get started with this new exciting feature.

Jakarta EE 10

Until now, The Jakarta EE testing framework supported only Jakarta EE 8. There is now also an artifact available specifically for Jakarta EE 10. version 2.x is now based on Jakarta EE 10 dependencies and thus can be added as a test dependency to your project.

All functionality that is available for Jakarta EE 8, is also available for this EE 10 version.

Conclusion

With this new release of the testing framework, more options are available to customise the container image that runs your application during the test. For example, you have now the possibility to specify those environment variables and values that need to the added without using a custom docker build script.

The two major features that are added to this version are of course the integration with a database container that makes it much easier when your application uses a database to test its functionality and the support for Jakarta EE 10.

Enjoy

Training and Support

Do you need a specific training session on Jakarta or MicroProfile? Or do you need some help in getting up and running with your next project? Have a look at the training support that I provide on the page https://www.atbash.be/training/ and contact me for more information.

Categories
Architecture performance

Time is Code, my Friend

For several years, the fast startup time of an application or service in Java has been a highly discussed topic. According to the authors of numerous articles, it seems if you don’t apply some techniques for a fast startup, your project is doomed.

This is of course nonsense, and I hope that everyone is sensible enough to realise that this is a hype and a sales and marketing trick to sell you some product. Because unless you are working on some project where start-up time is crucial, like financial transactions, the start-up time of 99.9% of the applications is not important at all (within limits).

Moreover, this startup time and topics like microservices and serverless, only focus on architecture and non-functional requirements. And, if the marketing hype is to be believed, it seems that functionality for the user is not important at all anymore – as long as you have an application that uses at least 5 of the current hypes.

Today, I want to add another interesting finding about applications or services focused on fast startup times. As a general rule, the faster your application starts, the less functionality it has.

The test

X starts up faster than Y. When applying Z you can achieve a 30% reduction in start-up time.  Some frameworks even made their core marketing tagline based on this.  Let us look at 10 solutions and compare them to see what we can learn about the results.

The idea of this test is to develop an application, slightly modified for the requirements of each framework, that has an endpoint capable of processing JSON. As a performance indicator, we measure the time when the first successful response is served by the runtime. I also captured the RSS of the process (for a description see the bottom of the text), to have an idea of the memory usage. And the third parameter I note is the size of the runtime.

Here is a listing of the runtimes:

Spring Boot 3.0. Project created using Spring Initializr using Spring Reactive web to make use of Netty.

Quarkus 2.16. Project created using code.quarkus.io using RestEasy Reactive and RestEasy Reactive JSONB.

Ktor 2.2. Project created using IntelliJ project wizard using Netty server, Content negotiation and Kotlin JSON serialisation.

HttpServer included in JVM with the addition of Atbash Octopus JSON 1.1.1 for the JSON Binding support. Custom minimal framework for handling requests and sending responses.

Payara 6. Jakarta EE 10 application running on Payara Micro 6

OpenLiberty. Jakarta EE 8 application running on OpenLiberty.

Wildfly 27. Jakarta EE 10 application running on WildFly 27

Helidon SE 3.1. The project was created using the Helidon Starter and includes JSON-P and JSON-B support.

Piranha. Jakarta EE 10 core profile application running on the Cor profile distribution

Micronaut 3.8. The project was created using Micronaut Launch and has support for JSON handling.

Why these 10? Because it is a wide range of frameworks in Java or Kotlin with various features and because it is the list of runtimes that I know well enough to create backend applications in.

The data is gathered when running JDK 17 (Zulu 17.30) on a machine with 16 GB of memory and 8-Core Intel i9 – 2,3 GHz processors. Just to give you all the details of the environment of the test in case you want to repeat the tests.

The determination of the time for the first response is performed by a Python 3 script to make sure we can measure very fast startup times.

All the information and code can be found in the Project FF GitHub repository.

The Results 

I will not keep you in suspense any longer, and present you the test results in the table below. The table is sorted according to the first request time from low to high.

FrameworkFirst RequestRSSArtefact size
Pure Java 158 ms41 Mb11 Kb
Helidon632 ms94 Mb5.7 Mb
Quarkus682 ms111 Mb14.1 Mb
Ktor757 ms111 Mb15.3 Mb
Micronaut956 ms116 Mb12.2 Mb
Piranha1060 ms140 Mb8.7 Mb
Spring Boot1859 ms184 Mb21.3 Mb
WildFly4903 ms313 Mb63.1 Mb
Open Liberty6268 ms356 Mb47.6 Mb
Payara Micro10018 ms438 Mb90.1 Mb

The placement of the frameworks is sometimes surprising, while other known facts are confirmed in this test.

But before I discuss some individual results, I want to highlight another aspect that you can see within the data. And which is actually more important than which framework is a few 100 ms faster.

Graph representing Start up time versus Artefact size

If we plot out the artefact size of the runtime against the first response time, we see a pretty good, almost linear relationship. And that is not really a surprise if you think about it. 

No Functionality is a Fast Startup

Looking at the table and the graph in the previous section, it is clear that we can achieve a fast first response when we have little to no functionality available in our application and runtime.

The evidence for that is shown in the example where a simple endpoint is created with only the HttpServer class of the JVM itself and a simple JSON handling library with only the basic functionality. It starts up in an astonishing 158 milliseconds. That is about 25% of the time required by Quarkus, for example.

And the trend of having little code and functionality available which results in a fast startup can also be seen in the results of other frameworks. Really modular frameworks, like Helidon SE, Quarkus, and Ktor are much faster than less modular ones like OpenLiberty and WildFly which are less modular, or Payara Micro which is not modular.

Hence the title “Time is Code, my Friend”, indicates that you can have a faster startup by sacrificing functionality within your application and the runtime, like observability. And yes, native compilation can help here but as said, for 99.9% of applications, startup time is irrelevant. As long as it is reasonably fast – it doesn’t matter if it is 1 or 5 seconds.

But actually, this means that the above results, and the majority of all those other blogs you can read about fast startup times, are completely useless.  Do you have an application that just takes in a JSON object and returns a response? Without interaction with any external system like a database or any other data storage, your application will startup fast but will not be very useful.

And another reason why the above results are useless is the environment in which they are executed: a machine with 8 dual-core CPUs.  If you allocate that configuration in your cloud provider, you will spend quite a lot of money each month. People hesitate to assign more than 0.5 or 1 CPU to their process which means that startup times must be multiplied by a factor.

So we should perform this kind of performance test in an environment with low CPU power and where the application is accessing databases where  latency is also a factor that you should not ignore.

Individual framework discussion

The first observation we can make is that when you really need high performance, do not use any framework or runtime but instead, create your own specialized solution. All the frameworks and runtimes must be generic to support most scenarios developer teams have. This comes with a cost, of course, since developing a specialised solution requires that you have to do much more. It is always a trade-off.

Secondly, Quarkus is less performant in startup time than I expected. They have a very elaborate and complex system to apply build time improvements so that the application can start up really fast. Yet, they reach only the same response times as Helidon SE and Ktor which don’t have such pre-processing. These build time improvements makes Quarkus much more complex, certainly under the hood, which will make maintenance of the framework much harder in the future and requires you to use a Quarkus extension for any kind of library you want to use in combination with Quarkus. There are currently more than 400 extensions because you need a specific extension to make use of the build time enhancements.

Some frameworks start up faster or slower than expected based on the artefact size. Piranha only starts at 1060 ms whereas the trend line says it should start at about 750 ms. So it is 25% slower than expected.  Also, OpenLiberty is slower than expected. On the other hand, WildFly, Quarkus, and Ktor are faster.

Atbash Runtime?

I didn’t include the results of Atbash Runtime in the table and the graph. For the simple reason that it is my pet project to learn about many aspects.  But here are the results:

FrameworkFirst RequestRSSArtefact Size
Atbash Runtime1537 ms168 Mb8.2 Mb

And I’m very proud of the result. Without any efforts focused on the startup time, just trying to create a modular Jakarta EE Core Profile runtime, I succeeded in beating the startup time of Spring Boot. And besides Helidon SE, it is the smallest one.

Conclusion

With the comparison of a simple application looking at the first response time and artefact size using 10 Java and Kotlin frameworks, I want to stress a few important factors:

– All the blogs and articles about startup time are useless since they are based on running a useless application in an unrealistic environment.  So we should stop focusing on all these architectural aspects and non-functional requirements and instead, development teams must focus on the things that matter to the end users of the applications!

– Modular runtimes and frameworks help you in removing functionality you do not need. This can help you to keep the startup time fast enough but also introduce some complexity in building and maintaining the artefacts for your environment.

– The build time enhancements of Quarkus make it faster than expected according to the artefact size. But they introduce complexity that can become a problem for the future of the framework. Other solutions like Helidon SE and Ktor achieve the same startup time without these tricks.

– Native compilation (AOT, Graal VM, etc…) can  reduce startup time and memory usage but are useless for 99.9% of the applications as they don’t benefit from those gains. And it will only introduce more complexity.

( I would like to thank Debbie for reviewing and commenting on the article)

Notes

The RSS (Resident Set Size) of a process is the portion of its memory that is held in RAM (Random Access Memory) and is used by the operating system to keep track of the memory usage of the process. It includes both the data and code segments of the process, as well as any shared libraries it is linked against.

The tests are performed with 10 times more free memory on the machine to make sure that the process is only using RAM.

Project FF, the Framework Frenzy, Framework Face-off, Framework Fireworks, or … the comparison and similarities between Jakarta EE Web Profile, Spring Boot, Quarkus, Kotlin Ktor, and a few others regarding creating backend applications with REST endpoints. It will host an extensive comparison between many frameworks regarding the functionality that you can find within Jakarta EE Web Profile, MicroProfile, and some other commonly used functionality in today’s back-end applications.

Atbash Training and Support

Do you need a specific training session on Jakarta or MicroProfile? Or do you need some help in getting up and running with your next project? Have a look at the training support that I provide on the page https://www.atbash.be/training/ and contact me for more information.

Categories
Jakarta EE Observability

Using OpenTelemetry with Jakarta EE

OpenTelemetry (informally called OTEL or OTel) is a powerful observability framework that assists in generating and capturing telemetry data from the software. With the rise of now-distributed systems, it has become increasingly difficult for developers to see how their services depend on or affect other services, especially in critical situations such as deployments or outages. OpenTelemetry provides a solution to this problem by making it possible for both developers and operators to gain visibility into their systems.

It is the merger of two other standards, OpenTracing provided a vendor-neutral API for sending telemetry data over to an Observability back-end, and OpenCensus provided a set of language-specific libraries that developers could use to instrument their code and send to any one of their supported back-ends.

As a CNCF incubating project, it is providing a set of standardized, vendor-agnostic SDKs, APIs, and tools for ingesting, transforming, and sending data to an Observability back-end. There is an implementation of the API for Java available, so integration with any Jakarta EE runtime is very easy and doesn’t require any additional implementation.

What does it do?

If you are not familiar with Otel or Observability, then this little introduction is for you. Especially in a micro-services world, but also in other scenarios, it can be very helpful to trace back individual requests and where they spent their time on. Not that it is the main goal, it already captures how much time was needed before a response was sent back to the client. But it can also collect information about database calls, calls to other services, etc … You get information about each request and you can use it to analyse your environment and find the bottlenecks for example. As the saying goes “To measure is to know.” (Although that sounds way much better in dutch “meten is weten”).

You can analyse the information as all the different pieces of information are linked together and stored by a collector. A kind of data storage where you can retrieve and analyse the information.

Observability is much more than just tracking a request throughout your environment. It is also about metrics and processing logs. In this blog, I’m concentrating on request tracing.

Out of the box

The Java implementation of OTel provides integration with Jakarta REST out of the box through a Java Agent. You can find all the supported frameworks and libraries on this page. Some of them require a specific dependency, other frameworks, like JAX-RS require only the Java agent itself.

Personally, I’m not a fan of Java agents. It allows of course to add functionality to your project without the need to change anything in your project. But I don’t like fiddling with the command line to add the Java agent and large sections to define the configuration. And in most cases, you will require the OpenTelemetry API in your application anyway as you want to interact with the system and define for example which CDI methods you like to be included in the trace.

Manual integration

But also integrating the OTel functionality in the application yourself is very straightforward. As an example, I created an integration of the OpenTelemetry Java API for Jakarta EE 10 with the following features.

  • Traces the JAX-RS requests that are processed.
  • Starts a new Tracing or starts a new child span if the header indicates that tracing is already in progress.
  • You can include information about CDI method calls by using an annotation on the method.
  • A Filter for JAX-RS clients is available to propagate the OpenTelemetry information on the header
  • Automatically registers this filter when you have a MicroProfile Rest Client available.

And all this with around 10 classes.

What do you need to do?

If you are interested in creating this integration for your project yourself, have a look at the GitHub repository. It should give you all the information needed to create a specific integration yourself very rapidly.

If you want to use my version in your Jakarta EE 10 project, follow the following steps.

  • Add the maven artefact to your project
    <dependency>
    <groupId>be.atbash.jakarta</groupId>
    <artifactId>opentelemetry</artifactId>
    <version>0.9.0</version>
    </dependency>
  • Define the name of your service, and how it shows up in the OpenTelemetry collector, through a MicroProfile Config source with the key atbash.otel.service.name.
  • Configure, if needed to OTel connector connection through environment variables as required by the OpenTelemetry Specification.
  • Use @WithSpan on a CDI method, or register RestClientPropagationFilter on your JAX-RS client if you want to make use of it.

And that is it.

You can access the current Span by injecting it into your CDI bean.

@Inject
private Span currentSpan;

You can add attributes and events to the span using this instance. These attributes end up in your collector and events mark specific moments in the span.

You can also make use of Baggage Items to carry information to other parts of the requests. Although, you should not see this as a replacement for passing parameters to methods and other services that are called. For that reason, the Baggage Items are not propagated externally. However, by adding the W3CBaggagePropagator provided by the Otel Java implementation to the OpenTelemetry instance, this is possible.

To add something to a baggage item.

    Baggage.current()
            .toBuilder()
            .put("baggageItem", name)
            .build()
            .makeCurrent();

And to access it later on

Baggage.current().asMap();

Conclusion

The OpenTelemetry specification goal is to get insight into what your process is doing when processing requests from the users. Besides metrics and logging, an important part is tracing the requests through your entire environment. It is a language-agnostic specification so that information is compatible regardless of what language the processes are programmed in. But there are also implementations available for many languages, including Java.

This means that vendors or framework maintainers don’t need to do anything to get it integrated. And developers can just use the Java implementation if they need the functionality in their environment. There exists a Java Agent but also manual integration can be done very easily as showcased by the Jakarta EE 10 integration code available in the Github repo.

Atbash Training and Support

Do you need a specific training session on Jakarta or MicroProfile? Or do you need some help in getting up and running with your next project? 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 Core Profile JAX-RS

Run your Jakarta Application without Runtime

Java EE and now Jakarta EE have the packaging requirements that your application needs to be bundled in a WAR or EAR file and executed by your runtime.
Traditionally, that was the application server that was already configured and running and you deploy the WAR file, containing your application, to it.

These days, with an application runtime, you can launch the runtime and at the same time deploy and run the application by specifying the WAR file location at the command. This makes use of the executable JAR file functionality within Java.

An example of Payara Micro

java -jar payara-micro.jar /path/to/myapplication.war

But now with the addition of the Java SE Bootstrap API to JAX-RS 3.1, this might change. And maybe you don’t need a runtime anymore.

Java SE Bootstrap API

The idea of the Java SE Bootstrap API is that you can start the JAX-RS implementation from the public static void main method. Some of the implementations already had support for this in the past, but it is now available within the JAX-RS specification and thus useable with any certified implementation.

You might wonder how that this is possible without using a servlet container?

When your application or server has REST endpoints that can be called by the client (application), you indeed need to capture the HTTP request. Most of the time, this is done using a servlet container and a specific servlet was responsible to call the correct JAX-RS method depending on the URL.

But actually, you don’t need a servlet for that. Any piece of code that listens on a socket can perform this operation. You don’t need a servlet for this task.

There is even a simple HTTP server within the JDK itself, since Java SE 6, that can be used for this purpose. But also other libraries and products like Netty can be used.

REST without server

Now that you have an API to start your JAX-RS server from within your code, like from within your main method, you can have your application respond to user requests.

The following snippet shows what is needed to realise that.

   SeBootstrap.Configuration.Builder configBuilder = SeBootstrap.Configuration.builder();
   configBuilder.property(SeBootstrap.Configuration.PROTOCOL, "HTTP")
                .property(SeBootstrap.Configuration.HOST, "localhost")
                .property(SeBootstrap.Configuration.PORT, 8080);


   SeBootstrap.start(new DemoApplication(), configBuilder.build());

The DemoApplication class is the class that extends the JAX-RS Application class and provides all JAX-RS resource classes through the getClasses() method.

But you probably need more than just the JAX-RS support of Jakarta EE. What about CDI, JSON handling, etc …

Jersey has already an artefact where they integrate Weld, a CDI implementation that also can be started from pure Java SE since CDI 2.0 ‘Java EE 8, and the JSON support, JSON-P and JSON-P, by adding the Jersey media support modules for JSON.

So, you have already all the specifications that make up the Jakarta EE Core Profile, available without the need for any server. An example of such a project can be found in this example project.

Note that this option is different from the embedded server support some vendors provide. There is no specific glue code or additional functionality from the vendor in this case in action. Just some minimal linking between the different specifications.

Really, no server?

Yes, this is now possible and might be the right choice for your situation. It allows you to run your optimised combination of the specifications that you need for the application, right from your main method in Java. Similar to Spring Boot, Jakarta EE can now be used in a truly modular way and no longer require the potentially large set of specifications provided by the runtime that you don’t need.

But you might need to write some classes to better integrate some specification implementations beyond the ones of the Core Profile.

Atbash Runtime

And that is also the goal of the Atbash Runtime, a limited set of code to integrate the specifications seemingness but keep the modular aspect.

That is the reason for the addition of the JakartaRunner class that can be used to start your application from the main method. But at the same time use the module loader of Atbash Runtime so that all specification implementations that are on the classpath are integrated automatically, just like the case with Spring Boot.

It also adds a logging module on top so that you have already one concern less to make your application production worthy.

You can find an example of this approach in this project.

Conclusion

With the addition of the Java SE Bootstrap API to JAX-RS, it becomes now possible to create your own custom, modular runtime that can be started from the main method. This avoids the overhead of potentially many specifications and functionality from the runtime that are not needed for your case.

Atbash Runtime also supports this mode by providing an easy-to-use API that starts the module system of the product behind the scenes and seemingness integrates the different specifications that are found on the classpath.

Want to lean more about Jakarta EE 10 Core Profile?

This topic was discussed during my JakartaOne LiveStream event of 2022. Have a look at the presentation if you want to know more about the Core Profile “Explore the new Jakarta EE Core Profile“.

Atbash Training and Support

Do you need a specific training session on Jakarta or MicroProfile? Or do you need some help in getting up and running with your next project? 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 Core Profile Jakarta EE

CDI 4.0 Lite and Potential Pitfalls

The CDI Lite specification is specifically created for the new Jakarta EE 10 Core Profile. This lite version is created to allow the discovery of CDI bans and preparation of the CDI container at build time.

This blog goes a bit deeper into a potential problem that you can encounter when building Core profile applications and running them on a Jakarta runtime concerning this CDI 4.0 Lite.

CDI Lite

To populate the CDI container with all the beans and the metadata to create the beans on demand like for the RequestScoped context, the CDI code needs to perform some initialisation.

Until now, the only available option is to perform a scan of the classpath and find the classes eligible as a CDI bean. Another source for beans is the CDI Portable Extensions that can register additional beans programmatically by the runtime or the application itself.

In the last few years, there are many initiatives to reduce the startup time of applications in various ways. The scanning of the classpath is a process that can be moved to the build phase if you have all classes available at build time. As you know, the JVM allows additional classes and libraries are added at runtime that was not available at build time. So, in case you move the metadata and bean discovery to build time, you need to make sure all classes are known and available or you need to provide the info.

The CDI Lite specification introduced the BuildCompatibleExtension interface to have the ability to move the scanning to the build phase of your application. This mechanism works similarly to the CDI Portable Extensions, where you have the opportunity to execute some methods during one of the 5 phases of the process.

At the same time, some classes are marked as not relevant for CDI Lite, as they are not really useful for the applications that are built with the Core Profile. Examples are the SessionScope and ConversationScope since REST applications are typically stateless. Keeping session information is in this case not required.

One single API artefact

The underlying narrative for creating the CDI Lite solution makes sense, but the single API solution is less obvious.

CDI lite contains most of the classes of the previous version of CDI and a few additional ones, like the BuildCompatibleExtension interface.
CDI full comprises CDI lite and a few additional concepts like the SessionScoped annotation that were available from the previous version of CDI but which didn’t fit into the CDI lite concept.

But the CDI 4.0 API artefact contains all classes, those of CDI Lite and CDI full.

Your project has only the option to add this single CDI API dependency to your project, as provided since the runtime has already these classes. And when your application is compiled and built against this API, it might fail at runtime.

You as a developer could have used or referenced a class from the CDI Full specification but you use a Core Profile certified runtime. This runtime only needs to support the CDI Lite classes and is not required to implement the other ones of CDI Full. So the application you successfully build fails at runtime. And you didn’t get notified of this problem during build time.

Testing for CDI Full classes usage

For this reason, I have created a small library that can inform you if you made use of one of the CDI Full classes in your code. You can write a test based on this code that fails when you make use of such a class. This way you get warned upfront that it might not run in production.

To make use of this library, add the following dependency to your project

    <dependency>
        <groupId>be.atbash.jakarta</groupId>
        <artifactId>core-profile-tester</artifactId>
        <version>1.0.0</version>
        <scope>test</scope>
    </dependency>

With this dependency, you can write the following test method

@Test
void testCompliance() {
    TestCoreProfile tester = new TestCoreProfile("be.atbash");
    Assertions.assertThat(tester.violations()).isEmpty();
}

The TestCoreProfile can determine those classes in the package you specify as a parameter, and in sub-packages, where you make use of a CDI Full class. If the list is empty, you are safe and good to go running it on a Core profile implementation.

Instead of using your top-level package, you can also specify a package from one of the CDI libraries that you have added to your project. This will tell you if that CDI library is safe to use on a Core Profile product.

Conclusion

CDI Lite groups all concepts of the CDI specification that is supported on the new Jakarta EE Core Profile. It also allows gathering information for the CDI container at build time.
But there is only 1 single artefact, containing all CDI Lite and Full classes. This means that even if your application compiles and builds successfully, it might fail on a Core Profile product. This is because you used some CDI Full-only classes that are not supported in Core Profile.
With the Jakarta Core Tester, you can find out if you referenced one of the CDI Full classes and it will run safely on your runtime.

Want to lean more about Jakarta EE 10 Core Profile?

This topic was discussed during my JakartaOne LiveStream event of 2022. Have a look at the presentation if you want to know more about the Core Profile “Explore the new Jakarta EE Core Profile“.

Atbash Training and Support

Do you need a specific training session on Jakarta or MicroProfile? Or do you need some help in getting up and running with your next project? 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
Jakarta EE release Testing

Atbash Jakarta EE Integration Testing version 1.1 Released.

The first version of the integration testing framework was released in July of this year. It allowed you to deploy your application using the Jakarta Runtime of your choice to a Docker environment using the TestContainer framework.

Selecting the runtime is as easy as setting a member value of the test annotation, the runtime version can be specified, endpoints can be easily called based on a MicroProfile Rest Client interface definition and it allows to have remote debugging by just setting a flag.

In this version1.1, you have the option to define the Docker build file that will be used for the test, and features for testing microservices are added.

Custom builds

In the initial version, the official docker images of the Jakarta runtimes are used to run your application within the docker container. But in many cases, your application needs a specific image as it requires some additional content.

This can now be achieved by specifying a custom build file for Docker.

@ContainerIntegrationTest(runtime = SupportedRuntime.PAYARA_MICRO)
@CustomBuildFile(location = "custom/payara")
public class CustomPayaraIT extends AbstractContainerIntegrationTest {
}

The annotation defines that the content of the directory src/docker/custom/payara will be used to generate the Docker image that will be used to test your application. The build file is expected as a file called Dockerfile (if this is not present, the runtime default will be used) and all other files in that directory and subdirectories will be part of the build step. This allows you to have a fully customized Docker image for testing.

Of course, by defining the runtime like Payara Micro in the above example, the port assignment checks to see if the application is ready and debug setup is still taken from the indicated runtime. So make sure you specify the correct runtime in the @ContainerIntegrationTest annotation which corresponds to the system used within the custom Docker build file.

This functionality is especially useful when you are working with Glassfish since they don’t have any official Docker image and support was limited in the first release for this runtime.

Microservices Testing

In most cases, your application depends on other services. They are called to retrieve data for or process parts of the functionality required for the user request. There are 2 additions available in this version that makes it easier to test your application in this situation.

Each public static variable that is a startle test container and added with @Container is also started just before the execution of your test code. It is now easier in this version 1.1 when this additional container is running an application using one of the supported Jakarta runtimes. You only need to specify the docker image name and the setup like health checks and port mappings is taken care of for you automatically.

  @Container
  public static GenericContainer<?> remote = new PayaraMicroContainer(DockerImageName.parse("test-remote:1.0"));

Also, networking configuration is taken care of, as it will share the same network as your application and this container will also have the name of the variable ‘remote’ in this case, as a hostname alias.

This makes it easy to add an external service needed for your application.

But instead of having an entire application providing data for your application, you can also configure the responses for URLs. In other words, you can mock the responses for certain requests for external services. For this purpose, Wiremock functionality is integrated into the framework.

First of all, you define a container that will be running the WireMock application where you also define the hostname which will be used.

  @Container
  public static final WireMockContainer wireMockContainer = WireMockContainer.forHost("wire");

And within each test method, you can define the responses using a builder pattern

  MappingBuilder mappingBuilder = new MappingBuilder()
   .forURL("/path")
   .withBody(foo);

  String mappingId = wireMockContainer.configureResponse(mappingBuilder);

The variable foo can be a String and in that case, the response is a plain text response with the content of the variable as the body. Otherwise, the variable is serialised to JSON and a JSON-type response is prepared.

The builder also has some other methods to control the response like the HTTP status, media type, etc …

Integration testing

With the initial release, you had all the features required to test your application with the Jakarta runtime of your choice using Testcontainers and a docker environment.

In this update, the container running your application under test can now be fully customised using a build file and resources that you specify by indicating the directory where they can be found.

Also, testing applications that are part of a microservices environment got easier. When the eternal service is also a Jakarta application, you only need to indicate its docker image name, and all other configuration is taken care of for you by default.

You can also use Wiremock to define predefined responses for certain requests. Again, the network setup is greatly simplified, and defining responses is easy. JSON responses can be specified by providing the data as a Java Object that will be serialised so that you don’t need to write complex JSON strings.

Atbash Training and Support

Do you need a specific training session on Jakarta or MicroProfile? Or do you need some help in getting up and running with your next project? 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 Configuration

A MicroProfile Config implementation for plain Java SE

The ability to define configuration values for your application outside the deployment artifact is very important. It is one of the 12-factor items, the requirement that your application can be unaltered deployed on test, acceptance, production, and so on.

Many framework and runtimes have their proprietary solution and there were already several attempts to create a specification within the Java Enterprise world.
Currently, there is an effort going on to define Jakarta Config which is based on the MicroProfile Config specification.

Although MicroProfile Config specification is built on top of CDI concepts, the fundamentals can be used in plain Java SE. Also, other implementations, like SmallRye Config can be used in Java SE without the need for CDI to be present.

Extraction from Atbash Runtime

The goal of Atbash Runtime was to have a modular runtime that supports the specifications of the Jakarta EE 10 core profile. The development of this runtime started before the release of the Core profile so it was based on the Jakarta EE 9.1 specifications and used MicroProfile Config as the basis for the future to finish Jakarta Config specification.

Atbash Runtime version 0.3 already contained an implementation of the config specification and passed the MP Config TCK.

Recent experimentations with the Atbash JWT module on plain Java SE confirmed the need for an MP Config implementation that runs on pure Java SE. Since the implementation within the Atbash was already nicely separated into different packages, the new library was quickly ready.

Using Atbash MP Configuration SE

Before you can use the configuration values, you need to add the following artifact to your project.

    <dependency>
        <groupId>be.atbash</groupId>
        <artifactId>mp-config</artifactId>
        <version>1.0.1</version>
    </dependency>

This dependency brings in all required dependencies using the transitive functionality of Maven, including the MicroProfile Config 3.0 API.

Now you can retrieve a Config instance programmatically and retrieve the values just as described in the specification.

    Config config = ConfigProvider.getConfig();
    String value = config.getValue("value", String.class);

All functionality that doesn’t require CDI is supported, including

  • ConfigSources, the 3 default implementations with their default ordinal values and the possibility to define custom ones through the ServiceLoader mechanism.
  • Custom ConfigSourceProvider‘s can be loaded through the ServiceLoader mechanism.
  • Converter, the implicitly defined one as specified in the specification and the possibility to define custom converters using the ServiceLoader mechanism.
  • Support for optional values
  • Support for expressions where a value is a result of combining other configuration values and constant expressions.
  • Support for Config Profile defining the application phase (dev, test, …) on the property and ConfigSource level.
  • Support for ConfigBuilder and creating custom Config instances.

Since MicroProfile Config 3.0 is using the Jakarta namespace, you make use of the @Priority within the jakarta package to define the order in the converter list if you define a custom one.

 import jakarta.annotation.Priority;

Information about library

The code is compiled with JDK 11 source compatibility, and is thus useable in that or any higher version.

The library and all dependencies, including the MicroProfile MP Config API code take about 240 kB. Logging is performed through the SLF4J library, and thus a specific binding is required if you want to see the log.

The library can also be used in a GraalVM native image. No additional configuration is required to be able to include it as native compiled Java code.

Use case

There are several use cases where this new library can be useful.

  • A plain Java SE program where some configuration values are needed. By adding the dependency, you have the MicroProfile Config functionality available through that small compact library.
  • Use it in a Jakarta runtime that doesn’t support any configuration framework for your application. An example is Glassfish, including the upcoming version 7, where no configuration specification is available for your application.

Conclusion

A version of the MicroProfile Config API that runs on Java SE only can be useful in several cases. Not only for Java SE applications themselves but also for runtimes like Glassfish that still don’t support any configuration possibilities for the deployed applications. And config is essential for writing good enterprise applications.

The Atbash MP Config SE was extracted from the Atbash Runtime that has an implementation of this specification as part of the experimentations around the Jakarta EE Core profile.

Better name

I also need a better name for this new library So if you have any ideas, let me know on Twitter or use the feedback form on the Training page. From the suggestion, I will pick one at the end of October 2022.

Update november 2022: The chosen name is Atbash Delivery. It delivers the configuration from your environment to your application.

Atbash Training and Support

Do you need a specific training session on Jakarta or MicroProfile? Or do you need some help in getting up and running with your next project? 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 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
Jakarta EE Security

Where is the Security Specification in Jakarta EE Core profile?

The Jakarta EE Core profile targets the smaller runtimes, those that focus on delivering support for applications with REST endpoints only. For that reason, the main specifications included in the profile are the JAX-RS specifications and the specifications around JSON, JSON-P and JSON-B.

Another very important specification was targeted for Jakarta EE 10 and this new core profile, Jakarta config. The discussion about it is still going on. It is thus not included yet. That is the reason why the Atbash Runtime includes an implementation of the MicroProfile Config specification for the moment.

But there is another very important aspect that seems to be forgotten for this core profile, security.

Jakarta Security specification

For the moment, there are no plans to include a security-related specification in this core profile and this is a missed opportunity. Security is a very important aspect of each application but as usual, it doesn’t receive enough attention. Although there were several major security issue events in the last 6 months, we all remember the log4shell vulnerability.

Within the Jakarta family, we have the Jakarta Security API specification which combines the more low-level specifications Authentication and Authorisation. It also makes it easier for the developer to define the requirements without relying on the runtime to perform the setup. Within cloud environments, we should be able to start our application without extensive setup of the server or runtime.

But this Security API specification is not really a good candidate to be included in the Core profile. First of all, it depends on many other specifications and some of them are archaic and not really adapted to be used in these small runtimes targeted to the cloud.

But most of all, there is no support for the token-based security that is typically used in microservices and the applications that stands as a model for these Core profile runtimes.

The JSON Web Tokens (JWS token specification) are an ideal means to carry the information about the user on the requests. Within the header, a cryptographically signed JSON carries the information about the identity and the permissions of the user who made the (initial) call to the environment. With the signature, we can be sure the content is not tampered with and we can make use of the groups and role information available in the token to determine if the user is allowed to perform the action.

And we only need to use the public key of the key pair to verify the signature. This public key can be kept cached and only occasionally refreshed from the process that creates those JWT tokens. The verification and the usage of the JWT tokens do not require calls to external systems and are ideal to implement performant systems.

MicroProfile Security specification

This is a major gap in the support of technologies for Jakarta EE that calls itself ‘Cloud-native Enterprise Java’. But also within MicroProfile, there is no adequate support for JWT tokens. You have the MicroProfile JWT Auth specification that defines functionality for the MicroProfile runtimes that are using JWT tokens.

But there are several restrictions on top of the JOSE (Javascript Object Signing and Encryption) specification that make the MicroProfile specification less useful. The configuration is defined so that an application can only be used by one token emitter. You can define only one issuer, only one signature algorithm, you can indicate that a JWS or JWE token is used but not both at the same time, etc.

This makes that applications that make use of the MicroProfile JWT Auth specification are in fact part of a distributed monolith. You cannot use it in a real microservices situation as it will be called by many different applications, including external systems using different token providers.

Side note, since the majority of the companies that claim to do microservices are actually just building a distributed monolith, the problem with the MicroProfile JWT Auth specification is not impacting the majority I guess.

Security in Atbash Runtime

Since security is an important and vital aspect of any application, the upcoming version of the Atbash runtime will have support for JWT tokens. It is based on the JOSE specifications and for convenience, is using the MicroProfile JWT Auth API but not having the many restrictions of the MicroProfile Specification.

The configuration parameters are interpreted slightly differently, like the key defining the issues is interpreted as a list. This still allows the developer to only allow tokens from one source, but also allows the application to be used in real microservices situations and accept multiple issuers.

A first draft of the implementation is included in the main branch of the GitHub repository and will be refined in the coming weeks before the release is made.

Conclusion

Although security is a very important aspect of each application, specifications, and products should help the developers to implement the security requirements they have. There is no Security specification included, nor is there one planned in the new upcoming Core profile of Jakarta EE.

In fact, Jakarta EE does not have a specification that is useful in cloud-native environments since there is no support for JWT tokens.

But also the MicroProfile security specification is not a solution in all cases since it restricts the tokens to one issuer. Making it only useable in a distributed monolith situation and not in a real large-scale microservices environment.

The JWT token implementation within Atbash Runtime is based on the API of MicroProfile JWT Auth but overcomes the limitations of the MicroProfile specification by supporting the configuration of multiple sources, multiple algorithms, and using JWT and JWE tokens at the same time.
Sounds good? Give it a try when the next version will be available in a few weeks.

This website uses cookies. By continuing to use this site, you accept our use of cookies.  Learn more