Skip to content

Come back Gavin King, all is forgiven (Spring is the new EJB 2.1)

I’ve just spent the past two days trying to make Spring transaction management work with JPA-annotated Hibernate-backed persistence classes that need to have multiple persistence units with transaction propagation REQUIRES_NEW between the two.

For a start, the documentation is merely a series of outlines of brief hints. One measly section.The laughably short Spring 3 doco section “Dealing with multiple persistence units” conveniently omits  the transaction manager configuration from the example. The problem appears to be that the JPA transaction manager only (and compulsorily) deals with one entity manager factory. And an entity manager factory only deals with one persistence unit. So therefore you have to have two JPA transaction managers. Which means the two persistence unit transactions won’t co-operate properly even though they may share the underlying datasource and are configured through the single persistence unit manager bean.

The above scenario is totally trivial in an EJB 3 container backed with Hibernate, or Eclipselink, as the provider. About one-quarter of the configuration. If I have to use a JTA transaction manager obtained by JNDI lookup from the container, to run a transaction across two JPA persistence units which share the same underlying datasource, why the hell am I using Spring in the first place?

All I wanted was to isolate one set of db transactions from another, use JPA persistence units so the two sets of tables could live easily in two different schemas, and use the annotations to kill the fragile AOP regex-like-but-not-like-regex class and method pattern-matching jiggery pokery from the Spring configuration.

My god, this is such a stonkingly non-trivial forest of horrible configuration and a trial and error morass of filthy swamp miasma … an equivalent EJB3 backed by Hibernate JPA set up is, by comparison, an almost effortless task. I can produce a unit-tested all singing all dancing multiple persistence unit JPA app running in an EJB 3 container with XA datasources using Hibernate as the JPA implementation in almost no time at all. Getting the same thing with Spring (oh, and running some tests with Jetty inside Maven) is like having all your teeth pulled while you’re coming down from a three day methamphetamine binge. Getting Spring to run with multiple JPA persistence units on the same JDBC connection (without XA, across the same database connection) with a transaction propagation of REQUIRES_NEW on the entry point of one of the units is a hair-pulling, beard-greying, head-desk banging, co-worker punching, drunken ranting, blood-pressure raising experience of pure horror. Which apparently doesn’t end.

Die, Spring, die. Can’t come soon enough as far as I am concerned. It’s more evil than Oracle. At least you know with Oracle you’re in for an un-lubed hard and fast backdoor job from Ellison with no reach-around before you even unpack the box. Spring is like a beautiful young sexy soft-porn film that turns into some relentlessly horrific succubus-filled horror film half way through.

