2013-07-02 16 views
5

Sto sviluppando un modulo su un'applicazione OSGi, utilizzando Spring MVC e Virgo Webserver.Utilizzo di tx: annotation-driven impedisce la creazione automatica di un bean

Sul mio modulo ho un controller, che accede a un gestore, che ha un elenco di gestori responsabili della gestione della generazione di report.

Tutto andava bene fino a quando non ho dovuto chiamare un metodo transazionale da un servizio esterno. Poiché nessuna delle mie classi era transazionale, ho dovuto aggiungere i riferimenti al gestore delle transazioni e annotation-driven. Quindi, il mio manager ha smesso di essere informato.

Capisco che quando si utilizza annotation-driven tutti i miei bean devono implementare un'interfaccia pubblica affinché il meccanismo di proxy funzioni. E per quanto ne so, tutte le classi sono (una non era, ma poi l'ho cambiata).

I miei file di configurazione sono:

fascio-context.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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" 
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd 
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> 
<context:annotation-config /> 
<tx:annotation-driven transaction-manager="transactionManager"/> 
<bean id="reportManager" class="reportmodule.manager.impl.ReportManagerImpl"/> 
<bean id="mvpepReportHandler" class="reportmodule.manager.impl.MVPEPReportHandler"/> 
<bean id="reportConfigDao" class="reportmodule.repository.impl.ReportConfigurationHibernateDAOImpl"/> 
<bean id="oSGIChangeReportHandler" class="reportmodule.osgi.impl.OSGIChangeReportHandlerImpl"/> 
<bean id="reportController" 
class="reportmodule.controller.impl.ReportControllerImpl"/> 
<bean id="reportControllerHandlerMapping" 
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> 
<property name="mappings"> 
<value>/module/reportController/**=reportController</value> 
</property> 
<property name="alwaysUseFullPath" value="true"></property> 
</bean> 
</beans> 

e il mio pacco-osgi.xml è la seguente:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:osgi="http://www.springframework.org/schema/osgi" 
xmlns:osgi-compendium="http://www.springframework.org/schema/osgi-compendium" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
http://www.springframework.org/schema/osgi 
http://www.springframework.org/schema/osgi/spring-osgi.xsd 
http://www.springframework.org/schema/osgi-compendium 
http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium-1.2.xsd"> 

<osgi:reference id="transactionManager" interface="org.springframework.transaction.PlatformTransactionManager" /> 
<osgi:reference id="sessionFactory" interface="org.hibernate.SessionFactory" /> 
<osgi:reference id="smaCoreUtilService" interface="core.util.service.SmaCoreUtilService" /> 

<osgi:service ref="reportControllerHandlerMapping" 
interface="org.springframework.web.servlet.HandlerMapping" 
context-class-loader="service-provider" 
auto-export="interfaces"/> 

<osgi:service interface="reportmodule.api.manager.ReportManager" ref="reportManager" auto-export="interfaces"/> 

<osgi:service interface="reportmodule.api.manager.ReportHandler" ref="mvpepReportHandler" auto-export="interfaces"/> 

<osgi:service interface="reportmodule.repository.ReportConfigurationDAO" ref="reportConfigDao" auto-export="interfaces"/> 

<osgi:service interface="reportmodule.osgi.OSGIChangeReportHandler" ref="oSGIChangeReportHandler" auto-export="interfaces"/> 

<osgi:list cardinality="0..N" id="reportHandler" interface="reportmodule.api.manager.ReportHandler" greedy-proxying="true"> 
<osgi:listener ref="oSGIChangeReportHandler" bind-method="register" unbind-method="unregister"/>  
</osgi:list> 

</beans> 

Quindi, dopo tutto i servizi sono stati pubblicati oSGIChangeReportHandler.register è chiamato (sono in grado di scaricarlo):

@Service(value="oSGIChangeReportHandler") 
public class OSGIChangeReportHandlerImpl implements OSGIChangeReportHandler { 

    private ReportManager reportManager; 

    /** 
    * @param reportManager the reportManager to set 
    */ 
    @Autowired 
    public void setReportManager(ReportManager reportManager) { 
     this.reportManager = reportManager; 
    } 

    @SuppressWarnings("rawtypes") 
    public void register(ReportHandler reportHandler, Map properties) { 
     reportManager.addReportHandler(reportHandler); 
    } 

    @SuppressWarnings("rawtypes") 
    public void unregister(ReportHandler reportHandler, Map properties) { 
     reportManager.removeReportHandler(reportHandler); 
    } 


} 

E anche se il debugger mostra proxy sia per il reportManager e reportHandler sul metodo register, il debugger non si ferma sul metodo ReportManagerImpl.addReportHandler:

@Service(value="reportManager") 
@Transactional(propagation = Propagation.MANDATORY, rollbackFor = Exception.class) 
public class ReportManagerImpl implements ReportManager { 

    private ReportConfigurationDAO reportConfigurationDAO; 

    private ArrayList<ReportHandler> reportHandlers = new ArrayList<ReportHandler>(); 

    /** 
    * @param reportConfigurationDAO the reportConfigurationDAO to set 
    */ 
    @Autowired 
    public void setReportConfigurationDAO(ReportConfigurationDAO reportConfigurationDAO) { 
     this.reportConfigurationDAO = reportConfigurationDAO; 
    } 

    @Override 
    @Transactional 
    public InputStream gerarRelatorio(ReportRequest repoReq) throws NegocioException { 
     // Generates the report... 
    } 

    /* (non-Javadoc) 
    * @see reportmodule.api.manager.ReportManager#addReportHandler(reportmodule.api.manager.ReportHandler) 
    */ 
    @Override 
    public void addReportHandler(ReportHandler handler) { 
     if (handler != null) { 
      this.reportHandlers.add(handler); 
     } 
    } 

    /* (non-Javadoc) 
    * @see reportmodule.api.manager.ReportManager#removeReportHandler(reportmodule.api.manager.ReportHandler) 
    */ 
    @Override 
    public void removeReportHandler(ReportHandler handler) { 
     if (handler != null) { 
      this.reportHandlers.remove(handler); 
     } 
    } 

} 

devo sottolineare che quando rimuovo il tag tx:annotation-driven dal file bundle-context.xml, tutto funziona correttamente (lo handler viene correttamente aggiunto all'elenco durante l'avvio).

Quindi, cosa mi manca qui?

+0

è 'reportManager' null in 'oSGIChangeReportHandler.register'? – Avi

+0

No! Mostra un oggetto proxy sul debugger. Ma ho risolto il problema, la risposta è sotto. Grazie per il commento, tho. :) –

risposta

2

Problema risolto!

Come potete vedere sopra il mio codice, stavo definendo i bean sia tramite XML e Annotation, quindi ogni bean è stato duplicato in runtime. Quindi, quando ho aggiunto il tag tx:annotation-driven, l'applicazione ha iniziato a intercettare il bean sbagliato. In effetti stava notificando un fagiolo, ma un fagiolo orfano.