[JAVA] I searched for a lightweight framework that answers the sudden "make it quickly"

Introduction

"** Make a mockup like this quickly. ** ”Have you ever been given a task with such a sudden word?

When conducting failure investigations and feasibility studies, we sometimes create mockup applications that work with the application to be investigated, but the task we have discussed this time is also the creation of this mockup application.

I just want to create a mockup application that works with a small amount of effort, so this time I'll start by looking for a ** framework that I haven't used yet that seems to be quick to make.

Conditions set for the framework to be adopted

Functional requirements to be implemented in mockup applications

How to actually go

First, I searched for the framework provided by OSS with ** GitHub ** with the search keyword java web framework microservice. The search results are as follows. Looking at the number of ★, ** tipsy / javalin ** is the first candidate, and ** pippo-java / pippo ** is the second candidate. github_search.png

Next, check the features of the framework on the official website, and read the description on the site diagonally to see if it can meet the adoption conditions and functional requirements to be implemented. Apparently, both of them meet the set conditions, so I was interested in "colorful and pop iconsandsize-conscious design (points that are supposed to be used in embedded devices), so this time Will try to adopt the second candidate ** Pippo **.

pippo-logo.png

The core is small (around 140 KB) and we intend to keep it as small/simple as possible and to push new functionalities in pippo modules and third-party repositories/modules. You are not forced to use a specific template engine or an embedded web server. Furthermore you have multiple out of the box options (see Templates and Server). Also, Pippo comes with a very small footprint that makes it excellent for embedded devices (Raspberry Pi for example).

Build mockup application

Immediately build a mockup application development environment.

Environment

Get source file

Get the repository to your local environment from GitHub's Repository.

Create a mockup application template

Follow the instructions in Quickstart, move to the root directory pippo of the repository cloned to your local environment, and execute the following command. Only the parts of -DgroupId and -DartifactId are changed.

mvn archetype:generate \
  -DarchetypeGroupId=ro.pippo \
  -DarchetypeArtifactId=pippo-quickstart \
  -DarchetypeVersion=1.5.0 \
  -DgroupId=com.example.mock \
  -DartifactId=example-mock

You will be asked if you want to set the version of the module you built, so enter it here if you want to change it. This time, the default 1.0-SNAPSHOT is fine, so leave it empty and press the Enter key.

Define value for property 'version' 1.0-SNAPSHOT: :

Next, the settings will be confirmed, so if there are no problems, enter Y.

[INFO] Using property: package = com.example.mock
Confirm properties configuration:
groupId: com.example.mock
artifactId: example-mock
version: 1.0-SNAPSHOT
package: com.example.mock
 Y: :

Implementation

A directory with the name ʻexample-mock specified by -DartifactIdis created under the root directorypippo`, so edit the following files to create a mockup application.

pippo
└─ example-mock
  ├─ pom.xml (Edit this file to add modules to use)
  └─ src
    └─ main
      ├─ java
      │  └─ com
      │     └─ example
      │        └─ mock
      │           ├─ PippoApplication.java (This time we will implement the process in this file)
      │           └─ PippoLauncher.java
      ├─ resources
      │  ├─ conf
      │ │ ├─ application.properties
      │  │ ├─ messages.properties
      │  │ └─ messages_xx.properties etc (Messages according to locale.There are some properties)
      │  ├─ templates
      │ │  └─ hello.ftl
      │  └─ simplelogger.properties (Logger settings edit this file)
      └─ webapp
        └─ WEB-INF
          └─ web.xml

First, create a POJO that maps the request and response.

RequestParameter.java


package com.example.mock.common;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class RequestParameter implements Serializable {

	private static final long serialVersionUID = 1L;

	public String itemA;
	public Boolean itemB;

}

ResponseParameter.java


package com.example.mock.common;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class ResponseParameter implements Serializable {

	private static final long serialVersionUID = 1L;

	//Response result (1:OK、0:NG)
	public Integer result;
	public String message;
}

Next, implement the logic to be executed when a JSON format request is accepted by POST.

PippoApplication.java



package com.example.mock;

import java.security.InvalidParameterException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.example.mock.common.RequestParameter;
import com.example.mock.common.ResponseParameter;

import ro.pippo.core.Application;

/**
 * A simple Pippo application.
 *
 * @see com.example.mock.PippoLauncher#main(String[])
 */
public class PippoApplication extends Application {

    private final static Logger log = LoggerFactory.getLogger(PippoApplication.class);

    @Override
    protected void onInit() {
        getRouter().ignorePaths("/favicon.ico");

        // send 'Hello World' as response
        GET("/", routeContext -> routeContext.send("Hello World"));

       //The part implemented this time is here
        POST("/reqJson", routeContext -> {

        	log.debug("Check Request Parameters:" + routeContext.getRequest().getParameters());
        	log.debug("Check Request Body:" + routeContext.getRequest().getBody());
           //Map the Body part of the request to the POJO for the request
        	RequestParameter reqParm = routeContext.createEntityFromBody(RequestParameter.class);

        	if (null == reqParm) {
        		throw new InvalidParameterException("Request Paramater is Invalid");
        	}

        	ResponseParameter resParm = new ResponseParameter();

           //Judge the value of itemB of the request and switch the response
        	if (Boolean.FALSE == reqParm.itemB) {
        		// NG
            	resParm.result = Integer.valueOf(0);
            	resParm.message = "NG:" + reqParm.itemA;

            	log.debug("Check Result:NG");
        	} else {
        		// OK
            	resParm.result = Integer.valueOf(1);
            	resParm.message = "OK:" + reqParm.itemA;

            	log.debug("Check Result:OK");
        	}

            //Return JSON format response
        	routeContext.json().send(resParm);
        });
    }

}

Edit simplelogger.properties and modify it so that the log embedded this time is output. Also, modify the log output date and time format so that the date is also output.

org.slf4j.simpleLogger.log.com.example.mock=debug
org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss

Compile / start

Since the mock application created this time uses Jackson, add the following description to pom.xml under the ʻexample-mock` directory.

