Representational State Transfer (REST) is part of Web Service Technology that see data and functionality as representations of resources and can be accessed using Unified Resource Identifiers (URIs) or in more general term is links on the web. REST quickly gain it’s popularity with many Tech Company start to adopted micro services architectural in their Product or Project. Micro service is structuring the application as a set of loosely coupled, collaborating services. Every service can be implemented using any programming languages as long it’s provided communication method between the service and REST is mostly used because it’s simplicity.

Java EE is fairly known as the oldest programming language used for building an enterprise application, and so far that I know is Java EE (especially Java EE 6 upward) already supported in build RESTful of course using JAX-RS. I will show you how easy and fun to build REST server side with Java EE 7, and before we started write some code I need to give you the minimal requirements:

Environment Setup

First and the most important is make sure you already installed Java Development Kit (JDK) and setting the PATH environment, because this is the basic requirement in develop Java application. I’m using Apache Maven as the build tools and dependency management. Talked about dependency you will just use Java EE 7 API in your pom.xml and can easily created with Java EE 7 Essentials Archetype that provided by Adam Bien.

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0</version>
    <scope>provided</scope>
</dependency>

Finally, Wildfly is the Application Server that will be used and for the sake of this tutorial I encourage you to following the same setup unless you already familiar with Java EE environment, but I need to remind you that you need full Application Server and not Web Container such as Tomcat or Jetty. We will used all Java EE API like: EJB, CDI, JPA, and Servlet. Application Server like: Payara, TomEE, or Websphere Liberty is recomended.

Let’s Dirty Your Hands with Some Code

What we will build is a simple guest book application, just like it’s name this application should be able to saved the identity of the user (which is his/her name) and the time he/she wrote their name.

Build Entity Class with Java Persistence API (JPA)

Have requirement to stored data into database we could use JPA as Object Relational Mapping (ORM) and of course we need to create an entity class for guest book.

@Entity
@Table(name = "guest_book")
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@NamedQuery(name = GuestBook.FIND_ALL, query = "select g from GuestBook g")
public class GuestBook {

    public static final String FIND_ALL = "findAll";

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @XmlTransient
    private Long id;
    private String name;
    @Temporal(TemporalType.TIMESTAMP)
    private Date created;
}

The entity class not only use JPA annotations, but also included JAX-WS annotations so we don’t need to create Data Transfer Object (DTO) just use the entity. Why use JAX-WS annotations? Did I said that we will use JAX-RS in order build REST? Yeah I know, but currently Java EE 7 still not fully adopted JSON related (the good news is it will be fully adopted in Java EE 8), but don’t worry since it’s worked very well. The best part of JAX-WS annotations that we used is it will automatically produces XML files when transfer our entity class as resources without a getter setter method, and we can chose which variable that should not exposed for example the id.

I did mention we don’t need to made DTO because we will used json object and for a simple example we can created method in our entity class to convert it into json.

public JsonObject toJson() {
    return Json.createObjectBuilder()
            .add("name", this.name)
            .add("created", this.created.toString())
            .build();
}

Configure JAX-RS

Before you can really used JAX-RS you need to created a JAX-RS configuration and it’s just look like this:

@ApplicationPath("resources")
public class JAXRSConfiguration extends Application {
    // nothing to configure here
}

Just with that class, now you can focus on business logic of the application, Java EE is convention over configuration and as Adam Bien stated using Java EE is like 70%-80% our work done, we just need to completed it with the business logic of the application.

Business Logic Code

Every time you build an application always paid more attention on separation of concerns, each class does it’s own job and believe me it will saved your life in the future. In this application you will create business logic class (which focused on complex business logic and database) and resources class (which focused on REST).

Business logic class will have more interaction with persistence class and because of that it’s a wise decision to give EJB annotations on business logic class for a better monitoring, transactions, and injecting.

@Stateless
public class Message {
    @PersistenceContext(name = "GuestBookPU")
    EntityManager em;

    public List<GuestBook> findAll() {
        return this.em.createNamedQuery(GuestBook.FIND_ALL).getResultList();
    }

    public GuestBook findById(Long id) {
        return this.em.find(GuestBook.class, id);
    }

    public void create(GuestBook guestBook) {
        this.em.persist(guestBook);
    }

    public void remove(GuestBook guestBook) {
        this.em.remove(guestBook);
    }
}

For the sake of simplicity, in this tutorial you just need to used H2 database to stored the data, Wildfly already provided H2 datasources so you don’t need to configure anything on the Application Server. Created a persistence.xml files on folder: /resources/META-INF.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="GuestBookPU" transaction-type="JTA">
        <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
        <properties>
            <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
        </properties>
    </persistence-unit>
