skofgar/mercury

View on GitHub
guides/CHAPTER-5.md

Summary

Maintainability
Test Coverage
# Traditional REST endpoints

The recommended way to create REST endpoints is the REST automation system described in chapter 4.

However, if you want to write REST and websocket endpoints in traditional ways, Mercury supports the following 
for backward compatibility.

1. JAX-RS annotation
2. Spring REST controller
3. Java Servlet

### JAX-RS annotated endpoints

You class should include the `@Path(String pathPrefix)` annotation. Set pathPrefix accordingly. 

All JAX-RS REST endpoints are prefixed with "/api". If your pathPrefix is "/hello". The path is "/api/hello".

In your REST endpoint method, you should use another `@Path` to indicate any additional path information. 
Note that you can use `{pathParam}` in the URL path.
If you have pathParam, please add `@PathParam` parameter annotation to the argument in your method.

You can set the HTTP method in the method with `@GET`, `@POST`, `@PUT`, `@DELETE`, etc.
and specify content types in `@Consumes` and `@Produces` method annotation.

If you want your REST endpoint to be optional when a property in the application.properties exists, annotate your 
class with `OptionalService`.

Please refer to example code in `rest-example` and the [JAX-RS reference site](https://jersey.github.io/) for details.

### Java Servlet

For low level control, you can use the `@WebServlet(String urlPath)` to annotate your Servlet class that must 
extend the `HttpServlet` class.

If you want your Java Servlet to be optional when a property in the application.properties exists, annotate your
class with `OptionalService`.

### Spring REST controller

If you are more familar with the Spring framework, you may use Spring REST controller.
Note that this will create tight coupling and make your code less portable.

Please refer to [Spring documentation](https://spring.io/guides/gs/rest-service/) for details. 
Note that Spring REST controllers are installed in the URL root path.

## Websocket service

You can use `@WebSocketService(handlerName)` to annotate a websocket service that implements the
`LambdaFunction` interface. Your websocket service function becomes the incoming event handler for websocket. 
The system will automatically create an outgoing message handler that works with your websocket service.

Please refer to the sample code `WsEchoDemo` in the `rest-example`.

Mercury is 100% event-driven. This includes websocket service. The sample code includes example for 
OPEN, CLOSE, BYTES and TEXT events. In the OPEN event, you can detect the query parameter and token.

For standardization, websocket service uses a URL path as follows:

```
ws://host:port/ws/{handlerName}/{token}
```
The websocket client application or browser that connects to the websocket service must provide the "token" 
which is usually used for authentication.

IMPORTANT: websocket does not support custom HTTP headers for authentication. As a result, we usually use an 
authentication token in the URL or query parameter. For the Mercury framework, we recommend the use of a token 
as a URL suffix. Typically, a user logs on to your application with a REST endpoint like "/login" and then a 
session cookie is created. The browser may then use the sessionId as a token in the websocket connection.

`Websocket idle timeout` - there is a one-minute idle timeout for all websocket connection. 
To keep the websocket connection alive, you may send a message to the websocket service. 
For example, sending a BYTES or TEXT message to the service with some agreed protocol.

To disconnect a websocket connection, you may use the Utility class as follows:

```
void closeConnection(String txPath, CloseReason.CloseCodes status, String message) throws IOException;
```
The txPath is available to the websocket service mentioned earlier.

## Calling other microservices functions

You may call other microservices functions from your REST and websocket endpoints using the `send` or `request` 
methods of the Post Office.

## Static contents for HTML, CSS and Javascript

Under the hood, we are using Spring Boot. Therefore you may put static contents under the "/public" folder in the 
project's "resources". The static contents will be bundled with your executable application JAR when you 
do `mvn clean package`.

## Loose coupling with Spring Boot

The Mercury framework is loosely coupled with Spring Boot to support REST and websocket endpoints. 
The light-weight application server for Spring Boot can be Tomcat, Jetty or Undertow.

For consistency, we have optimized Spring Boot with custom serializers and exception handlers in the `rest-spring` 
module.

If you know what you are doing, you can use Spring Boot feature directly with the exception of the `@SpringApplication` 
annotation because we use the `@MainApplication` to enable additional automation. You can change the behavior of 
Spring Boot including auto-config classes using the `application.properties` file in the resources folder in the 
maven project.

We are currently using Tomcat. If your organization prefers Jetty or Undertow, you may adjust the pom.xml file in 
the `rest-spring` and `platform-core` projects.

## Application parameters

In additon to the parameters defined by Spring Boot, Mercury has additional parameters. Below are some examples.
Please refer to [Appendix-I](APPENDIX-I.md) for a complete list.

Mercury can run with or without Spring Boot. For compatibility, it uses only application.properties or application.yml as the base configuration file.

If you use a different Spring Boot "profile", please keep Mercury parameters in application.properties or application.yml.

To use environment variables in your application.properties, you may use the standard convention like this:

```
some.key=${SOME_ENV_VARIABLE:defaultValue}
```

If you use the ConfigReader to load your own applicaton specific parameter, you may use the standard convention to point to an environment variable or to point to the base configuration in application.properties.

1. web.component.scan - you should add your organizaton packages as a comma separated list to tell Mercury to scan 
   for your packages.
2. snake.case.serialization - we recommend the use of snake case for modern API
3. safe.data.models - Optional. For higher security, you may specify a list of safe data models to be accepted by 
   the serialization engine. This is to protect against hidden "evil" Java classes in certain open sources that 
   you have not vetted directly.
4. protect.info.endpoints - Optional. You may protect certain "known" REST endpoints such as "/info" or "/env" 
   from unauthorized access.
5. spring.application.name/application.name, info.app.version and info.app.description - please update application 
   name and information before you start your project. spring.application.name and application.name can be used 
   interchangeably.

---

| Chapter-6                           | Home                                     |
| :----------------------------------:|:----------------------------------------:|
| [Cloud connectors](CHAPTER-6.md)    | [Table of Contents](TABLE-OF-CONTENTS.md)|