Monthly Archives: August 2017

2 posts

AsyncAPI Java Tools 0.0.4 released

It started a as proof-of-concept, checking out AsyncAPI and learning something about it. Actually that topic came to me from two different angles. We where looking into solutions for RPC over messaging (namely AMQP 1.0) instead of HTTP/REST. The second angle was a discussion with a very good friend of mine of “how do you define today an API about messages from the server to the client”. Everyone is talking about Swagger and OpenAPI, but this seems to be all request/response for HTTP based APIs.

And then someone mentioned AsyncAPI, I had to look into this. And this is what I came up with so far.

AsyncAPI tools

ctron/asyncapi is a set of tools, written in Java, around AsyncAPI in general. Reading the specification file into a Java model, a code generator for client and server side code, a few base classes which the generate code makes use of.

The definition file parser still is not optimal. The idea is that the definition is based on JSON schema, but I couldn’t find any good support for JSON schema in Java at the moment. So right now it all home-brew and although it does get the job done, I don’t think it is pretty.

Code generation

The code generation is a bit more sophisticated. The idea of taking this out of the Maven plugin came pretty early. I guess it would be cool to have a gradle plugin at some time in the future and the Maven plugin really is just a small wrapper around the code generator. So that should easily be possible.

The code generation is backed by Eclipse JDT, which allows you to create and parse Java code in a DOM style way. I am constantly torn apart between liking and hating this at the same time. I did work with generic model-to-text tools in the past, and tools like Acceleo or Xpand are way easier to read than Java code generating Java code in that way. On the other side you would need a full blown Ecore model before and then wrap this again by a Maven plugin. I am not sure this is fun either. Also, using the DOM approach, it is quite simple to write extension modules for the code generation, which allow to actually process the generated Java DOM and extend it, without the requirement to write an awfully complex code generation template. So let’s see where this is going in the future.

What works?

Don’t expect productive code … yet ūüėČ Currently the code generator will create the defined types/schemas, the messages and their payload. Topics will be parsed into services, versions and actions and generate Client and Server interfaces. Also is there a client and server implementation using AMQP and Qpid JMS. This already allows you to communicate between client and server. Right now GSON will be used for creating JSON payload serialization. But I think that it should be pretty simple to swap this with e.g. Jackson.

What does not work?

The AsyncAPI specification actually defines a bit more than the tooling can currently handle. The server section is missing, various meta data like license and descriptions are not supported. But the most important thing which is currently missing IMHO is some implementation backed on MQTT. Not that I am a big fan on MQTT, I would prefer AMQP over that in this case. But I would like to see two different AsyncAPI partners communicate via MQTT/JSON. One of them being generated by this tool-set and the other one based on something completely different.

Also is JSON schema more powerful than what the parser can currently handle. I am not sure if JSON schema and Java is a very good fit, but if you want to go AsyncAPI, then you need to work with JSON schema. And this toolset needs to do a better job here.

AsyncAPI Maven Plugin

The AsyncAPI Maven plugin takes the code generator from the main tools project and wraps in into a Maven plugin. The idea is to simply drop in you AsyncAPI YAML file and let the Maven plugin generate the code for it. Of course this is Eclipse M2E aware, so that you can simply safe your YAML file and Eclipse will on the fly generate new code for you.

Examples

Interested in how this would look like in the form of source code? Well, here are some examples. Also be sure to check out my examples repository.

First we need to create a builder for either the server or the client implementation:

Builder<JmsClient> builder = JmsClient.newBuilder()
  .host("localhost")
  .profile(AmqpProfile.DEFAULT_PROFILE)
  .payloadFormat();

Next create an instance from it, the following is a client instance which will listen to some server-side event:

try (JmsClient client = builder.build();
     ListenerHandle listener =
        client.accounts()
          .eventUserSignup().subscribe(System.out::println)) {

  System.out.println("Waiting for messages…");
  Thread.sleep(Long.MAX_VALUE);

}

The of course we need a server to publish messages:

try (JmsServer client = builder.build()) {

  client.accounts().eventUserSignup()
    .publish(newUserMessage())
      .toCompletableFuture()
      .get();

}

Of course there is no need to actively wait for the message to be sent with get() if you don’t need to. But you can use the AsyncAPI in sync way if you like to ūüėČ

What is next?

There is a lot to do. Really, a lot! I would like to make an interop test with MQTT. There are several fields from the specification which are currently not supported. The server side JMS API isn’t really suitable for JEE style programming, especially when it comes to container managed JMS.

So I hope I will find some time to work on the MQTT backed implementation, because that would validate that two different AsyncAPI tools could work together. And I think this is what it is all about.

Before I forget…

The initial idea of why I looked into AsyncAPI was to get message based request/response. Well, that is something which AsyncAPI doesn’t really provide. But, to be fair, it would only require a few changes to add this to the specification.

See also

Kapua micro client SDK, running on a microcontroller

A few weeks back, while being at EclipseCon France, I did stumble over a nice little gadget. There was talk from MicroEJ around Java on microcontrollers. And they where showing an IoT related demo based on their development environment. And it seemed they did have Eclipse Paho (including TLS) and Google Protobuf running on their JVM without too much troubles.

ST Board with Thermocloud

My first idea was to simply drop the Kapua Gateway Client SDK on top of it, implementing the cloud facing API of MicroEJ and let their IoT demo publish data towards Kapua.
After a few days I was able to order such a STM32F746G-DISCO board myself and play a little bit around with it. It quickly turned out that is was pretty easy to drop some Java code on the device, using the gateway client SDK was not an option. The MicroEJ JVM is based on Java CDLC 8. Sounds like Java 8, right? Well, it is more like Java 7. Aside from a few classes which are missing, the core features missing where Java 8’s lambdas and enhancements to interfaces (like static methods and default methods).

Rewriting the gateway client SDK in Java 7, dropping the shiny API which we currently have, didn’t sound very appealing. But then again, implementing the Kapua communication stack actually isn’t that complicated and such an embedded device wouldn’t really need the extensibility and modularity of the Java 8 based gateway client SDK. So in a few hours there was the Kapua micro client SDK, which doesn’t consume any dependencies other than Paho and Protobuf and also only uses a minimal set of Java 7 functionality.

The second step was to implement the MicroEJ specific APIs and map the calls to the Kapua micro SDK, which wasn’t too difficult either. So now it is possible to simply install the “Kapua Data Channel Provider” from the MicroEJ Community Store. Alternatively you can compile the sources yourself as the code for this adapter is also on GitHub. Once the data channel provider is installed you can fire up any application consuming the DataChannel API, like the “Thermocloud” application, and publish data to Kapua. Please be sure to follow the installation instructions on the Kapua data channel provider for configuring the connection to your Kapua instance.

Kapua Data Channel Provider
Data from Thermocloud in Kapua

As the micro client is capable of running on Java 7, it might also be a choice for people wanting to connect from Android to Kapua without the need to go for Java 8. As Java 8 on Android still seems to be rather painful, this could be an option.

Also see:

I would like to thank Laurent and Frédéric from MicroEJ, who did help me fix all the noob-issues I had.