Implementing a REST interface for a Java Microservice – CM003

by | Nov 30, 2016




DeegeU Java Course

The “Implementing a REST interface for a Java Microservice” video is part of a larger online tutorial about creating microservices in Java. You can find more information about this class on “Creating microservices in Java“.

Transcript – Implementing a REST interface for a Java Microservice

Hi, in this tutorial we’re going to start implementing our microservice. For this video, that means we’re going to add the Java code for the classes we defined in the last video.

Since there aren’t too many classes, our plan for this video is to just go over the code for every class.

This is the fourth video in a larger playlist for creating microservices in Java. You can find the link for the full playlist in the text below.

Creating the Java model classes

To start with, let’s create a class that represents our trivia question. We decided in the last video our trivia question should have, the question, four possible answers, the correct answer, a hint, an identifier and a date the question was last modified. The last modified date will let us take advantage of caching.

final public class TriviaQuestion {
    final private long id;
    final private String question;
    final private String answerA;
    final private String answerB;
    final private String answerC;
    final private String answerD;
    final private String correctAnswer;
    final private String hint;
    final private Date lastUpdated;

    TriviaQuestion(long id, String question, 
            String answerA, String answerB, String answerC, String answerD,
            String correctAnswer, String hint, Date lastUpdated) {
        this.id = id;
        this.question = question;
        this.answerA = answerA;
        this.answerB = answerB;
        this.answerC = answerC;
        this.answerD = answerD;
        this.correctAnswer = correctAnswer;
        this.hint = hint;
        this.lastUpdated = new Date(lastUpdated.getTime());
    }
}

This object should be immutable, so we’ll make sure nothing is editable by marking everything final.

We’ll also make sure everything is defined in the constructor, and we’ll only provide getters.

Next I’ll just mention we created a builder for this class. It doesn’t do anything too interesting. We feed it values, and the builder returns us an instance of our TriviaQuestion class. The important task is you can’t create a TriviaQuestion without defining all the values. The build method returns an instance of TriviaQuestion.

Every setter in the builder, sets a value and returns a builder. The complete source code is on GitHub, and each of the setters follow the same form as these two.

Creating the Java data access classes

For now we want to use a simple array to hold our trivia questions, but in the future we’ll want to move this to a database. To make our lives easier in later videos, we’ll create an interface called TriviaQuestionAccessible that represents access to our data. This way when we need to swap the array for a real database, the amount of code we need to change is minimal. Interfaces are a great way to decouple classes.

public interface TriviaQuestionAccessible {

    TriviaQuestion getQuestionByIndex(long index);
    
    TriviaQuestion getQuestionById(long id);
    
    TriviaQuestion getRandomQuestion();
    
    List<TriviaQuestion> getQuestionList(long offset);

    List<TriviaQuestion> getSpecifiedQuestionList(long... id);

    long getQuestionListSize();
}

Then we’ll create a TriviaQuestionArrayAccess class. This is our array implementation of TriviaQuestionAccessible. We’ll also add a method to load our data. We’re using the builder to add trivia questions to our array.

getQuestionByIndex will return one particular question by the index provided. This is by index, not id.

If we need it by id, we have getQuestionById. This looks at the identifier for the question, and returns the matching question.

getRandomQuestion will return one question at random. We don’t know which one it will be, but that’s the idea.

If we need to get a list of questions, we have the getQuestionList. This method will only return a list of 10 questions max. The reason is, if someone calls our microservice and asks for all the questions, that could tie our service up for a long time while it prepares the response. It’s better to return a few quickly, and then let them ask for the next set. We’ll do this by offering an offset as a parameter. If we pass 0, we’ll get the first ten questions. If we pass 11, we’ll get the next 10 questions starting at the index 11.

We might already know the questions we want to ask. For example, imagine a trivia round where multiple players are all getting the same questions. We’d want to return a list of questions, predetermined by the system. For that we will create getSpecifiedQuestionList. This takes a list of ids, and returns them in a list. This isn’t the fastest or most efficient implementation, but we’ll improve it when we move to a database.

In order for the clients to know how many times they need to call for questions, we need to tell them how many questions are in the list. We’ll give them a method that returns the number of trivia questions in our database. At this point we have data objects and a way to get to the data. Next we need to add endpoints to access the data from outside our microservice.

Creating the Java REST endpoints using JAX-RS

We’re going to return JSON using REST. JSON has plusses and minuses, but it’s a good general solution for communication since almost any client will be able to understand our data. In fact, if you’re following along on the Swift videos, we’ve already seen how to get JSON data from a REST endpoint for iOS devices. We’ll create REST endpoints using JAX-RS to access our microservice.

