0

У меня есть служба сервиса 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.

ответ

0

Попробуйте переместить @Transactional аннотацию к интерфейсу (не на методе интерфейса)

Liferay оборачивает операции над бобами, имена которых оканчиваются службы (зависит от имени боба не имя класса).

Также проблема может заключаться в размещении кода. Где вы определяете свой bean-компонент? Полагаю, в экструпине? Если вам нравится продлить транзакцию Liferay в вашем собственном портлете без сервис-строителя, это может стать сложным. Тем не менее, в 6.1 можно использовать контекст весны Лиферэй.

 Смежные вопросы

  • Нет связанных вопросов^_^