Comencé mi proyecto creando entidades, servicios y pruebas JUnit para servicios usando Spring e Hibernate. Todo esto funciona muy bien. Luego agregué spring-mvc para hacer esta aplicación web usando muchos tutoriales paso a paso diferentes, pero cuando intento crear un controlador con la anotación @Autowired, obtengo errores de Glassfish durante la implementación. Supongo que por alguna razón Spring no ve mis servicios, pero después de muchos intentos todavía no puedo manejarlo.
Pruebas para servicios con
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/beans.xml"})
y
@Autowired
MailManager mailManager;
trabaja apropiadamente.
Controladores sin @Autowired también, puedo abrir mi proyecto en el navegador web sin problemas.
/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)}
Lo siento por mucho código, pero ya no sé qué puede causar ese error.
Adicional
He creado la interfaz:
@Component
public interface IMailManager {
implementos añadidos:
@Component
@Transactional
public class MailManager extends AbstractManager implements IMailManager {
y cambiado autowired:
@Autowired
public IMailManager mailManager;
Pero todavía arroja errores (también cuando lo intenté con @Qualifier)
..No se pudo autowire campo: public pl.com.radzikowski.webmail.service.IMailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager ...
También probé con diferentes combinaciones de @Component y @Transactional.
¿No debería incluir beans.xml en web.xml de alguna manera?
fuente
MailManagerInterface
yIMailManager
? :)IMailManager
todas partes.<import resource="classpath:/beans.xml"/>
amvc-dispatcher-servlet.xml
Respuestas:
Debería conectar automáticamente la interfaz en
AbstractManager
lugar de la claseMailManager
. Si tiene diferentes implementacionesAbstractManager
, puede escribir@Component("mailService")
y luego@Autowired @Qualifier("mailService")
combinar para autowire una clase específica.Esto se debe al hecho de que Spring crea y usa objetos proxy basados en las interfaces.
fuente
@Autowired AbstractManager[] abstractManagers
que contenga todas sus implementaciones.MailManager
?@Service
clases que implementan la misma interfaz. Ambos están@Autowired
en otra clase. Inicialmente causó el mismo problema que la publicación original cuando usé el tipo de clase específico. Después de esta respuesta, cambié para usar el tipo de interfaz con diferentes@Qualifier("myServiceA")
y@Qualifier("myServiceB")
, y el problema se resolvió. ¡Gracias!Esto sucedió porque mis pruebas no estaban en el mismo paquete que mis componentes. (Había cambiado el nombre de mi paquete de componentes, pero no de mi paquete de prueba). Y lo estaba usando
@ComponentScan
en mi@Configuration
clase de prueba , por lo que mis pruebas no encontraban los componentes en los que se basaban.Por lo tanto, vuelva a verificar si obtiene este error.
fuente
@Configuration
clase desdesrc/main
adentrosrc/test
?La cuestión es que tanto el contexto de la aplicación como el contexto de la aplicación web se registran en WebApplicationContext durante el inicio del servidor. Cuando ejecuta la prueba, debe indicar explícitamente qué contextos cargar.
Prueba esto:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:/beans.xml", "/mvc-dispatcher-servlet.xml"})
fuente
@SpringBootApplication(scanBasePackages = { "com.package.one", "com.package.two" })
¡Pasé mucho de mi tiempo con esto! ¡Culpa mía! Más tarde descubrí que la clase en la que declaré la anotación
Service
oComponent
era de tipo abstracto. Había habilitado los registros de depuración en Springframework pero no se recibió ninguna pista. Compruebe si la clase es de tipo abstracto. Si entonces, se aplica la regla básica, no se puede instanciar una clase abstracta.fuente
¿Puedes intentar anotar solo tu implementación concreta con
@Component
? Quizás la siguiente respuesta pueda ayudar. Es un problema similar. Por lo general, pongo anotaciones de Spring en las clases de implementación.https://stackoverflow.com/a/10322456/2619091
fuente
Enfrentaba el mismo problema al cablear automáticamente la clase desde uno de mis archivos jar. Solucioné el problema usando la anotación @Lazy:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; @Autowired @Lazy private IGalaxyCommand iGalaxyCommand;
fuente
La forma correcta será conectar automáticamente AbstractManager, como sugirió Max, pero esto también debería funcionar bien.
@Autowired @Qualifier(value="mailService") public MailManager mailManager;
y
@Component("mailService") @Transactional public class MailManager extends AbstractManager { }
fuente
Me encontré con esto recientemente y resultó que importé la anotación incorrecta en mi clase de servicio. Netbeans tiene una opción para ocultar las declaraciones de importación, por eso no lo vi durante algún tiempo.
He usado en
@org.jvnet.hk2.annotations.Service
lugar de@org.springframework.stereotype.Service
.fuente
ver más esta url:
http://www.baeldung.com/spring-nosuchbeandefinitionexception
fuente
<context:component-scan base-package="com.*" />
Llegó el mismo problema, lo resolví manteniendo las anotaciones intactas y en el despachador servlet :: manteniendo el escaneo del paquete base ya que
com.*.
esto funcionó para mí.fuente
Esto puede ayudarlo a:
Tengo la misma excepción en mi proyecto. Después de buscar, descubrí que me falta la anotación @Service en la clase donde estoy implementando la interfaz que quiero @Autowired.
En su código, puede agregar la anotación @Service a la clase MailManager.
@Transactional @Service public class MailManager extends AbstractManager implements IMailManager {
fuente
@Service
anotación contiene@Component
. Tener ambos es redundante.En lugar de @Autowire MailManager mailManager, puede simular el bean como se indica a continuación:
import org.springframework.boot.test.mock.mockito.MockBean; :: :: @MockBean MailManager mailManager;
Además, puede configurar por
@MockBean MailManager mailManager;
separado en la@SpringBootConfiguration
clase e inicializar como se muestra a continuación:@Autowire MailManager mailManager
fuente
Enfrenté el mismo problema en mi aplicación de arranque de primavera a pesar de que tenía habilitados los escaneos específicos de mi paquete como
@SpringBootApplication(scanBasePackages={"com.*"})
Pero, el problema se resolvió proporcionando
@ComponentScan({"com.*"})
en mi clase de aplicación.fuente
Mi conjetura es que aqui
<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>
todas las anotaciones se desactivan primero mediante use-default-filters = "false" y luego solo se activa la anotación @Controller. Por lo tanto, su anotación @Component no está habilitada.
fuente
Si está probando su controlador. No olvide usar @WebAppConfiguration en su clase de prueba.
fuente
Esto sucedió porque agregué una dependencia cableada automáticamente a mi clase de servicio, pero olvidé agregarla a los simulacros inyectados en mi prueba de unidad de servicio.
La excepción de la prueba unitaria pareció informar un problema en la clase de servicio cuando el problema estaba realmente en la prueba unitaria. En retrospectiva, el mensaje de error me dijo exactamente cuál era el problema.
fuente