Getting Started with Eclipse MicroProfile, Part 1: the Application
Sunday, October 14, 2018 |To start our investigation, we need an application to work with. Part of the problem with getting started applications is making sure that your example is complicated enough to be interesting, but not so complicated that the greater message is lost in the details of the app. MicroProfile 2.0 is made up of a number of components:
-
MicroProfile Config 1.3
-
MicroProfile Fault Tolerance 1.1
-
MicroProfile Health Check 1.0
-
MicroProfile JWT Authentication 1.1
-
MicroProfile Metrics 1.1
-
MicroProfile OpenAPI 1.0
-
MicroProfile OpenTracing 1.1
-
MicroProfile Rest Client 1.1
-
CDI 2.0
-
Common Annotations 1.3
-
JAX-RS 2.1
-
JSON-B 1.0
-
JSON-P 1.1
To include all of those in this would probably be a bit too much technical weight for a getting started effort, so, for this example, I’ve leaned (probably too far) toward simple. Our application will have a single JAX-RS resource, into which is injected a single CDI bean. The point is to have a working REST endpoint, with an inject "service layer", to show a MicroProfile in action, allowing us to verify that our basic environment is configured and working correctly. From there you are free to load on all the complexity you find you need. That’s exactly what I’ll be doing in a separate project. :)
I may be covering far too basic a level, but I want to make sure I don’t leave too many behind, so let’s start at the very
beginning: the JAX-RS Application
:
1
2
3
4
5
6
7
8
9
10
@ApplicationScoped
@ApplicationPath("/")
public class MicroProfileApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> set = new HashSet<>();
set.add(HelloWorldResource.class);
return Collections.unmodifiableSet(set);
}
}
As you may know, when a JAX-RS-enabled container starts, by default it scans the classpath looking for instances of
Application
(there are, of course, other deployment options). Here, we define the application, using @ApplicationPath
to specify that we want our REST application to answer at the context root of application. As far as JAX-RS goes, that’s
all we need. However, some of the MicroProfile implementations are heavily CDI-based, and at least one of them (Helidon),
appears to be configured (by default) only to expose as CDI beans those classes that have certain annotations, thus we
have @ApplicationScoped
on this class as well. I’ll discuss that more later.
Next, we need a JAX-RS resource, so we create this:
1
2
3
4
5
6
7
8
9
10
11
12
@RequestScoped
@Path("/")
@Produces(MediaType.TEXT_PLAIN)
public class HelloWorldResource {
@Inject
private HelloWorldService service;
@GET
public String sayHello(@QueryParam("name") @DefaultValue("world") String name) {
return service.sayHello(name);
}
}
Again, the @Path
annotation should be enough, but we also provide @RequestScoped
to satisfy the CDI containers. As
any good REST service should, in my opinion, we delegate the work to a service that we inject using @Inject
. In our
resource method, we simply pull the values we need off the request (allowing JAX-RS to provide a default if the request
doesn’t specify a value), pass that to the service, the return the response. Nothing exciting here. Will the service be
more interesting? No. No it will not:
1
2
3
4
5
6
@RequestScoped
public class HelloWorldService {
public String sayHello(String name) {
return "Hello, " + name;
}
}
Not a single thing of interest here is there?
There is one last thing we need to take care of, and that’s marking this archive as a CDI bean archive. We do that by
creating a file at src/main/resource/META-INF/beans.xml
that can be completely empty if you prefer. We have nothing
special to declare, so that’s what we’ll do.
Finally, let’s take a look at a portion of the POM file. For this module to compile, there are really only two relevant entries:
1
2
3
4
5
6
7
8
9
<properties>
<version.javaee>8.0</version.javaee>
</properties>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>${version.javaee}</version>
<scope>provided</scope>
</dependency>
As I noted in the introduction, our main interest is in how to deploy this using one of several MicroProfile implementations, so the application is intensely underwhelming. In Part 2, we’ll start looking at deploying using Payara Micro, so stick around for that.