You get a new need, you do a new REST API…​but does it scale? Is it maintainable? UShip intends to make it future ready and more customizable.

What is Yupiik UShip

Yupiik UShip (µShip) is a light service framework. What does it mean? It means that it will enable you to expose a feature over HTTP - by default at least.

Concretely the stack is pretty common and straight forward:

  • A web server - Servlet and even a Tomcat by default,

  • An IoC - CDI and OpenWebBeans for the implementation,

  • A (de)serialization format - JSON with JSON-P/JSON-B for the API and Johnzon for the implementation,

  • A command API - JSON-RPC.

That is it.

The highlights on these choices are:

  • The stack relies on standards and are portables - i.e. you can switch Tomcat for Jetty if you want, OpenWebBeans for Weld and Johnzon for Yasson for example. So no vendor lock-in there and future proof choices.

  • The business is develop as JSON-RPC commands.

The last point hides a lot of goodness, and without rewriting JSON RPC post, it enables to:

  • Think about commands and not HTTP requests,

  • Enrich easily the protocol with custom features since it is JSON based and not with a custom grammar like GraphQL (like enabling to propagate some response to the next request in a bulk, see JSON RPC for an example),

  • Drop HTTP in favor of another transport like Kafka messages without changing your business code/JSON-RPC methods,

  • Integrate with any other service in any language (JSON is well supported in all languages with a lot of libraries),

  • Well document your API with no investment (UShip provides a AsciidoctorJsonRpcDocumentationGenerator which can generate an asciidoc documentation for your endpoint which can be rendered as HTML/PDF and even integrated with Yupiik Minisite) or in a very fancy and customized fashion,

  • Well share your specification thanks to OpenRPC format (equivalent to OpenAPI for JSON-RPC).

UShip also covers all the layers of the development since:

  • It is compatible with openwebbeans-junit5 for the testing (more on the testing documentation),

  • It runs as a plain standalone Java application (java -cp …​ CDILauncher) so is compatible with an assembly packaging and JIB to create docker images (more on the packaging documentation). Indeed you can also do a fat jar but as for any application it is not really recommended - but for unrelated reasons to UShip.

Get started

this part is a very light overview of getting started page.

The first step to start writing a UShip service is to import jsonrpc-core module:

<dependency>
  <groupId>io.yupiik.uship</groupId>
  <artifactId>jsonrpc-core</artifactId>
  <version>${uship.version}</version>
</dependency>

Then you can create a META-INF/beans.xml file in your resources (can be empty or <trim/> depending what you prefer for your CDI scanning) to enable CDI and write a JSON-RPC endpoint:

@JsonRpc
@ApplicationScoped
public class MyCommands {
    @JsonRpcMethod(name = "my-command", documentation = "Creates a foo from a name")
    public Foo myCommand(
        @JsonRpcParam(documentation = "The name") final String in) {
        // ...
    }
}

To start the application, you can write your own main using CDI SE API or use the default one of openwebbeans-se: org.apache.openwebbeans.se.CDILauncher. By default the container will start and stop but to await tomcat you can specify this arg: --openwebbeans.main uShipTomcatAwait. So overall you command will look like: java -cp …​. org.apache.openwebbeans.se.CDILauncher --openwebbeans.main uShipTomcatAwait.

Once executed, you can call your endpoint:

curl \
  http://localhost:8080/jsonrpc \
  -d '{"jsonrpc":"2.0","method":"my-command","params":{"in":"me"}}'

If you have multiple commands and want to call multiple ones at the same time, you can use the bulk option of JSON-RPC:

curl \
  http://localhost:8080/jsonrpc \
  -d '[ \
    {"id":1,"jsonrpc":"2.0","method":"my-command","params":{"in":"me"}}, \
    {"id":2,"jsonrpc":"2.0","method":"my-command","params":{"in":"too"}} \
  ]'

Conclusion

This post just covers the basic steps to use UShip but the benefits are quite high (don’t hesitate to read the previous links to understand them if you didn’t already do).

Customizing the JSON-RPC bulk behavior is really worth it, it enables to control the size of the payload (making the network transfer faster), to compose commands in a flexible ways (giving clients more control about what they fetch and "bulk") and avoid to code a lot of new REST endpoints each time a new consumer/front has a new need making your API more atomic and focused.

By default it is still HTTP/Servlet based so you can still reuse all the goodness you are used to like HTTP headers for security, JWT validation etc…​ Being command based does not mean you throw away all the rest, just that your business code is command oriented and in case of migration to another transport you will keep your command and likely just replace the injected beans representing your security context thanks to CDI if you need such a bean in your business code (for a fine resource based security for example).

The last note is that Yupiik Logging is a nice companion for UShip making it even more cloud and Kubernetes friendly so don’t hesitate to use both at the same time.

From the same author:

In the same category: