Sometimes it can be useful to deploy a JCA connector in a war.
That’s why TomEE got some features related to this need.
The technical part
First you can put the rar directly in WEB-INF/lib. If so keep in mind the rar will be unpacked by default where it is placed (WEB-INF/lib) so to avoid this behavior, set the system property tomee.unpack.dir to another folder (work/ folder is often a good choice).
Another interesting thing is the ability to put a ra.xml in WEB-INF/ folder and then put the adapter in WEB-INF/classes.
And in real? what does it mean?
To be more concrete i’ll take a sample: Hazelcast. Hazelcast is a nice library implementing distributed structures (Map, List, …) and some cloud computing features (behind an ExecutorService). This library provides a JCA connector (hazelcast-ra).
If you define a war with the rar in the lib (whatever how you do) and hazelcast in libraries of the war (not provided by default) you’ll be able to get injected the Hazelcast ConnectionFactory:
import import javax.resource.cci.ConnectionFactory;; [...] @Resource(name = "hazelcast-ra-2.4.1") // name provided by the ra.xml private ConnectionFactory cf;
Then simply use it:
final Connection conn = cf.getConnection(); final LocalTransaction tx = conn.getLocalTransaction(); tw.begin(); someHazelcastMap.put("foo", "bar"); tx.commit(); conn.close();
Here we are, we simply used standard types of the JRE (Map) and JCA API (javax.resource.cci…) but in fact our map is distributed through Hazelcast and transactional through its JCA connector :).
Side note: Hazelcast transaction mecanism can be used without any JCA connector but it is interesting to be able to isolate the Hazelcast part in very few classes (CDI Map producers?) and get a 100% standard code 100%.
Side note 2: the Hazelcast transaction can be managed more easily through a custom CDI interceptor and an interceptor binding @TransactionalMap for instance.
Workaround for Hazelcast
Hazelcast is great but it uses a shutdown hook to shutdown itself (why the connector is often added to the container and not only an application). To workaround it simply add a singleton which will manage the shutdown of Hazelcast:
@Singleton @Startup public class ShutdownHazelcast { @PreDestroy public void shutdown() { for (HazelcastInstance i : Hazelcast.getAllHazelcastInstances()) { i.getLifecycleService().shutdown(); // kill() is a bit more aggressive } } }
Good post – so cannot adopt it to hazelcast 3.1.3,
tomee 1.6.0 root cause:
Caused by: org.apache.tomee.catalina.TomEERuntimeException: org.apache.openejb.OpenEJBException: Can’t find resource for class demo.JcaTest#cf. (No provider available for resource-ref ‘null’ of type ‘javax.resource.cci.ConnectionFactory’ for ‘rest-example.Comp300822365’.)
Changed the hazelcast-ra-2.4.1 string to hazelcast-ra-3.1.3
–> Do you have a hint or idea how to move on?
Also saw your comments and code snippets for hazelcast issue 440 – tried them and
there also seem to be changes since hazelcast 2.x and cannot get them running with hazelcast 3.x.
Also you mention a custom CDI interceptor in this post – do you have source / github link available?
the name to use is logged in the startup logs, did you check it?
about the interceptor just do Exception e = null;begin(); try {proceed(); } catch(Exception ex) {e=ex; rollback(); } finally {if (e == null) commit();}
Thanks for the hint. Checked name and changed it to: hazelcast-ra-3.1.3RA
–> taken from log: Creating Resource(id=hazelcast-ra-3.1.3RA)
Now:
@Resource(name = “hazelcast-ra-3.1.3RA”)
private ConnectionFactory cf;
…
try {
final Connection conn = cf.getConnection();
final LocalTransaction tx = conn.getLocalTransaction();
tx.begin();
// someHazelcastMap.put(“foo”, “bar”);
tx.commit();
conn.close();
} catch( Exception e ) {
System.out.println(“JcaTest:doit – explode”);
}
Results in:
Caused by: org.apache.openejb.OpenEJBException: Can’t find resource for class org.superbiz.rest.service.UserService#cf. (No provider available for resource-ref ‘null’ of type ‘javax.resource.cci.ConnectionFactory’ for ‘rest-example.Comp2003049152’.)
any idea?
If you have a project reproducing it push it on github and send the link to tomee user list.