2014-09-08 28 views
11

Devo pubblicare eventi di notifica su sistemi esterni su JMS, quando i dati vengono aggiornati. Id come questo deve essere fatto all'interno della stessa transazione in cui gli oggetti sono impegnati nel database per garantire l'integrità.Gestire gli eventi di applicazione di dati a molla nella transazione

Gli eventi ApplicationLifecycle che emettono spring-data-rest sembra il luogo logico per implementare questa logica.

@org.springframework.transaction.annotation.Transactional 
public class TestEventListener extends AbstractRepositoryEventListener<Object> { 

    private static final Logger LOG = LoggerFactory.getLogger(TestEventListener.class); 

    @Override 
    protected void onBeforeCreate(Object entity) { 
     LOG.info("XXX before create"); 
    } 

    @Override 
    protected void onBeforeSave(Object entity) { 
     LOG.info("XXX before save"); 
    } 

    @Override 
    protected void onAfterCreate(Object entity) { 
     LOG.info("XXX after create"); 
    } 

    @Override 
    protected void onAfterSave(Object entity) { 
     LOG.info("XXX after save"); 
    } 

} 

Tuttavia, questi eventi si verificano prima e dopo l'inizio e il commit del tx.

08 15:32:37.119 [http-nio-9000-exec-1] INFO n.c.v.vcidb.TestEventListener - XXX before create 
08 15:32:37.135 [http-nio-9000-exec-1] TRACE o.s.t.i.TransactionInterceptor - Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save] 



08 15:32:37.432 [http-nio-9000-exec-1] TRACE o.s.t.i.TransactionInterceptor - Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save] 
08 15:32:37.479 [http-nio-9000-exec-1] INFO n.c.v.vcidb.TestEventListener - XXX after create 

Cosa punto di estensione fa primavera-dati-resto hanno per l'aggiunta di un comportamento che eseguirà all'interno della transazione primavera gestito?

+0

Avete capito questo? Affrontare lo stesso problema adesso. – Daniel

+0

Nessuna soluzione ancora ho paura. –

risposta

7

Io uso AOP (pointcut e consigli tx) per risolvere questo problema:

@Configuration 
@ImportResource("classpath:/aop-config.xml") 
public class AopConfig { ... 

e AOP-config.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
         http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop.xsd 
         http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx.xsd" 
    default-autowire="byName"> 

    <aop:config> 
     <aop:pointcut id="restRepositoryTx" 
      expression="execution(* org.springframework.data.rest.webmvc.RepositoryEntityController.*(..))" /> 
     <aop:advisor id="managerTx" advice-ref="txAdvice" pointcut-ref="restRepositoryTx" order="20" /> 
    </aop:config> 

    <tx:advice id="txAdvice" transaction-manager="transactionManager"> 
     <tx:attributes> 
      <tx:method name="postCollectionResource*" propagation="REQUIRES_NEW" rollback-for="Exception" /> 
      <tx:method name="putItemResource*" propagation="REQUIRES_NEW" rollback-for="Exception" /> 
      <tx:method name="patchItemResource*" propagation="REQUIRES_NEW" rollback-for="Exception" /> 
      <tx:method name="deleteItemResource*" propagation="REQUIRES_NEW" rollback-for="Exception" /> 
      <!-- <tx:method name="*" rollback-for="Exception" /> --> 
     </tx:attributes> 
    </tx:advice> 

</beans> 

Questo è lo stesso come essendo metodi controllore annotato con @Transactional.

+0

quando si inserisce testo/uri-list per aggiornare una proprietà incorporata, è necessario includere anche org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.createPropertyReference nella configurazione AOP – Korgen

0

Non ho lavorato su Spring-Data-Rest, ma con la primavera, questo può essere gestito nel modo seguente.

1) Definire TransactionSynchronizationAdapter personalizzato e registrare il bean in TransactionSynchronizationManager.

Di solito, ho un metodo registerSynchronizaiton con un @Before pointcut per questo.

@SuppressWarnings("rawtypes") @Before("@annotation(org.springframework.transaction.annotation.Transactional)") 
    public void registerSynchronization() { 
     // TransactionStatus transStatus = TransactionAspectSupport.currentTransactionStatus(); 
     TransactionSynchronizationManager.registerSynchronization(this); 
     final String transId = UUID.randomUUID().toString(); 
     TransactionSynchronizationManager.setCurrentTransactionName(transId); 
     transactionIds.get().push(transId); 
     if (TransactionSynchronizationManager.isActualTransactionActive() && TransactionSynchronizationManager 
      .isSynchronizationActive() && !TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { 
      if (!TransactionSynchronizationManager.hasResource(KEY)) { 
       final List<NotificationPayload> notifications = new ArrayList<NotificationPayload>(); 
       TransactionSynchronizationManager.bindResource(KEY, notifications); 
      } 
     } 
    } 

2) E, implementare il metodo Override come segue

@Override public void afterCompletion(final int status) { 
    CurrentContext context = null; 
    try { 
     context = ExecutionContext.get().getContext(); 
    } catch (final ContextNotFoundException ex) { 
     logger.debug("Current Context is not available"); 
     return; 
    } 
    if (status == STATUS_COMMITTED) { 
     transactionIds.get().removeAllElements(); 
     publishedEventStorage.sendAllStoredNotifications(); 
     // customize here for commit actions 
    } else if ((status == STATUS_ROLLED_BACK) || (status == STATUS_UNKNOWN)) { 
     // you can write your code for rollback actions 
    } 
} 
+0

Con questo metodo, dove definiamo i metodi che vuoi avvolto nella transazione? –

+0

Siamo spiacenti per la risposta molto tardi, utilizzare AOP per i metodi che richiedono la sincronizzazione transazionale –