Ich habe mein Projekt mit dem Erstellen von Entitäten, Diensten und JUnit-Tests für Dienste mit Spring und Hibernate begonnen. All dies funktioniert großartig. Dann habe ich spring-mvc hinzugefügt, um diese Webanwendung mit vielen verschiedenen Schritt-für-Schritt-Anleitungen zu erstellen. Wenn ich jedoch versuche, Controller mit @ Autowired-Annotation zu erstellen, werden während der Bereitstellung Fehler von Glassfish angezeigt. Ich denke, dass Spring aus irgendeinem Grund meine Dienste nicht sieht, aber nach vielen Versuchen kann ich immer noch nicht damit umgehen.
Tests für Dienste mit
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/beans.xml"})
und
@Autowired
MailManager mailManager;
Funktioniert einwandfrei.
Controller auch ohne @Autowired kann ich mein Projekt problemlos im Webbrowser öffnen.
/src/main/resources/beans.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:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
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/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd">
<context:property-placeholder location="jdbc.properties" />
<context:component-scan base-package="pl.com.radzikowski.webmail">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!--<context:component-scan base-package="pl.com.radzikowski.webmail.service" />-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- Persistance Unit Manager for persistance options managing -->
<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="defaultDataSource" ref="dataSource"/>
</bean>
<!-- Entity Manager Factory for creating/updating DB schema based on persistence files and entity classes -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager"/>
<property name="persistenceUnitName" value="WebMailPU"/>
</bean>
<!-- Hibernate Session Factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--<property name="schemaUpdate" value="true" />-->
<property name="packagesToScan" value="pl.com.radzikowski.webmail.domain" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
</bean>
<!-- Hibernate Transaction Manager -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Activates annotation based transaction management -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
/webapp/WEB-INF/web.xml
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="WebApp_ID" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring Web MVC Application</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
/webapp/WEB-INF/mvc-dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="pl.com.radzikowski.webmail" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
pl.com.radzikowski.webmail.service.AbstractManager
package pl.com.radzikowski.webmail.service;
import org.apache.log4j.Logger;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Master Manager class providing basic fields for services.
* @author Maciej Radzikowski <[email protected]>
*/
public class AbstractManager {
@Autowired
protected SessionFactory sessionFactory;
protected final Logger logger = Logger.getLogger(this.getClass());
}
pl.com.radzikowski.webmail.service.MailManager
package pl.com.radzikowski.webmail.service;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
@Transactional
public class MailManager extends AbstractManager {
// some methods...
}
pl.com.radzikowski.webmail.HomeController
package pl.com.radzikowski.webmail.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import pl.com.radzikowski.webmail.service.MailManager;
@Controller
@RequestMapping("/")
public class HomeController {
@Autowired
public MailManager mailManager;
@RequestMapping(value = "/", method = RequestMethod.GET)
public String homepage(ModelMap model) {
return "homepage";
}
}
Error:
SEVERE: Exception while loading the app
SEVERE: Undeployment failed for context /WebMail
SEVERE: Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public pl.com.radzikowski.webmail.service.MailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pl.com.radzikowski.webmail.service.MailManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Entschuldigung für viel Code, aber ich weiß nicht mehr, was diesen Fehler verursachen kann.
Hinzugefügt
Ich habe die Schnittstelle erstellt:
@Component
public interface IMailManager {
Geräte hinzugefügt:
@Component
@Transactional
public class MailManager extends AbstractManager implements IMailManager {
und automatisch verdrahtet geändert:
@Autowired
public IMailManager mailManager;
Aber es gibt immer noch Fehler (auch wenn ich es mit @Qualifier versucht habe)
..Kann nicht automatisch verdrahtet werden: public pl.com.radzikowski.webmail.service.IMailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager ...
Ich habe es auch mit verschiedenen Kombinationen von @Component und @Transactional versucht.
Sollte ich beans.xml nicht irgendwie in web.xml aufnehmen?
quelle
MailManagerInterface
und zu verlassenIMailManager
? :)IMailManager
überall.<import resource="classpath:/beans.xml"/>
zumvc-dispatcher-servlet.xml
Antworten:
Sie sollten die Autowire-Schnittstelle
AbstractManager
anstelle der Klasse verwendenMailManager
. Wenn Sie unterschiedliche Implementierungen habenAbstractManager
, können Sie schreiben@Component("mailService")
und dann@Autowired @Qualifier("mailService")
kombinieren, um eine bestimmte Klasse automatisch zu verdrahten.Dies liegt an der Tatsache, dass Spring Proxy-Objekte basierend auf den Schnittstellen erstellt und verwendet.
quelle
@Autowired AbstractManager[] abstractManagers
, das alle seine Implementierungen enthält.MailManager
?@Service
Klassen, die dieselbe Schnittstelle implementieren. Beide sind@Autowired
in einer anderen Klasse. Anfangs verursachte es das gleiche Problem wie der ursprüngliche Beitrag, als ich den spezifischen Klassentyp verwendete. Nach dieser Antwort habe ich den Schnittstellentyp mit einem anderen@Qualifier("myServiceA")
und verwendet@Qualifier("myServiceB")
und das Problem wurde behoben. Vielen Dank!Ich hatte dies geschehen, weil meine Tests nicht im selben Paket wie meine Komponenten waren. (Ich hatte mein Komponentenpaket umbenannt, aber nicht mein Testpaket.) Und ich habe es
@ComponentScan
in meinem Test verwendet@Configuration
, sodass meine Tests nicht die Komponenten fanden, auf die sie sich stützten.Überprüfen Sie dies, wenn Sie diesen Fehler erhalten.
quelle
@Configuration
Klasse vonsrc/main
insrc/test
?Die Sache ist, dass sowohl der Anwendungskontext als auch der Webanwendungskontext während des Serverstarts im WebApplicationContext registriert werden. Wenn Sie den Test ausführen, müssen Sie explizit angeben, welche Kontexte geladen werden sollen.
Versuche dies:
quelle
Ich habe viel Zeit damit verbracht! Mein Fehler! Später stellte ich fest, dass die Klasse, für die ich die Anmerkung deklarierte
Service
oderComponent
vom Typ abstrakt war. Hatte Debug-Protokolle in Springframework aktiviert, aber es wurde kein Hinweis empfangen. Bitte überprüfen Sie, ob die Klasse vom abstrakten Typ ist. Wenn dann die angewandte Grundregel eine abstrakte Klasse nicht instanziieren kann.quelle
Können Sie versuchen, nur Ihre konkrete Implementierung mit zu
@Component
kommentieren? Vielleicht könnte die folgende Antwort helfen. Es ist ein ähnliches Problem. Normalerweise füge ich Spring-Annotationen in die Implementierungsklassen ein.https://stackoverflow.com/a/10322456/2619091
quelle
Ich hatte das gleiche Problem, als ich die Klasse automatisch aus einer meiner JAR-Dateien verdrahtete. Ich habe das Problem mithilfe der @ Lazy-Annotation behoben:
quelle
Der richtige Weg sollte sein, AbstractManager automatisch zu verdrahten, wie Max vorgeschlagen hat, aber dies sollte auch gut funktionieren.
und
quelle
Ich bin kürzlich darauf gestoßen, und wie sich herausstellte, habe ich die falsche Anmerkung in meine Serviceklasse importiert. Netbeans hat die Option, Importanweisungen auszublenden. Deshalb habe ich sie einige Zeit nicht gesehen.
Ich habe verwendet
@org.jvnet.hk2.annotations.Service
statt@org.springframework.stereotype.Service
.quelle
mehr sehen diese URL:
http://www.baeldung.com/spring-nosuchbeandefinitionexception
quelle
Das gleiche Problem ist aufgetreten. Ich habe es gelöst, indem ich die Anmerkungen intakt gehalten und im Dispatcher- Servlet :: den Basispaket-Scan beibehalten habe, da
com.*.
dies für mich funktioniert hat.quelle
Dies kann Ihnen helfen:
Ich habe die gleiche Ausnahme in meinem Projekt. Nach der Suche habe ich festgestellt, dass mir die Annotation @Service für die Klasse fehlt, in der ich die Schnittstelle implementiere, die ich @Autowired verwenden möchte.
In Ihrem Code können Sie die Annotation @Service zur MailManager-Klasse hinzufügen.
quelle
@Service
Anmerkung enthält@Component
. Beides zu haben ist überflüssig.Anstelle von @Autowire MailManager mailManager können Sie die Bean wie folgt verspotten:
Sie können
@MockBean MailManager mailManager;
die@SpringBootConfiguration
Klasse auch separat konfigurieren und wie folgt initialisieren:quelle
Ich vermute, das hier
Alle Annotationen werden zuerst durch use-default-filter = "false" deaktiviert und dann nur die @ Controller-Annotation aktiviert. Daher ist Ihre @ Component-Annotation nicht aktiviert.
quelle
Wenn Sie Ihren Controller testen. Vergessen Sie nicht, @WebAppConfiguration für Ihre Testklasse zu verwenden.
quelle
Dies geschah, weil ich meiner Serviceklasse eine automatisch verdrahtete Abhängigkeit hinzugefügt habe, aber vergessen habe, sie in meinem Serviceeinheitentest zu den injizierten Mocks hinzuzufügen.
Die Unit-Test-Ausnahme schien ein Problem in der Serviceklasse zu melden, als das Problem tatsächlich im Unit-Test lag. Rückblickend sagte mir die Fehlermeldung genau, was das Problem war.
quelle
Das gleiche Problem trat in meiner Spring-Boot-Anwendung auf, obwohl ich meine paketspezifischen Scans wie aktiviert hatte
Das Problem wurde jedoch durch Angabe
@ComponentScan({"com.*"})
in meiner Anwendungsklasse behoben .quelle