Seriously, its enough to make one pine for bloody Weblogic. Spring is the new EJB 2.1.



    Grab the JTA transaction manager from the container, or drop in a 3rd-party one. It’s not hard. The JTA transaction manager replaces the JPA ones.

    The reason it’s trivial in EJB3 is that the stack is required to give you a JTA transaction manager – Spring gives you the option of not requiring that, that’s all.

    Wednesday, February 16, 2011 at 23:37 | Permalink
  2. Ryan wrote:

    Its nice to see that I’m not the only developer who wanted to use Spring in place of the EJB 3.0 container, and use it with multiple JTA managed transactions, JTA DataSources managed by a Java EE 5 app server, and found the required Spring configuration to be a complete nightmare. I went through exactly the same crap you did following a series of half clues in Spring documentation, forums, Google, etc. I didn’t waste days though, I wasted weeks (not all at once). You probably came across many of my forum postings and possibly my solution on my blog. Nobody in the Spring forums had an answer, and the zealots that didn’t like me ragging on Spring threw me under a bus.

    Now that EJB 3.1 works in the web container, supports singleton beans, and now that CDI is here, I’m going to give it a serious look for use on green field projects. For the purpose of container managed transactions and dependency injection, I suspect Spring is no longer needed unless you are a masochist.

    Thursday, February 17, 2011 at 00:16 | Permalink
  3. Ryan wrote:

    BTW in the end my solution was pretty clean. It involved abandoning most or all of Spring’s internal JPA support and pointing it to the one managed my by Java EE app server:

    That solved a whole stack of problems I had with Spring and multiple JPA JTA datasources, multiple transactions, etc.

    Thursday, February 17, 2011 at 00:30 | Permalink
  4. Scot Mcphee wrote:

    Robert and Ryan,

    Thanks for your comments – I realise that the solution is to use the JTA transaction from the app server. The fly in that ointment is using it with Jetty for and configuring a transaction manager (I believe Tomcat has the same problem). Have you seen those transaction managers like JOTM? uuuuggghhh…

    So its not all Spring’s fault to be sure but the whole area is a morass of pain.

    Thursday, February 17, 2011 at 06:22 | Permalink
  5. Ryan wrote:

    @Scott: I realize Spring is useful or even necessary when using a barebones servlet container.

    The conclusion I came to is that you usually end up building your own Java EE application server anyway with nearly 1:1 mapping of technologies, but it is much easier and quicker to use a Java EE app server because everything is pre-integrated out of the box and just works. Plus the one I use is free/open source, starts very fast, and only uses memory for features I use.

    Thursday, February 17, 2011 at 06:45 | Permalink
  6. What are you using Jetty for? If it’s just for a developer build, you may be able to get away with faking the transactional support – point at a dev database where the tables are all in one schema. Yes, the difference may be a source of bugs, but you can address that by focusing on external integration tests against the app-server deployed version.

    One of the stronger advantages of Spring is the ability to easily configure a development wiring vs a production wiring, similar to Rails’ environment concept.

    Thursday, February 17, 2011 at 07:25 | Permalink
  7. Scot Mcphee wrote:

    Robert, Ryan is right. You end with a duplicate configuration which is more or less like a JEE app server config anyway.

    The issue with Jetty is that previously – when the datasource only was obtained from JNDI – the same configuration worked in Jetty as Glassfish. The JNDI resource just pointed elsewhere.

    Now, all the transaction managers and so forth have to manually configured in a different set of configuration files to run in Jetty. And **EVEN THEN** it still would not work trivially, because in one set of DAOs there’s this;

    EntityManager em;

    and in another set there’s this;

    EntityManager em;

    Which means, in the persistence.xml, there has to be two units defined with that name.

    And then the pain starts. Spring support of multiple persistence units is totes a pain in the butt.

    Thursday, February 17, 2011 at 11:00 | Permalink
  8. It works fine for me, with only a couple of lines – but I’m not span transactions of my multiple data sources. Still, it sounds like your issue isn’t Spring as such (which works fine if you have a JTA transaction manager available to you), but the container you are trying to deploy too, which doesn’t.

    So you’re complaining that you’re trying to do something which is possible, but annoying, under Spring (deploy to Jetty/Tomcat), but impossible at all with EJB 3.

    If you want to do an apples-to-apples comparison, you really should take Jetty out of the picture.

    Thursday, February 17, 2011 at 11:08 | Permalink
  9. Scot Mcphee wrote:

    Oh that annotation should be @PersistenceContext(unitName=”…”)

    Another thing is “the ability to easily configure a development wiring vs a production wiring”

    We are probably going to try out embedded Glassfish and see if it can be run up under Maven for tests. However, in the JEE world the “development wiring” is done by pointing your JNDI resources to a different context. So the question is – different app servers all of which have a local per-environment configuration, which is trivially different, or … tons and tons of XML configuration that radically changes from environment to environment …

    Thursday, February 17, 2011 at 11:11 | Permalink
  10. Scot Mcphee wrote:

    The thing I find is that Spring itself is horrible to configure.

    What am I gaining using Spring AT ALL as opposed to just writing an EJB in EJB3 syntax?

    The fact that I could theoretically, deploy my app in a servlet container like Jetty or Tomcat is **supposed to be the big advantage** … but not if you want to use two persistence units or have XA transactions.

    In other words, in my view, it’s another of these technologies that works great for “hello world” applications (web app, one datasource … which admittedly is most web apps) but its complexity past that point quickly gets logarithmic. On the other hand the JEE application server world looks like overkill if you are just have that “hello world” application, but once over that hump … more features (like multiple persistence units, or XA transactions) are easily added by practically just altering the server configuration.

    Thursday, February 17, 2011 at 11:18 | Permalink
  11. Or you could take the same Spring configuration that works in glassfish and rather than unpacking it like crazy, you add in a 3rd-party JTA Transaction Manager…

    But what I can’t do in EJB land, which Spring does let me do, is bring up my application in a mode which I drop in test stubs – e.g. emulate a service that, in prod, does a call out to a remote server but that in dev just produces an extra environmental issue to manage. This is trivial in Spring simply by breaking the config up into sub files and using a system property to determine which configuration to import.

    Thursday, February 17, 2011 at 11:26 | Permalink
  12. Ryan wrote:

    I haven’t tried any of these yet, but I know CDI has built-in support for test environments, EJB 3.1 has spec defined APIs for use in unit tests, and Arquillian is supposed to be the next-gen in-container testing framework for Java EE 6 apps:

    Thursday, February 17, 2011 at 12:10 | Permalink
  13. Scot Mcphee wrote:

    Oh man, a 3rd party TX manager in Jetty? Have you tried it?

    And you can unit test @EJB annotated services with normal mocks in regular unit tests.

    Reviewing out Spring cfg now, it’s just a bit of wiring services together which is accomplished trivially … there’s only one really important “springly” bit of code where we are using a post-processor to wire multiple anonymous config-driven children context instances of the same bit of spring application context for each. That would be hard if not impossible to do with EJB3 but dependency injection is not an issue anymore.

    Thursday, February 17, 2011 at 17:55 | Permalink
  14. I’ve been playing with Arquillian, and it is definitely not ready yet. It does not yet supply all your ‘compile’ dependencies from maven and you have to add the JARs manually via the EAR shrink wrap API, which was quite undocumented from when I last checked. The API is still evolving.

    Try embedded Glassfish 3.1- that is what is working for me, but I’m still figuring out how to set up test persistence units cleanly (I’m an EJB 3.1 newbie).

    I don’t hate spring, but I’m quite bored with the config (I’m not such a fan of @Configuration – EJB3.1 annotations are much nicer than Springs). One thing spring does nicely as far as transactions go? It lets you set the serialisation strategy per method, and also lets you set up the ‘readOnly’ flag. EJB doesn’t let you set up the serialisation strategy, but you can achieve the readOnly thing by setting PROPAGATION.SUPPORTS

    Also, JPA2 is lacking ‘scrollable result sets’ – and you may have to resort to the underlying native ORM API (via em.getDelegate()) – which is ugly. The other way is to have two separate queries (one to fetch the count, the other to fetch the page of results).

    But, I’m still going with JPA2. The criteria api is very thorough and lets you do complex joins, something which was lacking out of the Hibernate criteria api.

    Friday, April 15, 2011 at 22:18 | Permalink
  15. Scot Mcphee wrote:

    William, thanks for the tip on Arquillian, it looks interesting. We ended up using the embedded glassfish plugin, but vers 3.0, I can’t remember what exactly, but there was a difference in 3.1 that stopped us from using it.

    We are using Spring 3 with JPA2 (Hibernate as the provider) and JTA transactions out of the container.

    Saturday, April 16, 2011 at 09:42 | Permalink