Ich entwickle ein Modul für eine OSGi-Anwendung mit Spring MVC und Virgo Webserver.Verwendung von tx: Annotation-Driven verhindert das Autowiren einer Bean
Auf meinem Modul habe ich einen Controller, der auf einen Manager zugreift, der eine Liste von Handlern enthält, die für die Berichterstellung zuständig sind.
Alles lief gut, bis ich eine Transaktionsmethode von einem externen Dienst aufrufen musste. Da keine meiner Klassen transaktional war, musste ich die Referenzen zum Transaktionsmanager und annotation-driven
hinzufügen. Dann wurde mein Manager nicht mehr benachrichtigt.
Ich verstehe, dass bei Verwendung von annotation-driven
alle meine Beans eine öffentliche Schnittstelle implementieren müssen, damit der Proxy-Mechanismus funktioniert. Und soweit ich weiß, sind alle Klassen (einer von ihnen war nicht, aber dann habe ich es geändert).
Meine Konfigurationsdateien sind:
bündel 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>
und mein Bündel-osgi.xml sich wie folgt:
<?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>
, also nach allen Die Dienste werden veröffentlicht Das oSGIChangeReportHandler.register wird aufgerufen (ich kann es debbug):
@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);
}
}
Und obwohl der Debugger Proxies für zeigt sowohl die reportManager
und reportHandler
auf dem register
Methode, der Debugger stoppt nicht an der ReportManagerImpl.addReportHandler
Methode:
@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);
}
}
}
Ich muss betonen, wenn ich entfernen Sie die tx:annotation-driven
Tag Von der Datei bundle-context.xml
funktioniert alles einwandfrei (die handler
wird während des Startvorgangs ordnungsgemäß zur Liste hinzugefügt).
Also, was fehlt mir hier?
Ist 'reportManager' null in 'oSGIChangeReportHandler.register'? – Avi
Nein! Es zeigt ein Proxy-Objekt auf dem Debugger. Aber ich habe das Problem gelöst, die Antwort ist unten. Danke für den Kommentar, tho. :) –