miércoles, marzo 26, 2014

Apache TomEE + NoSQL (writing your own resources)



@Resource annotation appeared for the first time in Java EE 5 specification.  When you annotate an attribute with @Resource, it will be the container responsible of injecting the requested resource. The typical example is used with DataSource class.

import javax.annotation.Resource;
@Resource(name = "myDataSource")
private DataSource movieDatabase;
view raw DataSource.java hosted with ❤ by GitHub
That's great and you can use it with JMS as well, but what's happening to NoSQL databases, would not it be perfect to do something similar for them?

With Apache TomEE you can do it by providing your own @Resource provider class. In this post we are going to see how you write your own provider for MongoDB so you can use @Resource for MongoDB too.

The first thing to do is create the provider class, which is a simple POJO:

import java.net.UnknownHostException;
import com.mongodb.MongoClient;
public class MongoProvider {
private String address;
private int port;
public MongoClient mongoClient() throws UnknownHostException {
return new MongoClient(address, port);
}
public void setAddress(String address) {
this.address = address;
}
public void setPort(int port) {
this.port = port;
}
}
It is a simple POJO with a method which returns a MongoClient class (the base class for Java MongoDB driver), and setters with required parameters.

Next step is creating a file called resources.xml in WEB-INF directory. In this file we configure TomEE so he knows about the provider/class.

<resources>
<Resource id="mongo" class-name="com.lordofthejars.tomee.jpa.MongoProvider">
address localhost
port 27017
</Resource>
</resources>
view raw resources.xml hosted with ❤ by GitHub
Notice that in this file you set the provider class and how the attributes are set. In fact you set them more or less like a properties file. So when you are are writing address 127.0.0.1, TomEE under the cover will call provider.setAddress("127.0.0.1")

The last thing to do is start using @Resource annotation with MongoDB.

@Resource(name = "mongo")
private MongoProvider mongo;
public void createBookInMongo(Book book) throws Exception {
MongoClient mongoClient = mongo.mongoClient();
}
view raw TestMongo.java hosted with ❤ by GitHub
So in this case we are creating a MongoClient provider because TomEE requires a no parameters constructor, but MongoClient has parameters so we need to create a provider class with a method which returns the MongoClient instance to be used.

And what really is awesome about TomEE is that you can even override your @Resource definitions from system properties, so you can do something like:

-Dmongo.address=localhost

where mongo is the id of the resources file and address the name of the field.

So you can change each of the value in an easy way depending on the environment you are pushing. And that's an awesome thing.

So now there is no excuses to not start treating NoSQL databases like SQL databases from the point of view of Java EE.

[Update] Romain notice me that with latest version of Apache TomEE you don't need a default constructor, parameters are bound directly properties as constructor params

We keep learning,

Alex.

Et j’ai sa main!, Jour prospère!, Me voici, Militaire et mari! (Ah mes amis - Gaetano Donizetti)

Music: https://www.youtube.com/watch?v=3aS6M8j3pvQ