Wednesday, June 9, 2010

Grizzly Spring and JTA Transactions

If you want to have declarative transactions using the @Transactional annotation in Spring and you are running an embedded Grizzly instance (possibly with Jersey) you are going to have to jump through some hoops. Since I've already had to jump through those hoops allow me to save you the trouble.

Most of this info was gleaned/compiled from Ian Pojman's blog posts: here and here.

First you need to get Grizzly and Spring working happily:


ConfigurableApplicationContext context =
new ClassPathXmlApplicationContext("application-context.xml");
ResourceConfig rc = new DefaultResourceConfig();

IoCComponentProviderFactory factory = new SpringComponentProviderFactory(rc,
context);

final Adapter adapter =
ContainerFactory.createContainer(Adapter.class, rc, factory);

log.info("Starting grizzly...");
SelectorThread threadSelector = GrizzlyServerFactory.create(BASE_URI,
new TransactionalAdapterDecorator(adapter));
//server is now running


And the code for the TransactionalAdapterDecorator:


private static class TransactionalAdapterDecorator implements Adapter {

public static final String JTA_TX = "JTA.TX";

private final Adapter adapter;

private PlatformTransactionManager txManager;

public TransactionalAdapterDecorator(Adapter adapter) {
this.adapter = adapter;
txManager = (PlatformTransactionManager) context.getBean(
"transactionManager");
}

/** allow for pre-request processing */
protected void preRequest(Request req) {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def);
}

public void service(Request req, Response res)
throws Exception {
preRequest(req);
try {
adapter.service(req, res);
} catch (Exception ex) {
log.error("Exception: ", ex);
TransactionStatus status = getCurrentTx(req);
txManager.rollback(status);
}
}

public void afterService(Request req, Response res)
throws Exception {
adapter.afterService(req, res);
TransactionStatus status = getCurrentTx(req);
txManager.commit(status);
}

private TransactionStatus getCurrentTx(Request req) {
TransactionStatus status = (TransactionStatus) req.getAttribute(JTA_TX);
return status;
}

private void setCurrentTx(TransactionStatus status, Request req) {
req.setAttribute(JTA_TX, status);
}
}
}


From here you're on your own.

No comments:

Post a Comment