Implementing Entity Services using NoSQL – Part 4: Java EE
It’s worth noting at this point that it’s not strictly necessary that I use Java EE at all for his kind of R&D work. I don’t need the security or the transaction features that are provided by a JEE server like Glassfish and I could probably use something a little lighter like Tomcat or Jetty. However, I do like the convenience and the features of JEE, and many applications that begin life on an standard Java application server like Tomcat do end up either grafting JEE features into Tomcat (like JAX-WS) or migrating to a full JEE server like Glassfish.
Tomcat’s users do often require JEE features – this was the main reasoning behind starting up the TomEE project at Apache. This project adds JEE Web Profile features into the vanilla Tomcat stack so it can handle things like EJB’s and JAX-WS.
Separating the Business Logic into Beans.
My application already has 2 distinct layers. The first (from the perspective of the consumer) is the web service layer which is tasked with providing all the web service operations and other service specific tasks like handling the custom SOAP headers and messaging metadata that help with problems like idempotency. The last layer is the database access layer which is in charge of communicating with the database and dealing with persistence and retrieval of my Product entities.
The third and final layer that I’m now adding is the middle tier that bridges the previous two – the business logic layer. This layer will be responsible for implementing the rules and decisions of the Product Entity Service such as ensuring that any semantically important information is present, added or validated before a persistence operation is carried out.
One example of this semantically important information is the Products ‘state’. In my model, I allow Products to transition through a number of states in order to maintain a strict product lifecycle. The stages are as follows and are roughly linear in nature (each state follows the last)…
- PROVISIONAL
- STOCKABLE
- SALEABLE
- DISCONTINUED
- REMOVED
In my business logic layer, my Product Manager bean ensures that the state of each entity makes sense for each service operation. For example, if you call the createProduct() operation with a Product, the Product given must have a state of ‘Provisional’. If it doesn’t, my logic will change it so that it does.
These kind of rules are unique to each business so it’s not a one size fits all solution. In the real world, a rules engine or something similar would be ideal as it would allow some additional flexibility in the definition and policing of these rules. However, for my basic R&D needs, this hard-coded solution is fine and adequately demonstrates the reason why it’s good to provide a business logic layer – so that you can separate the business logic ‘concerns’ from the message and database handling logic.
One data model to rule them all.
There is one thing that all these layers have in common and that’s the data (a.k.a Entity) objects that they manage. Product entities are represented by XML, described by XSD’s and referenced by the WSDL. These definitions are turned into Java objects by JAX-WS and these same Java objects are used natively throughout the code thereby avoiding any data model transformation.
This technique is know as ‘transformation avoidance’ is one of the major benefits of this particular style of NoSQL based entity service development technique.
Transformation Avoidance is a best practice which improves a service’s reusability and composability – soapatterns.org.
In essence, with this service development I’ve managed to use these same Java data objects in every layer and yet maintained a true contract-first development approach. That’s really good news for developers. I’ve also avoided the need for the data model transformation layers that often become necessary when you have incompatible data models between messages and databases (bad news for ESB salespeople).
Using NoSQL has also allowed me to totally avoid any SQL DDL for tables and data-relations and I don’t need any complex object mappings such as those required to handle traditional ORM. I can even morph my data model over time without stuff breaking quite so regularly (great for service versioning).
Notes on keeping JEE simple.
In order to cut down on the deployment and configuration hassle associated with JEE I’ve used the new deployment and packing mechanisms that allow you to locatate EJB’s and web applications within the same application WAR file. This makes using JEE features a breeze and greatly simplifies the Maven build as I only use one project and zero deployment descriptors (even web.xml is missing!).
JEE with EJB 3.1 couldn’t be simpler as it’s now based on the use of some very simple Java annotations. For example, specifying a Stateless EJB can be as straightforward as adding the @Stateless annotation to a class. In doing so, you’re telling the application server to deploy the class into a pool in order to make it highly available and wrap calls to its methods in a transaction. As a stateless bean, it will have no concept of a session and will not maintain any state between calls (ideal for stateless services).
@Stateless public class ProductsManager
In order to use this bean from another part of your application (from the @WebService class for example), you’d simply add a reference variable of the correct class type, and annotate that variable with the @EJB annotation. This tells the application server to ‘inject’ and instance of the correct type from the pre-populated bean pool at runtime using a mechanism called dependency injection.
@WebService(...) public class ProductsEntityService implements Products { @EJB private ProductsManager bean; ...
Other useful JEE features.
Message driven beans are great for implementing event driven messaging where persistent and asynchronous communication is required between message producers and consumers. However I probably won’t use them for this particular R&D effort as for my requirements the usecase is too weak to justify the effort (who would I notify about new products?). Besides, the @MessageDriven bean annotation has made this capability very easy to use and it’s a well established and highly reliable feature that’s based on JMS.
EJB 3.1 also allows for a number of new and useful bean types. Singleton beans are singleton classes that are managed by the server and specified using the @Singleton annotation (handy if things like clustered singleton’s are a worry for you). And the @Schedule annotation can be used to generate regular events based on a schedule (such as every Friday at Noon) which can be handy for reporting etc.
Summary
So I now have a fully working n-tier web-service that is capable of persisting, managing and retrieving Product entities using a NoSQL database. Next time I’ll cover the implementation of some more SOA patterns using these technologies. Subscribe to my blog to get a notification when this happens.
Continue to Part 5.
Reference: Implementing Entity Services using NoSQL – Part 4: Java EE from our JCG partner Ben Wilcock at the SOA, BPM, Agile & Java blog.