Even or Odd

This is a quick demo, showing how to create a Java web-service in just a few minutes. I’m assuming you have Java and Tomcat already installed on you computer and use IntelliJ as your IDE, and gradle as your build-automation system.

The simple task is to create a web-service that can answer if a provided number is even or odd. So for example, you would type “http://localhost:8080/eo/evenORodd?x=3” into the URL address input field of your browser, and then see something like this as the result: 3 is odd
Not all that sophisticated, I know that, but that’s not the point of this demo.

Java Source Code

Here is the Java code that implements the service:

package edu.gcccd.csis;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * WebService, answering the question, if the given integer x is even or odd.
 * Remember: requestURI = contextPath + servletPath + pathInfo
 * - contextPath is the basically the name of the WAR when it's deployed
 * - servletPath is declared as "/evenORodd" below.
 */
@WebServlet(value = "/evenORodd", name = "EO")
public class WebService extends HttpServlet {
    private final Logger logger = LogManager.getLogger(WebService.class);

    @Override
    protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) {
        try {
            final int x = Integer.parseInt(req.getParameter("x"));
            resp.setHeader("Content-Type", "text/html; charset=UTF-8");
            resp.getWriter().printf("%d is %s", x, (x % 2) == 0 ? "even" : "odd");
            resp.setStatus(HttpServletResponse.SC_OK);
            logger.info("That went well.");
        } catch (Exception ex) {
            resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            logger.error(ex.toString());
        }
    }
}

Java Test Code

Let’s also show you this could be tested, i.e. with a very Unit-Test, using only classes from java.io and java.net:

package edu.gcccd.csis;

import org.junit.Test;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import static org.junit.Assert.assertEquals;

public class WebServiceTest {

    @Test
    public void doGet() throws Exception {
        final URL url = new URL("http://localhost:8080/eo/evenORodd?x=3");
        final HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setRequestMethod("GET");

        final int status = con.getResponseCode();
        assertEquals(200, status);

        final BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        final StringBuilder content = new StringBuilder();
        String inputLine;
        while ((inputLine = in.readLine()) != null) {
            content.append(inputLine);
        }
        in.close();
        con.disconnect();
        assertEquals("3 is odd", content.toString());
    }
}

IntelliJ

With the code out of the way, lets talk tools: We start a new project in IntelliJ, using Gradle with Java and Web selected.

On the next screen I entered “edu.gcccd.csis” for the GroupId and “WebService” for the ArtifactId. That’s it.

Customizations

Since there is really no need for any GUI with this little service, lets remove the src/main/webapp folder. Next, we need to edit the build.gradle file to add the javax.servlet-api and since there is no UI, we also want to make sure we have reasonable logging capabilities:

plugins {
    id 'java'
    id 'war'
}
repositories {
    mavenCentral()
}

group 'edu.gcccd.csis'
sourceCompatibility = 1.8
war.archiveFileName = 'eo.war'

dependencies {
    providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1'
    //  Logger
    compile group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.11.2'
    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.2'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

If you look closely, the javax.servlet-api is declared as a provided dependency and junit is of course a test dependency. Therefore, we have only added the two logging libraries to the distributable, we will eventually build.

However, we have now set the name of the distributable WAR file to eo.war. The WAR file will eventually contain the web-app with all its resources. By default, Tomcat uses the name of such a WAR files as the context name. I.e., once deployed, our web service will be available at this URL: http://localhost:8080/eo

Logging

Logging is important once things start to fail .. let’s prepare for that too. Putting this log4j2.xml document into the project’s resource folder will allow for some minimal logging functionality.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
    <Console name="stdout" target="SYSTEM_OUT">
        <PatternLayout pattern="[%d{HH:mm:ss.SSS}][%t][%-5level][%logger{36}] %msg%n"/>
    </Console>
</Appenders>
<Loggers>
    <Root level="INFO">
        <AppenderRef ref="stdout" level="INFO"/>
    </Root>
</Loggers>
</Configuration>

At this point the IntelliJ Project looks something like this. We have added a java source and a java test file, a log4J2 descriptor and edited the build.gradle file.

To see the web-service working (e.g. debugging it) and launching it from within IntelliJ, we need to add a Run/Debug configuration. Select “Tomcat Server” and “Local” once you have found it. Initially, you will have to tell IntelliJ where Tomcat is installed on you Computer ..

This is the place where we will also tell IntelliJ to launch a browser with the aforementioned URL, every time you made a change to the source and relaunched Tomcat.  Moreover, we configure the steps we want IntelliJ to do during a launch. I.e. Build and Build the war file:

Do not step over the next step: Open the Deployment tab and change the Application context to “/eo”

Now it’s time to run the Tomcat 9.0.27 configuration you just created .. hopefully resulting in something like this:

Find the code for this kiss (keep it simple stupid) project here: https://github.com/GCCCD-CSIS/evenorodd

..

Leave a Reply