</persistence>

This is your resources class

@Stateless
@Path("messages")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public class MessageResources {

    @Inject
    Message message;

    @GET
    public JsonArray findAll() {
        JsonArrayBuilder list = Json.createArrayBuilder();
        List<GuestBook> all = this.message.findAll();
        all.stream().map(m -> m.toJson().forEach(list::add);
        return list.build();
    }

    @GET
    @Path("{id}")
    public JsonObject findById(@PathParam("id") Long id) {
        GuestBook guestBook = this.message.findById(id);
        return guestBook.toJson();
    }

    @POST
    public Response save(@Valid GuestBook guestBook) {
        this.message.create(guestBook);
        return Response.ok().build();
    }
}

JAX-RS can produces and consumes both of xml and json and many more, you just need to define the MediaType on produces and consumes annotations. Beware, the sequence of MediaType is important, when you put MediaType.APPLICATION_XML at the first order then your API will produces or consumes xml files as the default. In order to consumes or produces json, you need to put both Accept: application/json and Content-Type: application/json in your http header request (apply for another MediaType that you define on the produces and consumes annotations).

With this your application is done, build your application using command line mvn clean install and deploy it into Wildfly. Notes, since the database it’s still empty you need to stored some data and I will show you using curl (of course you need a curl) or you can used application like postman or advanced rest client, in this tutorial I give example using curl and then execute command bellow in you command line terminal:

curl -i -H "Content-Type: application/json" -X POST -d '{"name": "sukma", "created":"2017-03-10"}' http://localhost:8080/guestbook/resources/messages

Then, you can retrieve your data with command:

curl -i -H "Content-Type: application/json" http://localhost:8080/guestbook/resources/messages

Then you will get your response like this:

{
    "name": "sukma",
    "created": "2017-03-10 07:00:00.0",
}

REST as in Hypermedia

Actually, REST have some level of maturity and the highest level of the maturity of REST is Hypermedia as the Engine of Application State (HATEOAS). To simplified, REST is not only give a resources but also Media Type and the links relations. The resources of a HATEOAS REST will be like:

{
    "name": "sukma",
    "created": "2017-03-10 07:00:00.0",
    "_links":{
        "rel": "self",
        "href": "http://localhost:8080/guestbook/resources/messages/1"
    }
}

Of course this can be done use Java EE 7, you just need to refactor toJson method in entity class and with a little help of UriInfo you can build the link relations, first refactor you toJson method like this:

public JsonObject toJson(URI self) {
    return Json.createObjectBuilder()
            .add("name", this.name)
            .add("created", this.created.toString())
            .add("_links", Json.createObjectBuilder()
                    .add("rel", "self")
                    .add("href", self.toString())
            )
            .build();
}

UriInfo is part of Java EE API which is very convenient to build link relations, since it you can get your base path, analyze your resources class path and even your method class path. To avoid repeated UriInfo code you can build a resources URIs builder.

public class ResourceUriBuilder {

    public URI createResourceUri(Class<?> resourcesClass, UriInfo uriInfo) {
        return uriInfo.getBaseUriBuilder().path(resourcesClass).build();
    }

    public URI createResourceUri(Class<?> resourcesClass, String method, long id, UriInfo uriInfo) {
        return uriInfo.getBaseUriBuilder().path(resourcesClass).path(resourcesClass, method).build(id);
    }
}

Then refactor your MessageResource Class become like this:

....
@Inject
ResourceUriBuilder resourceUriBuilder;

@Context
UriInfo uriInfo;

@GET
public JsonArray findAll() {
    JsonArrayBuilder list = Json.createArrayBuilder();
    List<GuestBook> all = this.message.findAll();
    all.stream()
            .map(m -> m.toJson(
                    resourceUriBuilder.createResourceUri(
                            MessageResources.class,
                            "findById",
                            m.getId(),
                            uriInfo
                            )
                    )
            )
            .forEach(list::add);
    return list.build();
}
.....

In the end your response will be look like this:

[
    {
        "name": "sukma",
        "created": "2017-03-10 07:00:00.0",
        "_links": {
            "rel": "self",
            "href": "http://localhost:8080/guestbook/resources/messages/1"
        }
    },
    {
        "name": "james",
        "created": "2017-03-10 07:00:00.0",
        "_links": {
            "rel": "self",
            "href": "http://localhost:8080/guestbook/resources/messages/2"
        }
    }
]

With this your REST application is done, the completed source code is on github and I welcome any discussion or guidance.

References: