Simple Application Server’s Concepts People Forgot

As a consultant, I often face the same issues and questions from customers, and with the emergence of DevOps practices, I often see people arguing on some old and proofed principles, probably only because we, as human, forget and are trying to re-invent the wheel.

Java EE and the Application Servers world is no exception, so here is the top three problems I always have to re-explain when dealing with Operations and Developers issues.

Rely on resources provided by application server

Java EE is an extension of Java. And as such, some of the people who created Java participated in elaborating Java EE specification, with the goal in mind to provide mechanisms to solve the current issues in the Enterprise world. This lead to put in application some of the principles behind OO programming and Java programming as well:
– Separate concerns: Segregate responsibilities, do one thing but do it well, try to work as service, hide the complexity but provide powerful services.
– Increase Reusability: Some skilled people will do job for you, and they were selected to do it well, so use what they do, use the APIs, and focus on doing your stuff better.

As you can see, this sounds like DevOps concepts, if you have a double reading you can see that these principles both apply to code, and to human organizations in IT where people wants to build, deploy and operate a piece of software in the most efficient, collaborative and secure manner.

This is how I have been taught Java Programming since Java 1.1, and I still think that Java, and as a consequence Java EE is built this way. Of course it has defect, after all, perfection is not human, and this is another debate.

The datasources

To return to our subject, I remember that of the toughest issue I always facing is often related to datasources configuration. To go back to the basics, you should remember that in a Java EE Application Server a lot of resources can be registered in a directory called JNDI. It allows use of resources in a distributed manner, but, and this is the most important thing, it allows to decorelate a physical resource from its name. Just like the DNS. And I think that, today, nobody will prefer using static IP addresses instead of name servers?

The guys behind the concept of JNDI, by first applying it to datasources, knows that one of the most important interaction between an application server and the rest of the Information System is often related to connect to a source of data. Java EE rapidly came with a solution to that, including a way to easily pass from an environment to another: Simply use a name indirection and let the Application Server administrator (the Operations guy, or the Ops) configure it in a transparent manner for application that needs data from this source.

So, I often get very confused when I hear people saying that they don’t want to rely on such a feature because they don’t want to wait after the Ops guy to do the job, just like if the application will run on production from the developer’s laptop.

Moreover, not only providing an indirection name to the “welcome to run” application, the application server also manages the resource life cycle, using pools or other functionalities (failover, hiding passwords, providing drivers, etc…), so many features that the developer would have to handle if they were not provided.

The modules

In the first generations of Java EE applications servers, things where quite monolithic. This was only related to choices of implementations and internal architecture of application servers, and not related (not entirely true) to EE specifications. A few generations later, JBoss AS 7 and some others (Geronimo, Glassfish, etc…) introduced modularity in their architecture to allow better class loading isolation (on of the most important issues in the first application servers, probably because this part was underspecified in Java EE) as well as improving performance and allowing better reusability.

To apply the “eat your own dog food” principle, JBoss AS 7 relies on its own modular class loader (called JBoss modules) to load its core components or its dependent librairies and provides at the same time a convenient way for applications that may require it, a framework for sharing their libraries or to rely on application servers library to result in a lower footprint and a higher reuse. Quite academic.

And again, the configuration of datasources is not an exception.

One more thing to understand, in AS7/WildFly8+ a module is not a deployment, but a deployment, once deployed, is visible as a module. So people are often mistaken and makes confusion between these two concepts.

So Why Should I Use Modules For My Datasource Driver ?

If we compile all these previous arguments together, we can clearly understand that a datasource is a resource provided by the application server in a named manner abstracting its physical location. At the end, its goal is to facilitate the deployment of an application in all the environments with no modifications of the delivery. When doing DevOps, I should put my Ops cap, remember that principle, and start configuring it as such.

So then, I have two options: install the datasource driver as a deployment by copying it in the $JBOSS_HOME/deployments directory. As stated before, once a deployment is deployed, it is seen as a module. The JBoss guys provided this feature for compatibility reasons and because this quite easy for a Dev to put the driver there, add a few lines of XML in the AS server and have its datasource ready, testing it.

But, in real life, when we go production, the developer does not have to bother to manage this, someone is doing it, in a transparent manner. Hence, the resource is part of the configuration of the application server and does not follow the deployment lifecycle, it follows the AS configuration lifceycle. As such, it is preferable that it relies on resources (classes, librairies, etc…) available in the application server and not deployed on top of the application server. Said with other words, if the Ops have to wait that the Dev deploys the JDBC driver, we will end-up in a dead lock.

An extra simple argument, this also simply allows to manage credentials for datasources from a limited number of people, and not putting them in files inside the Source Code Management system or worse on github.

If you see it now this way, you should understand that the driver has its seat in the modules directories, but of course you have the choice, even when wearing your Ops cap, to put the driver’s in deployments. But we do not recommend it.

I hope that these few arguments convinced the most skeptical of you.

 

Know What To Log Not How To Log

TODO

This is about the subsystem logging in JBoss

Use The Tools Provided By The Platform

TODO

This is about the domain mode in JBoss

 

 

Binding an URL in AS7 JNDI tree

AS7 provides the JNDI functionnaly through the naming subsystem. If you take a look at the corresponding schema ($AS7_HOME/docs/schema/jboss-as-naming_1_1.xsd, you will see that its configuration has only a few options.

What does this XML schema description says ? It says that the configuraiton of the naming subsystem is composed of “binding” elements. Each of this element can be:

  • A simple type: Basically, these are the common number types (int, long, BigDecimal, etc…) or String.
  • a lookup type: This only a kind of JNDI name alias. Which you can use to have two different names for the same resource
  • An object-factory type: A class which implements javax.naming.spi.ObjectFactory, instantiated once per declared resource and responsible of the instantiation of a custom object.

As you can see, the simple type is quite limited, but I hope that this may evolve depending on needs. So, our last chance to register custom types is to use the object-factory.

Create an URLResourceFactory

To avoid creating one factory class every time you need to bind one URL, the factory will get the value attached to a system property having the same name as the JNDI resource to create URL.Here is what the ResourceURLFactory may look like (some additional checks may help) :

package org.akram.factory;
public class ResourceURLFactory implements ObjectFactory {
  public Object getObjectInstance(Object object, Name name, Context nameCtx,
                                  Hashtable<?,?> environment) throws Exception {
    String urlAsString = System.getProperty(object.toString());
    URL url = new URI(urlAsString).toURL();
    return url;
  }
}

Add it as a module in JBoss

Then, you need to package this class in a jar and add it as a module in AS7:

mvn install
mkdir -p $AS7_HOME/modules/org/akram/factory/main
cp target/url-resource-factory.jar $AS7_HOME/modules/org/akram/factory/main
vi modules/org/akram/factory/main/module.xml

The content of the module.xml file must be the following lines. The dependency to javax.api is required cause the classes of the jar uses this API, so it has to be loaded otherwise, you gill get ClassNotFoundExceptions.

<module xmlns="urn:jboss:module:1.1" name="org.akram.factory">
 <resources>
  <resource-root path="resource-url-factory.jar"/>
 </resources>
 <dependencies>
  <module name="javax.api" />
 </dependencies>
</module>

Bind a new resource using this object-factory

The server can be started now. And, you can try adding the new JNDI binding and a system property with the CLI:

$AS7_HOME/bin/jboss-cli.sh
connect
/subsystem=naming/binding=java:/jboss/exported/myurl:add(binding-type=object-factory, module=org.akram,factory, class=.org.akram.factory.ResourceURLFactory)
/system-property=java:/jboss/exported/myurl:add(value=http://www.myurl.org)

From now, every lookup to java:/jboss/exported/myurl will return a java.net.URL object pointing to http://www.myurl.org.