У меня есть служба сервиса NotificationService. По строкам MailService следует, что сервисный уровень имеет интерфейс NotificationService (определение службы) и класс NotificationServiceUtil (предоставляя услугу статически), и у меня есть слой impl, предоставляющий NotificationServiceImpl (реализация). Затем я зарегистрировал услугу в ext-spring.xml:Как создать метод службы в транзакции liferay без сервисного построителя
<bean id="org.mitre.asias.portal.notification.service.NotificationService"
class="org.mitre.asias.portal.notification.service.impl.NotificationServiceImpl">
...
</bean>
<bean id="org.mitre.asias.portal.notification.service.NotificationServiceUtil"
class="org.mitre.asias.portal.notification.service.NotificationServiceUtil">
<property name="service"
ref="org.mitre.asias.portal.notification.service.NotificationService" />
</bean>
Все работает должным образом, пока я не попытаюсь выбросить транзакции в микс. У меня есть один метод в NotificationServiceImpl, который должен быть транзакционный:
public void sendAndUpdate(Message message, List<Event> eventsToUpdate) throws SystemException, MessagingException {
for (Event event : eventsToUpdate) {
eventLocalService.updateEvent(event);
}
Transport.send(message);
}
Идея заключается в том, что если по какой-то причине отправка сообщения не удалась, изменения в модели объектов будет откат, чтобы я мог повторить отправьте позже. Я попытался аннотировать этот метод с помощью:
@Transactional(isolation = Isolation.PORTAL,
rollbackFor = { PortalException.class, SystemException.class, MessagingException.class })
Но этого не потребовалось. Я попытался переместить эту аннотацию в интерфейс NotificationService, но все равно не кубик. Я включил ведение журнала отладки на org.hibernate.transaction.JDBCTransaction
и может видеть, что транзакция никогда не запускается для вызова этого метода, но один запускается и фиксируется для каждого вызова updateEvent
в цикле.
Порывшись в источнике, по-видимому, что Liferay имеет боб постпроцессор под названием ServiceBeanAutoProxyCreator
, который имеет следующий код:
...
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, TargetSource targetSource)
throws BeansException {
if (beanName.endsWith(_SERVICE_SUFFIX)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
else {
return DO_NOT_PROXY;
}
}
private static final String _SERVICE_SUFFIX = "Service";
...
Что делает вид, будто каждый боб, имя которого оканчивается служба (так как мой боб делает : ...id="org.mitre.asias.portal.notification.service.NotificationService"...
) должны быть обернуты в ServiceBeanAopProxy
который добавит транзакционной совет в соответствии с застройщиком услуг генерироваться base-spring.xml
:
<bean class="com.liferay.portal.spring.aop.ServiceBeanAutoProxyCreator">
<property name="methodInterceptor" ref="serviceAdvice" />
</bean>
<bean class="com.liferay.portal.spring.context.PortletBeanFactoryCleaner" />
<bean class="com.liferay.portal.spring.context.PortletBeanFactoryPostProcessor" />
<bean class="com.liferay.portal.spring.bean.BeanReferenceAnnotationBeanPostProcessor" />
<bean id="portletClassLoader" class="com.liferay.portal.kernel.portlet.PortletClassLoaderUtil" factory-method="getClassLoader" />
<bean id="servletContextName" class="com.liferay.portal.kernel.portlet.PortletClassLoaderUtil" factory-method="getServletContextName" />
<bean id="basePersistence" abstract="true">
<property name="dataSource" ref="liferayDataSource" />
<property name="sessionFactory" ref="liferaySessionFactory" />
</bean>
<bean id="serviceAdvice" class="com.liferay.portal.monitoring.statistics.service.ServiceMonitorAdvice">
<property name="monitoringDestinationName" value="liferay/monitoring" />
<property name="nextMethodInterceptor" ref="asyncAdvice" />
</bean>
<bean id="asyncAdvice" class="com.liferay.portal.messaging.async.AsyncAdvice">
<property name="defaultDestinationName" value="liferay/async_service" />
<property name="nextMethodInterceptor" ref="threadLocalCacheAdvice" />
</bean>
<bean id="threadLocalCacheAdvice" class="com.liferay.portal.cache.ThreadLocalCacheAdvice">
<property name="nextMethodInterceptor" ref="transactionAdvice" />
</bean>
<bean id="transactionAdvice" class="com.liferay.portal.spring.transaction.TransactionInterceptor">
<property name="transactionAttributeSource" ref="transactionAttributeSource" />
<property name="transactionManager" ref="liferayTransactionManager" />
</bean>
<bean id="transactionAttributeSource" class="com.liferay.portal.spring.transaction.AnnotationTransactionAttributeSource" />
кто-нибудь есть какие-либо идеи как я мог бы сделать эту работу?
Я использую Liferay 6.0 EE sp2 в контейнере tomcat 6.0.32.