J'ai commencé mon projet en créant des entités, des services et des tests JUnit pour les services utilisant Spring et Hibernate. Tout cela fonctionne très bien. Ensuite, j'ai ajouté spring-mvc pour créer cette application Web à l'aide de nombreux didacticiels étape par étape, mais lorsque j'essaie de créer Controller avec l'annotation @Autowired, j'obtiens des erreurs de Glassfish lors du déploiement. Je suppose que pour une raison quelconque, Spring ne voit pas mes services, mais après de nombreuses tentatives, je ne peux toujours pas le gérer.
Tests pour les services avec
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/beans.xml"})
et
@Autowired
MailManager mailManager;
fonctionne correctement.
Contrôleurs sans @Autowired aussi, je peux ouvrir mon projet dans un navigateur Web sans problème.
/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";
}
}
Erreur:
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)}
Désolé pour beaucoup de code, mais je ne sais plus ce qui peut causer cette erreur.
Ajoutée
J'ai créé l'interface:
@Component
public interface IMailManager {
outils ajoutés:
@Component
@Transactional
public class MailManager extends AbstractManager implements IMailManager {
et changé autowired:
@Autowired
public IMailManager mailManager;
Mais cela génère toujours des erreurs (même lorsque j'ai essayé avec @Qualifier)
..Ne peut pas utiliser automatiquement le champ: public pl.com.radzikowski.webmail.service.IMailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager ...
J'ai également essayé différentes combinaisons de @Component et @Transactional.
Ne devrais-je pas inclure beans.xml dans web.xml d'une manière ou d'une autre?
la source
MailManagerInterface
etIMailManager
? :)IMailManager
partout.<import resource="classpath:/beans.xml"/>
àmvc-dispatcher-servlet.xml
Réponses:
Vous devriez autowire l'interface
AbstractManager
au lieu de la classeMailManager
. Si vous avez différentes implémentations deAbstractManager
vous pouvez écrire@Component("mailService")
puis les@Autowired @Qualifier("mailService")
combiner pour activer automatiquement une classe spécifique.Cela est dû au fait que Spring crée et utilise des objets proxy basés sur les interfaces.
la source
@Autowired AbstractManager[] abstractManagers
ça contient toutes ses implémentations.MailManager
?@Service
classes implémentant la même interface. Les deux sont@Autowired
dans une autre classe. Au départ, cela a causé le même problème que le message d'origine lorsque j'ai utilisé le type de classe spécifique. Suite à cette réponse, j'ai changé pour utiliser le type d'interface avec différents@Qualifier("myServiceA")
et@Qualifier("myServiceB")
, et le problème a été résolu. Merci!J'ai eu cela parce que mes tests n'étaient pas dans le même package que mes composants. (J'avais renommé mon package de composants, mais pas mon package de test.) Et j'utilisais
@ComponentScan
dans ma@Configuration
classe de test , donc mes tests ne trouvaient pas les composants sur lesquels ils s'appuyaient.Donc, revérifiez cela si vous obtenez cette erreur.
la source
@Configuration
classe desrc/main
dedanssrc/test
?Le fait est que le contexte d'application et le contexte d'application Web sont enregistrés dans WebApplicationContext lors du démarrage du serveur. Lorsque vous exécutez le test, vous devez indiquer explicitement les contextes à charger.
Essaye ça:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:/beans.xml", "/mvc-dispatcher-servlet.xml"})
la source
@SpringBootApplication(scanBasePackages = { "com.package.one", "com.package.two" })
J'ai passé beaucoup de temps avec ça! Ma faute! Plus tard, j'ai trouvé que la classe sur laquelle j'ai déclaré l'annotation
Service
ouComponent
était de type abstract. Avait activé les journaux de débogage sur Springframework mais aucun indice n'a été reçu. Veuillez vérifier si la classe est de type abstrait. Si alors, la règle de base appliquée, ne peut pas instancier une classe abstraite.la source
Pouvez-vous essayer d'annoter uniquement votre implémentation concrète avec
@Component
? Peut-être que la réponse suivante pourrait vous aider. C'est un peu un problème similaire. Je mets généralement des annotations Spring dans les classes d'implémentation.https://stackoverflow.com/a/10322456/2619091
la source
J'étais confronté au même problème lors du câblage automatique de la classe à partir de l'un de mes fichiers jar. J'ai résolu le problème en utilisant l'annotation @Lazy:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; @Autowired @Lazy private IGalaxyCommand iGalaxyCommand;
la source
La bonne manière doit être d'autowire AbstractManager, comme Max l'a suggéré, mais cela devrait également fonctionner correctement.
@Autowired @Qualifier(value="mailService") public MailManager mailManager;
et
@Component("mailService") @Transactional public class MailManager extends AbstractManager { }
la source
Je suis tombé dessus récemment, et il s'est avéré que j'ai importé la mauvaise annotation dans ma classe de service. Netbeans a une option pour masquer les déclarations d'importation, c'est pourquoi je ne l'ai pas vu depuis un certain temps.
J'ai utilisé à la
@org.jvnet.hk2.annotations.Service
place de@org.springframework.stereotype.Service
.la source
voir plus cette url:
http://www.baeldung.com/spring-nosuchbeandefinitionexception
la source
<context:component-scan base-package="com.*" />
le même problème est arrivé, je l'ai résolu en gardant les annotations intactes et dans le servlet du répartiteur :: en gardant le scan du paquet de base car
com.*.
cela fonctionnait pour moi.la source
Cela peut vous aider:
J'ai la même exception dans mon projet. Après une recherche, j'ai trouvé qu'il me manquait l'annotation @Service pour la classe où j'implémente l'interface que je veux @Autowired.
Dans votre code, vous pouvez ajouter l'annotation @Service à la classe MailManager.
@Transactional @Service public class MailManager extends AbstractManager implements IMailManager {
la source
@Service
annotation contient@Component
. Avoir les deux est redondant.Au lieu de @Autowire MailManager mailManager, vous pouvez vous moquer du bean comme indiqué ci-dessous:
import org.springframework.boot.test.mock.mockito.MockBean; :: :: @MockBean MailManager mailManager;
En outre, vous pouvez configurer
@MockBean MailManager mailManager;
séparément dans la@SpringBootConfiguration
classe et initialiser comme ci-dessous:@Autowire MailManager mailManager
la source
J'ai rencontré le même problème dans mon application de démarrage de printemps même si les analyses spécifiques de mon package étaient activées comme
@SpringBootApplication(scanBasePackages={"com.*"})
Mais, le problème a été résolu en fournissant
@ComponentScan({"com.*"})
dans ma classe Application.la source
Je suppose que c'est ici
<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>
toutes les annotations sont d'abord désactivées par use-default-filters = "false", puis seule l'annotation @Controller est activée. Ainsi, votre annotation @Component n'est pas activée.
la source
Si vous testez votre contrôleur. N'oubliez pas d'utiliser @WebAppConfiguration sur votre classe de test.
la source
Cela s'est produit parce que j'ai ajouté une dépendance auto-câblée à ma classe de service, mais j'ai oublié de l'ajouter aux simulacres injectés dans mon test d'unité de service.
L'exception de test unitaire semblait signaler un problème dans la classe de service alors que le problème était en fait dans le test unitaire. Rétrospectivement, le message d'erreur m'a dit exactement quel était le problème.
la source