Wednesday, October 3, 2018

How to build Java hardware ready system by using Robo4J

In the pasts there was a lack of information about all achievements on the field of Robo4J framework. We have been speaking at the various conferences and explaining there how simple it is to build the hardware system powered by Java. Now it's time to change it and start sharing step by step what we have done in last 2 years.

The goal of this blog post is to show how is possible to build system using Robo4J framework. 
It is important to notice that the created system is Immutable. It means, once it is created it is not possible to add any new unit into the system. The available units will follow their life cycle:


UNINITIALIZED
INITIALIZED
STARTING
STARTED
STOPPING
STOPPED
SHUTTING_DOWN
SHUTDOWN
FAILED

In other hand it's possible to operate upon those units according the life cycle. Each of them can be for example stopped or reinitiated at the runtime without influencing the running system, Eg. the desired unit can be stopped and reinitiated again.

The Robo4J framework provides two approaches (Declarative and Programmatic) that can be used for the building purpose. Both of the are described in the following text.


1. Declarative approach
The declarative approach uses the domain capabilities of  "old" good XML. Most of the time it is the fastest way how to get Robo4J system up and running in very short time. Let's dive into the example.
For the example purposes we have available only one unit HttpServerUnit. As you may have noticed the Robo4J schema begins with the element <robo4j>. In case we want to define one specific unit the <roboUnit> element should be used.  The class for the unit is specified by the <class> element, which represents the path. The Class configuration uses <config> element and its children are represented by <values> elements. The following content can be stored into the "robo4j.xml" file, for example:

<robo4j>
    <roboUnit id="httpServer">
    <class>com.robo4j.socket.http.units.HttpServerUnit</class>
    <config name="com.robo4j.root">
      <value name="port" type="int">
        8042
      </value> 
      <value name="packages" type="String">
        com.robo4j.socket.http.codec
      </value>
      <value name="unitPathsConfig" type="String">
       [{"roboUnit":"","method":"GET"}]
      </value>
    </config>
  </roboUnit>
</robo4j>

Now we have defined the Robo4jJ RoboContext by using the declarative XML approach and for example we've stored it into the "robo4j.xml" file. The xml file is then use in the class to create RoboContext in the following way:

InputStream systemIS = Thread.currentThread().getContextClassLoader().getResourceAsStream("robo4jSystem.xml");

InputStream contextIS = Thread.currentThread().getContextClassLoader().getResourceAsStream("robo4jContext.xml");

RoboBuilder builder = new RoboBuilder(systemIS);
builder.add(contextIS);


RoboContext system = builder.build();

2. Programmatic approach
Sometimes user would like to get more control over the Robo4J system creation process. Luckily, Robo4J provides programmatic way of configuring the whole system. This way is slightly longer as you need to define all specific classes by yourself. In the approach we will use Robo4J internal classes Configuration, ConfigurationBuilder, RoboBuilder to create desired RoboContext. The RoboContext is the representation of the entire system. 

Configuration systemConf = new ConfigurationBuilder()
.addInteger(RoboBuilder.KEY_SCHEDULER_POOL_SIZE, 3)
        .addInteger(RoboBuilder.KEY_WORKER_POOL_SIZE, 2)
        .addInteger(RoboBuilder.KEY_BLOCKING_POOL_SIZE, 2)
        .build();

Configuration serverUnitConf = new ConfigurationBuilder()
.addInteger("port", 8043)
        .addString("packages", "com.robo4j.socket.http.codec")
        .addString("unitPathsConfig", "[{\"roboUnit\":\"http_server\",\"method\":\"GET\"}]")
        .build();

RoboContext system = new RoboBuilder("robonetSystem2", systemConf)
.add(HttpServerUnit.class, serverUnitConf, "http_server")
        .build();

Working demo can be found on my GitHub account: robo4j-net-simple. The README.md file contains all necessary information to execute both of described approaches. 

Happy Coding! 

No comments: