Why JBoss AS should use Scala... ;)

I bet the title got the attention of a few JBoss Application Server developers, but let me clarify something before I go on: My intention is not to rewrite JBoss AS in Scala. However, I think Scala makes it easier to build and test JBoss AS extensions/subsystems compared to Java. Let me explain:

JBoss Application Server 7+ is formed out of a MSC core and a bunch of subsystems built on top of it. To test these subsystems, a mix of steps are required including: compile the code, build the module(s) for this subsystem, change application server configuration, start the server and run your tests.

If you look at the JBoss Application Server code base, you'll find that all these steps are achieved with a mix of operations involving: Java compilation, Maven, Ant scripts...etc, which is a bit of pain.

When I started developing Escalante, one of my aims was to be able to test my Escalante subsystems with minimal need from a build tool and in the fastest possible way. The end result is that today I can just right click one of the Escalante Arquillian tests (i.e. Lift HelloWorldTest) , and it will run all the steps above without the need of a build tool! How is that possible? Let me explain:

Building an Escalante subsystem

Escalante code is layered in such way that subsystems can be built purely using Scala code. For this post, let's take the Lift subsystem as example (For those unaware, Lift is a web application development framework for Scala, more info in the FAQ). So for Lift, we have a class called LiftModule which builds the JBoss module supporting the subsystem from scratch. For that it uses:

  • ShrinkWrap to build the JBoss module jar which includes classes in a number of packages and definition of the corresponding the JBoss AS Extension service provider:
  • Scala XML integration to define XML directly in the code (without annoying Java formatting required to write an XML programmatically). XML is a requirement of the JBoss Application Server, and the Lift module uses XML to define itself and its dependencies. XML is also required in order to configure the extension and subsystem in the main app server configuration file:
Warning: I'm fully aware that XML is one of Scala's most controversial features, but it's actually very handy in this particular case because it allows for seamless XML coding within Scala code. This promotes encapsulation allowing both metadata information and logic to build a JBoss module to reside in the same place, without the need of separate XML files.

Running Escalante Arquillian tests

With the subsystem built, it's time to figure out how to make sure the JBoss Application Server instance is ready to serve our applications. For this, Escalante has implemented some nifty Arquillian callbacks in a class called ArquillianListener , which allow us to execute some code at different stages. This listener class uses an AppServer class that encanpsulates logic to do with setting up the application server correctly.

Unzip JBoss AS before test set up

Using @Observes with BeforeSetup, we can force the base JBoss Application Server to be unzipped so that Arquillian has a JBoss Home to use:

The testUnzipAppServer() method just unzips the server and changes file permissions if necessary:

Prayer to the JBoss AS Gods: I hope at some point there will be an easier way to kick off a JBoss Application Server from Arquillian without the need of this unzipping... I'd love to have a way to say: my application needs subsystems X, Y and Z, go fetch them and start a server with those subsystems.

Set up modules before container start

Using @Observes with BeforeStart, we can force Arquillian to install the modules into the JBoss Application Server using the code mentioned above. This way, by the time the server starts, all the extensions we want to install are ready with their modules built and the configuration ready:

Tear down modules after container stop

This is a very important step because it's here where the app server is restored to its initial state in order for other tests to run cleanly. This involves restoring the original configuration:

Note: In order to minimise changes to the application server and simplify cleanup phase, the modules that we're testing are stored under a different module path to the one the server uses. Arquillian allows us for these extra modules paths to be passed to the server through the `modulePath` property. See arquillian.xml used by Escalante for more details.

Plug Arquillian with the listener

Once the code is written, we just need to write the corresponding service provider definition so that Arquillian picks it up:

Run the tests from the IDE

With this in place, you can now run your JBoss Application Server subsystem in-container tests directly from the IDE (of course, if you run it from Maven it will also work)!!

Reuse, reuse, reuse...

A very cool thing things about Scala is that it can work both as an standard programming language to build applications, but also as a scripting language, so this means that whatever code I've used to build the subsystems and set up the app server for the unit tests, it can be perfectly used when building an Escalante distribution.

With minimal changes, and the help of the Maven Scala plugin, I was able to create a simple Scala script that would build the entire Escalante distribution, which effectively builds the modules alongside their configurations, and installs the subsystems and extensions in the main configuration:

Configuring Maven Scala plugin to run this script is dead easy:

Summary

Pretty much everything I explained in this blog post could have been achieved using just Java (i.e. Maven has a Java exec plugin that could execute a Java class to build the distribution).

However, I think Scala makes it a lot more concise and cleaner to write all this up, particularly when it comes to embedding XML.

So, next time you're building a JBoss Application Server extension, give Scala a go! Using the code in this blog post you should be able to build JBoss Module jar archives required to test and run application server extension/subsystems programmatically, as well as adding their own configuration to the main app server configuration in a nice, reusable, way.

There are other benefits JBoss Application Server could get from using Scala as opposed to Java, but I'll leave those for future blog posts ;).

Finally, all the code I mentioned above is located in the Escalante Git repository, so you can clone it, open it in your favourite IDE and see all of this in action :)