Introduce EzyHTTP

Updated at 1685846300000
EzyHTTP (Easy going to HTTP Interaction) is a framework support to interact to HTTP, it includes both http server and http client.

1. Structure of EzyHTTP Server

  1. When client request to server, Servlet receive the request first
  2. The request must pass through the list of interceptor before pass to controller
  3. The controller handle the request and return response to the Servlet
  4. If have any exceptions unprocessed by the Interceptor and the Controller, an ExcetionHandler will process that exception and return result to the Servlet
  5. After all the Servlet will send the response to client

2. Install EzyHTTP

To create a http server application we need add dependency To use http client we need add dependency

<dependency>
    <groupId>com.tvd12</groupId>
    <artifactId>ezyhttp-server-boot</artifactId>
    <version>1.3.0</version>
</dependency>
<dependency>
    <groupId>com.tvd12</groupId>
    <artifactId>ezyhttp-client</artifactId>
    <version>1.3.0</version>
</dependency>

The latest version can be found in the Maven Central repository.

3. Example

Let’s say we need create an http server application to manage user, we need 2 apis

  • api/v1/users/add: Add user to system
  • api/v1/users/{username}: Get user by name

Firstly, we need create a maven project with

  • name: user-management-application
  • package: com.example.user_management
  • java version: 1.8

Next, we need add ezyhttp-server-boot dependency We use lombok to generate getter, setter, constructor so you need install and add lombok dependency to pom.xm

3.1 Create the application entry point class

    package com.example.user_management;
    import com.tvd12.ezyhttp.server.boot.EzyHttpApplicationBootstrap;
    import com.tvd12.ezyhttp.server.core.asm.RequestHandlerImplementer;
    public class App {
        public static void main(String[] args) throws Exception {
            RequestHandlerImplementer.setDebug(true);
            EzyHttpApplicationBootstrap.start(App.class);
        }
    }

3.2 Create User class to keep user information

    package com.example.user_management.entity;
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    public class User {
        protected String username;
        protected String password;
    }

3.3 Create UserService class to manage user information

    public class UserService {
        protected final Map users = new ConcurrentHashMap<>();
        public User addUser(User user) {
            return users.put(user.getUsername(), user);
        }
        public User getUser(String username) {
            return users.get(username);
        }
    }

3.4 Create UserController class to handle request from client

    package com.example.user_management.controller;
    import com.example.user_management.entity.User;
    import com.example.user_management.service.UserService;
    import com.tvd12.ezyfox.bean.annotation.EzyAutoBind;
    import com.tvd12.ezyhttp.core.exception.HttpConflictException;
    import com.tvd12.ezyhttp.core.exception.HttpNotFoundException;
    import com.tvd12.ezyhttp.core.response.ResponseEntity;
    import com.tvd12.ezyhttp.server.core.annotation.*;
    import lombok.Setter;
    @Setter
    @Controller("/api/v1/users")
    public class UserController {
        @EzyAutoBind
        protected UserService userService;
        @DoPost("/add")
        public ResponseEntity addUser(@RequestBody User user) {
            User existed = userService.addUser(user);
            if(existed == null)
                return ResponseEntity.ok(Boolean.TRUE);
            throw new HttpConflictException("user: " + user.getUsername() + " existed");
        }
        @DoGet("/{username}")
        public User getUser(@PathVariable("username") String username) {
            User user = userService.getUser(username);
            if(user != null)
                return user;
            throw new HttpNotFoundException("user: " + username + " not found");
        }
    }

3.4 Create logback.xml file in src/resources folder with content:

<configuration>
    <appender name="console">
        <encoder>
            <pattern>
                %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} %msg%n
            </pattern>
        </encoder>
    </appender>
    <root level="info">
        <appender-ref ref="console"></appender-ref>
    </root>
</configuration>

Ok, we done all, let’s start main class ‘App’ and great! We’ve had a http server application.

3.5 Let’s take a test on postman

With api: /api/v1/users/add we have:

With api: /api/v1/users/{username} we have:

Awesome! Everything ok.

4. Create a client example

With client, we have 2 way (2 class) to call http request

  • HttpClient: A simple http client, it simply open a connection, send the request and return the response, it only supports sync method
  • HttpClientProxy: It use HttpClient class to send the request, but every request will add to a queue, and we need config number of threads to process this queue. It supports both sync and async method

Firstly, we need add ezyhttp-client dependency to maven Next, create a test package with name: com.example.user_management.test in src/test/java folder

4.1 To test /api/v1/users/add api

We need create a class ApiAddUserTest with content:

    package com.example.user_management.test;
    import com.example.user_management.entity.User;
    import com.tvd12.ezyhttp.client.HttpClient;
    import com.tvd12.ezyhttp.client.request.PostRequest;
    import com.tvd12.ezyhttp.client.request.Request;
    import com.tvd12.ezyhttp.client.request.RequestEntity;
    import com.tvd12.ezyhttp.core.constant.StatusCodes;
    public class ApiAddUserTest {
        public static void main(String[] args) throws Exception {
            HttpClient httpClient = HttpClient.builder()
                    .build();
            User body = new User();
            body.setUsername("dev");
            body.setPassword("123456");
            RequestEntity entity = RequestEntity.body(body);
            Request request = new PostRequest()
                    .setURL("http://localhost:8080/api/v1/users/add")
                    .setEntity(entity)
                    .setResponseType(Boolean.class)
                    .setResponseType(StatusCodes.CONFLICT, String.class);
            Boolean reponse = httpClient.call(request);
            System.out.println("add user reponse: " + reponse);
        }
    }

And we get output: add user response: true.

4.2 To test /api/v1/users/add api

We need create a class ApiAddUserTest with content:

    package com.example.user_management.test;
    import com.tvd12.ezyhttp.client.HttpClientProxy;
    import com.tvd12.ezyhttp.client.request.GetRequest;
    import com.tvd12.ezyhttp.client.request.Request;
    import com.tvd12.ezyhttp.client.request.RequestEntity;
    import com.tvd12.ezyhttp.core.constant.StatusCodes;
    public class ApiGetUserTest {
        public static void main(String[] args) throws Exception {
            HttpClientProxy httpClient = HttpClientProxy.builder()
                    .build();
            httpClient.start();
            RequestEntity entity = RequestEntity.builder().build();
            Request helloRequest = new GetRequest()
                    .setURL("http://localhost:8080/api/v1/users/dev")
                    .setEntity(entity)
                    .setResponseType(String.class)
                    .setResponseType(StatusCodes.NOT_FOUND, String.class);
            String reponse = httpClient.call(helloRequest, 10000);
            System.out.println("get user reponse: " + reponse);
        }
    }

And we can see the output:

get user reponse: {"username":"dev","password":"123456"}

5. Conclusion

With EzyHTTP everything are simple, you don’t need care about HttpServlet, HttpRequest, HttpResponse, how to serialize/deserialize request/response and bean management, with IOC EzyHTTP will care for you.

6. List of examples

  1. ezydata-jpa: an example uses EzyHTTP and ezydata-jpa
  2. ezydata-mongodb: an example uses EzyHTTP and ezydata-mongodb
  3. ezydata-redis: an example uses EzyHTTP and ezydata-redis
  4. ezyhttp-login: an example uses EzyHTTP to login via google and facebook or username and password
  5. ezyhttp-thymeleaf: an example uses EzyHTTP and ezyhttp-thymeleaf

Next

We can see how to handle client request.