J'ai démarré mon projet en créant des entités, des services et des tests JUnit pour les services utilisant Spring et Hibernate. Tout cela fonctionne à merveille . Ensuite, j'ai ajouté spring-mvc pour créer cette application Web à l'aide de nombreux didacticiels pas à pas, mais lorsque j'essaie de créer Controller avec l'annotation @Autowired, je reçois erreurs de Glassfish lors du déploiement. Je suppose que, pour une raison quelconque, Spring ne voit pas mes services, mais après plusieurs tentatives, je ne peux toujours pas le gérer.
Tests de 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 il y a toujours des erreurs (aussi quand j'ai essayé avec @Qualifier)
..Le champ ne peut pas être autowire: 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.
Est-ce que je ne devrais pas inclure beans.xml dans web.xml?
Vous devez utiliser autowire interface AbstractManager
au lieu de la classe MailManager
. Si vous avez différentes implémentations de AbstractManager
, vous pouvez écrire la combinaison @Component("mailService")
et ensuite @Autowired @Qualifier("mailService")
pour classer automatiquement une classe.
Cela est dû au fait que Spring crée et utilise des objets proxy basés sur les interfaces.
Cela m'est arrivé 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 comme j'utilisais @ComponentScan
dans ma classe de test @Configuration
, mes tests ne trouvaient pas les composants sur lesquels ils s'appuyaient.
Donc, vérifiez que si vous obtenez cette erreur.
Le fait est que le contexte d'application et le contexte d'application Web sont tous deux 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"})
J'ai passé beaucoup de temps avec ça! Ma faute! Plus tard, j'ai découvert que la classe sur laquelle j'avais déclaré l'annotation Service
ou Component
était de type abstract Avait activé les journaux de débogage sur Springframework mais aucun indice n’avait é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 manière correcte doit être de signer automatiquement AbstractManager, comme le suggère Max, mais cela devrait également fonctionner correctement.
@Autowired
@Qualifier(value="mailService")
public MailManager mailManager;
et
@Component("mailService")
@Transactional
public class MailManager extends AbstractManager {
}
Pouvez-vous essayer d'annoter uniquement votre implémentation concrète avec @Component
? Peut-être que la réponse suivante answer 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.
J'ai récemment rencontré ce problème et, en fin de compte, j'ai importé la mauvaise annotation dans ma classe de service. Netbeans a une option pour masquer les instructions d'importation, c'est pourquoi je ne l'ai pas vue depuis un certain temps.
J'ai utilisé @org.jvnet.hk2.annotations.Service
au lieu de @org.springframework.stereotype.Service
.
Cela peut vous aider:
J'ai la même exception dans mon projet. Après avoir cherché et constaté que l'annotation @Service de la classe où je suis en train d'implémenter l'interface que je souhaite @Autowired manquait.
Dans votre code, vous pouvez ajouter l'annotation @Service à la classe MailManager.
@Transactional
@Service
public class MailManager extends AbstractManager implements IMailManager {
voir plus cette url:
http://www.baeldung.com/spring-nosuchbeandefinitionexception
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 uniquement l'annotation @Controller activée. Ainsi, votre annotation @Component n'est pas activée.
Au lieu de @Autowire MailManager mailManager, vous pouvez simuler le bean comme indiqué ci-dessous:
import org.springframework.boot.test.mock.mockito.MockBean;
::
::
@MockBean MailManager mailManager;
De plus, vous pouvez configurer @MockBean MailManager mailManager;
séparément dans la classe @SpringBootConfiguration
et l'initialiser comme ci-dessous:
@Autowire MailManager mailManager
Je faisais face 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;
Si vous testez votre contrôleur… .. N'oubliez pas d'utiliser @WebAppConfiguration sur votre classe de test.
Cela est dû au fait que j'ai ajouté une dépendance auto-câblée à ma classe de service, mais que 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 qu'il était en réalité dans le test unitaire. Rétrospectivement, le message d'erreur m'a dit exactement quel était le problème.
J'ai rencontré le même problème dans mon application de démarrage printanier même si les analyses spécifiques à mon paquetage étaient activées comme
@SpringBootApplication(scanBasePackages={"com.*"})
Mais le problème a été résolu en fournissant @ComponentScan({"com.*"})
dans ma classe d'application.
<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 dispatcher servlet :: en conservant l'analyse du paquet de base comme com.*.
, cela a fonctionné pour moi.