pom.xml


<!-- Jackson -->
<dependency>
  <groupId>ro.pippo</groupId>
  <artifactId>pippo-jackson</artifactId>
  <version>${pippo.version}</version>
</dependency>

Execute the command under the ʻexample-mock` directory.

mvn compile exec:java

Operation verification

  1. Go to http: // localhost: 8338 / with your browser and confirm that ** Hello World ** is displayed.

  2. Send a JSON-formatted request with the cURL command and check the response result.

$ curl -H "Content-Type: application/json" -X POST "http://localhost:8338/reqJson" -d '{"itemA": "Test Request", "itemB": true}' -i
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    80  100    40  100    40    183    183 --:--:-- --:--:-- --:--:--   197HTTP/1.1 200 OK
Date: Mon, 17 Dec 2018 02:53:48 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 40
Server: Jetty(9.4.6.v20170531)

{"result":1,"message":"OK:Test Request"}

Log output result

2018-12-17 11:53:48 [qtp188599000-16] DEBUG ro.pippo.core.PippoFilter - Request POST '/reqJson'
2018-12-17 11:53:48 [qtp188599000-16] DEBUG ro.pippo.core.route.DefaultRouter - Found 1 route matches for POST '/reqJson'
2018-12-17 11:53:48 [qtp188599000-16] DEBUG ro.pippo.core.route.DefaultRouteContext - Executing handler for POST '/reqJson'
2018-12-17 11:53:48 [qtp188599000-16] DEBUG com.example.mock.PippoApplication - Check Request Parameters:{}
2018-12-17 11:53:48 [qtp188599000-16] DEBUG com.example.mock.PippoApplication - Check Request Body:{"itemA": "Test Request", "itemB": true}
2018-12-17 11:53:48 [qtp188599000-16] DEBUG com.example.mock.PippoApplication - Check Result:OK
2018-12-17 11:53:48 [qtp188599000-16] DEBUG ro.pippo.core.route.RouteDispatcher - Returned status code 200 for POST '/reqJson'
$ curl -H "Content-Type: application/json" -X POST "http://localhost:8338/reqJson" -d '{"itemA": "Test Request", "itemB": false}' -i
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    81  100    40  100    41    182    187 --:--:-- --:--:-- --:--:--   187HTTP/1.1 200 OK
Date: Mon, 17 Dec 2018 02:53:55 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 40
Server: Jetty(9.4.6.v20170531)

{"result":0,"message":"NG:Test Request"}

Log output result

2018-12-17 11:53:55 [qtp188599000-19] DEBUG ro.pippo.core.PippoFilter - Request POST '/reqJson'
2018-12-17 11:53:55 [qtp188599000-19] DEBUG ro.pippo.core.route.DefaultRouter - Found 1 route matches for POST '/reqJson'
2018-12-17 11:53:55 [qtp188599000-19] DEBUG ro.pippo.core.route.DefaultRouteContext - Executing handler for POST '/reqJson'
2018-12-17 11:53:55 [qtp188599000-19] DEBUG com.example.mock.PippoApplication - Check Request Parameters:{}
2018-12-17 11:53:55 [qtp188599000-19] DEBUG com.example.mock.PippoApplication - Check Request Body:{"itemA": "Test Request", "itemB": false}
2018-12-17 11:53:55 [qtp188599000-19] DEBUG com.example.mock.PippoApplication - Check Result:NG
2018-12-17 11:53:55 [qtp188599000-19] DEBUG ro.pippo.core.route.RouteDispatcher - Returned status code 200 for POST '/reqJson'

Build build

After the operation verification is completed, create ʻexample-mock / src / main / assembly / assembly.xml referring to the description in [Pippo site](http://www.pippo.ro/doc/deployment.html). I will. The contents of ʻassembly.xml are as follows.

assembly.xml


<?xml version="1.0" encoding="UTF-8"?>
<assembly>
    <id>app</id>
    <formats>
        <format>zip</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <useProjectArtifact>false</useProjectArtifact>
            <scope>runtime</scope>
            <outputDirectory>lib</outputDirectory>
            <includes>
                <include>*:jar:*</include>
            </includes>
        </dependencySet>
    </dependencySets>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory>.</outputDirectory>
            <includes>
                <include>*.jar</include>
            </includes>
            <excludes>
                <exclude>*-javadoc.jar</exclude>
                <exclude>*-sources.jar</exclude>
            </excludes>
        </fileSet>
    </fileSets>
</assembly>

This time, you don't need to edit pom.xml because it follows the procedure of QuickStart. (Already mentioned when creating the mockup application template) A build ʻexample-mock-1.0-SNAPSHOT.zip with the application server Jettyis created in thetarget` directory. The command to execute is as follows.

mvn clean package

If a separate application server such as Tomcat is prepared, execute the following command to build the War file of the mockup application.

mvn -Pwar package

Start-up

Unzip the created Zip file ʻexample-mock-1.0-SNAPSHOT.zip` to an arbitrary directory, move to the unzipped directory, and then execute the following command.

java -jar example-mock-1.0-SNAPSHOT.jar

Summary

It was an impression that I made a mockup application using ** Pippo ** in a hurry, but I was able to confirm that the condition of ** making quickly ** was fully satisfied.

Set conditions Evaluation
Must be a framework provided by OSS ○ Apache 2.Provided with 0 license
What can be implemented in Java
Deploy from environment construction/Being able to do the work up to startup quickly ○ The description of the document was easy to understand and I was able to do it quickly without clogging.
Avoid consuming server resources as much as possible ○ Both the size on the disk and the memory size used are small.

The size of the web application I was looking forward to on disk was ** about 5.9MB **. (Including application server) For comparison, when I checked the size on the disk when deploying the War file to Tomcat (8.5.30: distribution is Core), it was ** about 14.5MB **. There was a difference of more than twice in the size on the disc, and I got the impression that it was quite small.

In addition, the heap size of the JVM can also be operated with the default value, and the memory usage confirmed by the task manager is ** about 61MB **, and the memory used is only considered for use in embedded devices. You can see the consideration for size.

For comparison, the memory usage when starting Tomcat and Jetty with the default settings was as follows.

I will also introduce the modularized Other Features if I have a chance.

Reference information

Pippo official website

GitHub Repository

Recommended Posts

I searched for a lightweight framework that answers the sudden "make it quickly"
I searched for a web framework with Gem in Ruby
A note that I gave up trying to make a custom annotation for Lombok
How to make a lightweight JRE for distribution
I wrote a test code (Junit & mockit) for the code that calls the AWS API (Java)
I made a check tool for the release module
I read the readable code, so make a note
What should I use for the testing framework [Rails]
How to make a mod for Slay the Spire
[Java] I tried to make a rock-paper-scissors game that beginners can run on the console.
I made a reply function for the Rails Tutorial extension (Part 4): A function that makes the user unique
I tried to make it possible to set the delay for the UDP client of Android by myself
I made a GitHub Action that makes it easy to understand the execution result of RSpec
How to deal with the type that I thought about writing a Java program for 2 years