Transaction management in a SOAP server implementation
I have a standard jax-ws webservice set up that uses Spring for DI and Hibernate for persistence. Now in Spring you'd normally wrap your request in a custom filter and execute beginTransaction()
and commit()
/ rollback()
on the Hibernate session depending whether the execution went through without errors or not.
For the soap web client开发者_JAVA技巧 however, this execution chain is not used and therefor no transaction management can easily be set up like this. Of course I also want to avoid wrapping each of my @WebMethod
implementations in
session.beginTransaction();
try {
...
session.commit();
}
catch (RuntimeException e) {
session.rollback();
throw e;
}
so I looked into other possibilities. Apparently the JSR allows to configure SOAPHandler
's (via @HandlerChain
) that intercept SOAP traffic after incoming and before outgoing soap messages are sent, but I wonder if I am on the right track with that or doing it wrong...
Do you guys know of other alternatives?
I went down the SOAPHandler
route and it seems to work nicely:
public class SOAPServiceHandler implements SOAPHandler<SOAPMessageContext>
{
@Override
public void close(MessageContext mc)
{
}
@Override
public boolean handleFault(SOAPMessageContext smc)
{
MyHibernateUtil.rollbackTransaction();
return true;
}
@Override
public boolean handleMessage(SOAPMessageContext smc)
{
Session session = MyHibernateUtil.getCurrentSession();
Boolean outbound = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (!outbound)
{
session.beginTransaction();
session.setFlushMode(FlushMode.COMMIT);
return true;
}
SOAPBody body = null;
try
{
body = smc.getMessage().getSOAPBody();
}
catch (SOAPException e)
{
}
session.flush();
session.setFlushMode(FlushMode.AUTO);
if (body == null || body.hasFault())
{
session.getTransaction().rollback();
}
else
{
session.getTransaction().commit();
}
return true;
}
@Override
public Set<QName> getHeaders()
{
return null;
}
}
This is my applicationContext.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:ws="http://jax-ws.dev.java.net/spring/core"
xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://jax-ws.dev.java.net/spring/core
http://jax-ws.dev.java.net/spring/core.xsd
http://jax-ws.dev.java.net/spring/servlet
http://jax-ws.dev.java.net/spring/servlet.xsd">
<bean id="SoapServiceImpl" class="path.to.SOAPServiceImpl" />
<bean id="SoapServiceHandler" class="path.to.SOAPServiceHandler" />
<wss:binding url="/soap">
<wss:service>
<ws:service bean="#SoapServiceImpl">
<ws:handlers>
<ref bean="SoapServiceHandler" />
</ws:handlers>
</ws:service>
</wss:service>
</wss:binding>
</beans>
Feedback welcome!
精彩评论