У меня есть стандартная веб-служба jax-ws, которая использует Spring для DI и Hibernate для персистентности. Теперь в Spring вы обычно заключаете запрос в специальный фильтр и выполняете beginTransaction()
и commit()
/ rollback()
в сеансе Hibernate в зависимости от того, прошло ли выполнение без ошибок или нет.
Однако для мыльного веб-клиента эта цепочка выполнения не используется, и поэтому управление транзакциями не может быть легко настроено подобным образом. Конечно, я также хочу избежать включения каждой из моих @WebMethod
реализаций в
session.beginTransaction();
try {
...
session.commit();
}
catch (RuntimeException e) {
session.rollback();
throw e;
}
поэтому я посмотрел на другие возможности. Очевидно, JSR позволяет настроить SOAPHandler
(через @HandlerChain
), которые перехватывают SOAP-трафик после отправки и до отправки исходящих мыльных сообщений, но мне интересно, нахожусь ли я на правильном пути с этим или делаю это неправильно ...
Ребята, знаете ли вы о других альтернативах?
Я пошел по маршруту SOAPHandler
, и, похоже, он хорошо работает:
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;
}
}
Это мой 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>
Обратная связь приветствуется!