We’ll first create the application class. This is TriviaApp. This class doesn’t have much functionality. You can consider it like a main method. This is where Wildfly Swarm enters our code. We define the application path here. The application path is the starting path for our API. This class extends the JAX-RS Application class.

@ApplicationPath("/trivia")
@Path("")
public class TriviaApp extends Application {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getDirectory(@Context UriInfo uri) {
        Link selfLink = Link.fromUri(uri.getBaseUri())
                .rel("self").type(MediaType.APPLICATION_JSON)
                .build();
        Link questionsLink = Link.fromUri(uri.getBaseUri() + "questions")
                .rel("questions").type(MediaType.APPLICATION_JSON)
                .build();

        return Response.ok()
                .lastModified(new Date())
                .location(uri.getRequestUri())
                .links(selfLink, questionsLink)
                .build();
    }
}

We’ll also return our directory from here. It produces JSON data for GET requests. Our getDirectory method builds two links to return to the caller. The links inform the caller what services are available. We’ll return self, which is just a pointer to what URL produced this response, and a questions link.

The reason we’re doing this is we want some other system to reach our API though one published endpoint. That endpoint is “/trivia”. From there, a system should be able to discover how to navigate our API programmatically. The link for questions will take them to the questions endpoint.

We don’t have a HTTP body to return for this endpoint, but we will return status code OK, the links, and a last modified date. In the future, we’ll change that date to match the date our code was created. This will help clients cache responses.

Finally we’ll create 3 endpoints for the questions in our trivia question resource. The starting path for all of these will be /questions. The constant STARTING_OFFSET represents the value for the first trivia question, 0. It’s there mostly to avoid hard coding the constant, and it makes the code a bit more readable. The PAGE_SIZE constant defines how many questions are returned per request. We’re going with 10, but if we find that’s too small or big, we can change it later.

This endpoint will return the complete list of questions, 10 at a time. We don’t want to return all the questions in one go, because it can create a bottleneck in our system. What if we have millions of questions. If the system is spending too much time responding to one very long request, other users can’t access the system. We’ll provide links for the system to navigate to other pages of our data, like next and prev. Finally we’ll build and return the JSON response.

We’ll create a endpoint for getting the total count of questions. This will be the /count path under the /questions path. We’re returning the number of questions in the message body, and as a header variable.

We also need to get a particular question by it’s identifier, or a random question. If an id number is provided, we’ll assume the request is for a particular question. If the path “/random” is provided, we’ll return a random question.

Conclusion

And that wraps up the code. If you see anything confusing, or anything that could be improved let me know. Now that we have the basic functionality, we’ll need to look at making sure it works as intended with unit tests.

Thanks for watching the video. You can find the source code and the complete transcripts on DeegeU.com. Next we’ll take a look at testing our Trivia microservice. If you like what you’re seeing or have any questions, let me know in the comments or on DeegeU.com! Please like and share, and I’ll see you in the next tutorial!




Related Posts

Tools Used

  • Java
  • NetBeans
  • JAX-RS
  • Wildfly Swarm

Media Credits

All media created and owned by DJ Spiess unless listed below.

  • No infringement intended

Music:
Rhastafarian by Audionautix is licensed under a Creative Commons Attribution license (https://creativecommons.org/licenses/by/4.0/)
Artist: http://audionautix.com/

Mandeville by Kevin MacLeod is licensed under a Creative Commons Attribution license (https://creativecommons.org/licenses/by/4.0/)
Source: http://incompetech.com/music/royalty-free/index.html?isrc=USUAN1100809
Artist: http://incompetech.com/

Get the code

The source code for “Implementing a REST interface for a Java Microservice” can be found on Github. If you have Git installed on your system, you can clone the repository by issuing the following command:

 git clone https://github.com/deege/deegeu-quizzer.git

Go to the Support > Getting the Code page for more help.

If you find any errors in the code, feel free to let me know or issue a pull request in Git.

Don't miss another video!

New videos come out every week. Make sure you subscribe!

Comments

comments

DJ Spiess

DJ Spiess

Your personal instructor

My name is DJ Spiess and I'm a developer with a Masters degree in Computer Science working in Colorado, USA. I primarily work with Java server applications. I started programming as a kid in the 1980s, and I've programmed professionally since 1996. My main focus are REST APIs, large-scale data, and mobile development. The last six years I've worked on large National Science Foundation projects. You can read more about my development experience on my LinkedIn account.

Pin It on Pinterest

Share This