In September, we looked at MicroProfile, an initiative to create a baseline platform definition that optimises Java EE for a microservices architecture. It is a collaboration between Red Hat, IBM, Tomitribe, Payara, the London Java Community and more, with different implementations from different groups (see MicroProfile 1.0: What developers want).

This is a quick glance at setting up a MicroProfile project using WildFly Swarm. For the code examples, see the Voxxed Github.

Generate the project

Luckily for us we can ‘Rightsize your Java EE microservice in a few clicks’ by going to http://wildfly-swarm.io/generator/. It is incredibly easy to get started, and there is a great existing tutorial.

Type ‘MicroProfile’ into the Dependencies:

microprofile setup

As the initial planned baseline is JAX-RS + CDI + JSON-P, we have access to these libraries. This gives us dependency injection, and an API for RESTful Web Services with JSON-P enabled.

Unzip JEC-demo.zip and open in an IDE. In the terminal, run

mvn package

then

cd  /target

java -jar demo-swarm.jar

In the logging you should see the line:

2017-01-23 11:31:33,286 INFO [org.wildfly.swarm] (main) WFSWARM99999: WildFly Swarm is Ready

 

Go to http://localhost:8080/hello to see “Hello from WildFly Swarm!”.

Utilising JAX-RS

JAX-RS is the Java API for RESTful Web Services. It has a number of runtime annotations to define resources and actions that can be performed on the resources. In HelloWorldEndpoint.java, we can see the example:

@Path("/hello")
public class HelloWorldEndpoint {

	@GET
	@Produces("text/plain")
	public Response doGet() {
		return Response.ok("Hello from WildFly Swarm!").build();
	}
}

Let’s say we want a ‘To Do’ application, with a different list per day, e.g. some site like www.todo-app.com/my-routine/Monday. To display the day, we can use @PathParam to extract the day from the URL. For example add a class MyRoutineEndpoint.java:

@Path("/my-routine/{input}")
public class MyRoutineEndpoint {

    @GET
    @Produces("text/plain")
    public Response doGet(@PathParam("weekday") String weekday) { 
        return Response.ok("Tasks for " + weekday).build(); 
    }
}

Then, restarting WildFly Swarm and going to http://localhost:8080/my-routine/Monday we can see:

Monday screen shot

It is just as easy to do a POST, e.g. add to MyRoutineEndpoint.java:

    @POST
    @Consumes("text/plain")
    public Response doPost(String task) {
        //Save to task database
        return Response.ok("Todo :" + task).build();
    }

 

Using Chrome and the Advanced REST client app we can test this:

POST request

CDI

CDI provides dependency injection, contexts (stateful components, e.g. beans, can be bound to lifecycle contexts, such as a single HTTP request) and more. See the Simple Greeting Tutorial provided by Oracle.

To enable CDI, add an empty file beans.xml to the META-INF folder.

Create a TaskDeadline bean:

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.RequestScoped;
import javax.ws.rs.Produces;
import java.time.LocalDateTime;

@RequestScoped
public class TaskDeadline {

    public LocalDateTime twoHoursFromNow() {
        return LocalDateTime.now().plusHours(2);
    }
}

Then a Task bean that will be created once per request:

import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import java.time.LocalDateTime;

@RequestScoped
public class Task {

    @Inject
    TaskDeadline taskDeadline;

    private String taskTitle;
    private LocalDateTime deadline;

    @PostConstruct
    public void setTaskDeadline() {
        this.deadline = taskDeadline.twoHoursFromNow();
    }

    public void setTaskTitle(String taskTitle) {
        this.taskTitle = taskTitle;
    }

    @Override
    public String toString() {
        String deadlineStr = deadline.toString();
        return taskTitle + ", deadline: " + deadlineStr;
    }

    public String getTaskTitle() {
        return taskTitle;
    }
    public LocalDateTime getDeadline() {
        return deadline;
    }
}

Then, we need to inject the Task into the MyRoutineEndpoint by adding the bean, and amending doPost(...):


    @Inject
    Task task;

    @POST
    @Consumes("text/plain")
    public Response doPost(String taskTitle) {
        task.setTaskTitle(taskTitle);
        //Save to task database
        return Response.ok("Todo: " + task.toString()).build();
    }

Using the Advanced REST client again, we can test this by sending a request to http://localhost:8080/my-routine/monday:

Task with deadline

JSON-P

Now to make use of the JSON, we can use the JsonBuilderFactory to convert our response into JSON. Adding the JsonBuilderFactory to MyRoutineEndpoint, and amending doPost(…) again:

    private static final JsonBuilderFactory jsonFactory = Json.createBuilderFactory(null);

    @POST
    @Consumes("text/plain")
    public Response doPost(String taskTitle) {
        task.setTaskTitle(taskTitle);

        JsonObject json = jsonFactory.createObjectBuilder()
                .add("task", jsonFactory.createObjectBuilder()
                        .add("title", task.getTaskTitle())
                )
                .add("deadline", jsonFactory.createObjectBuilder()
                        .add("hour", task.getDeadline().getHour())
                        .add("minutes", task.getDeadline().getMinute())
                        .add("seconds", task.getDeadline().getSecond())
                )
                .build();
        return Response.ok(json, MediaType.APPLICATION_JSON).build();
    }

We can test this using the Advanced REST client again: again sending a request to http://localhost:8080/my-routine/monday with payload “Complete WildFly Swarm app”:

json response

Further resources

For more on WildFly Swarm, see the User’s Guide.

For more on MicroProfile see MicroProfile.io.

More on CDI.

For a more in-depth look, see Microservices using WildFly Swarm, Docker and Couchbase or WildFly Swarm: Building Microservices with Java EE by Arun Gupta.