I was in the process of doing a major overhaul on my server-side JAX-RS WEB Services and their accompanying persistence services to bring things up to a little more standard approach. In particular my goals were to:
- Utilize more dependency injection (from JSR-299) to avoid having to separately manage my services in a factory.
- Utilize JPA using the JTA transactions and a JDBC datasource (I was previously using
- Inject the EntityManager (or factory - see below)
- Leverage in-container testing using Arquillian for the services (to verify the transactional integrity of the services)
- Clear out remnants and methods from when the services were used by a Swing Application (which was replaced by Stamp Web 1.0 in 2008)
- Leverage MOXy with JAXB for JSON serialization from JAX-RS WEB Services in place o the Jersey implementation with Jackson and mapped notation (which had required me to create custom JABXContext objects, register properties in my custom mapping file etc.)
- Provide a proper JAX-RS implementation using Response Builders. Previously I was returning a JSON object with a success flag instead of using valid HTTP Status objects like NOT_FOUND (404)
- Provide complete testing of all JAX-RS WEB Service methods in particular using both JSON and XML supported content encodings and verifying all response code for non-conditions.
As you can imagine this has turned out not to be a small effort and I have had to learn and re-learn a lot of areas of J2EE I had convienently left behind in my memory space.
The following is probably the most important points to remember when designing an application like this:
- Start small. I didn't simply start modifying my codebase. Instead I started a new project and brought over the highest level concepts (in my case my PersistableObject, AbstractPersistenceService and a few other classes) and built it up from there - testing as I went. This allowed me to verify the new JTA based approach and also let me figure out a few concerns. For example, previously I had to manage all commit/rollback code. Initially I was thinking to mark methods as Transactional and write an interceptor (which led me down a deep hole of Interceptors) only to realize this was not needed in a JTA context.
- Early on I read a blog article that stated that you shouldn't use
@PersistenceContext(injecting an EntityManager) because it wasn't thread safe and should instead use
@PersistenceUnit(injecting an EntityManagerFactory). This seemed like a good idea and worked... until I tried to save 150 stamps (which each created a EntityManager at a lower level of the code). It appears when using JTA and Container Managed transactions (CMT) creating an EntityManager from the factory will establish a different connection in the pool (I couldn't verify this other than I was seeing max-connection errors and deadlocks in my arquillian tests - but only when this test was used). After some reading, I saw that using
@PersistenceContextin CMT it becomes the responsibility of the container to close and manage the EntityManagers. Doing so (in place of using the factory to get a new one) instantly rid me of the connection errors and I see a balance of connection threads - Note the test that hit this is one that never happens in my WEB application (yet) but I am glad to have hit this now - rather than after deploying on my production server.
- Arquillian took a little effort to get completely working right, but now that I have it working it seems to work nicely for testing my services "in context". I am currently testing my WEB Services using the jersey-client module and running them after my application is deployed to glassfish. I do want to do some further experimentation to see if I can use Arquillian for these (this article looks promising: http://www.samaxes.com/2012/05/javaee-testing-introduction-arquillian-shrinkwrap/)
Along with my services, I am actually going to rewrite my client side application from a GWT/GXT 2 based solution to SmartClient JS. I originally was going to convert to GXT 3, but I have become pretty disillusioned with the roadmap from Sencha, and therefore are planning to go with a JS based client application. In order to pace this, I need to keep the existing GXT 2 + WEB Services running (which is why I am creating a new Web application project) and will be converting/creating client portions on a priority basis. As well, from the services perspective I am attempting to capture a new level of test code coverage (before it was about 45% now I am aiming for 70%+). To accomplish this, I am not writign any WEB Services beyond my first one to ferret out the testing/WADL approaches to prevent me from working on the client code until the server is complete and solid.