Comecei meu projeto criando entidades, serviços e testes JUnit para serviços usando Spring e Hibernate. Tudo isso funciona muito bem. Em seguida, adicionei spring-mvc para fazer este aplicativo da web usando muitos tutoriais passo a passo diferentes, mas quando estou tentando fazer Controller com a anotação @Autowired, recebo erros do Glassfish durante a implantação. Acho que por algum motivo o Spring não vê meus serviços, mas depois de muitas tentativas ainda não consigo lidar com isso.
Testes de serviços com
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/beans.xml"})
e
@Autowired
MailManager mailManager;
funciona corretamente.
Controladores sem @Autowired também, posso abrir meu projeto no navegador da web sem 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";
}
}
Erro:
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)}
Desculpe por muito código, mas não sei mais o que pode causar esse erro.
Adicionado
Eu criei a interface:
@Component
public interface IMailManager {
implementos adicionados:
@Component
@Transactional
public class MailManager extends AbstractManager implements IMailManager {
e mudou autowired:
@Autowired
public IMailManager mailManager;
Mas ainda gera erros (também quando tentei com @Qualifier)
..Não foi possível fazer o autowire: public pl.com.radzikowski.webmail.service.IMailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager ...
Eu tentei com diferentes combinações de @Component e @Transactional também.
Não devo incluir beans.xml em web.xml de alguma forma?
fonte
MailManagerInterface
eIMailManager
? :)IMailManager
toda parte.<import resource="classpath:/beans.xml"/>
amvc-dispatcher-servlet.xml
Respostas:
Você deve fazer o autowire da interface em
AbstractManager
vez da classeMailManager
. Se você tiver diferentes implementações de,AbstractManager
você pode escrever@Component("mailService")
e, em seguida,@Autowired @Qualifier("mailService")
combiná-las para conectar automaticamente uma classe específica.Isso se deve ao fato de que o Spring cria e usa objetos proxy com base nas interfaces.
fonte
@Autowired AbstractManager[] abstractManagers
que contenha todas as suas implementações.MailManager
?@Service
classes implementando a mesma interface. Ambos estão@Autowired
em outra classe. Inicialmente, isso causou o mesmo problema da postagem original, quando usei o tipo de classe específico. Seguindo esta resposta, mudei para usar o tipo de Interface com diferente@Qualifier("myServiceA")
e@Qualifier("myServiceB")
, e o problema foi resolvido. Obrigado!Eu fiz isso acontecer porque meus testes não estavam no mesmo pacote que meus componentes. (Eu havia renomeado meu pacote de componentes, mas não meu pacote de teste.) E eu estava usando
@ComponentScan
em minha@Configuration
classe de teste , então meus testes não estavam encontrando os componentes nos quais confiavam.Portanto, verifique se você receber esse erro.
fonte
@Configuration
classe desrc/main
emsrc/test
?O fato é que tanto o contexto do aplicativo quanto o contexto do aplicativo da web são registrados no WebApplicationContext durante a inicialização do servidor. Ao executar o teste, você deve informar explicitamente quais contextos carregar.
Experimente isto:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:/beans.xml", "/mvc-dispatcher-servlet.xml"})
fonte
@SpringBootApplication(scanBasePackages = { "com.package.one", "com.package.two" })
Passei muito do meu tempo com isso! Foi mal! Posteriormente descobri que a classe na qual declarei a anotação
Service
ouComponent
era do tipo abstrato. Habilitou logs de depuração no Springframework, mas nenhuma dica foi recebida. Verifique se a classe é do tipo abstrato. Se então, a regra básica aplicada, não pode instanciar uma classe abstrata.fonte
Eu estava enfrentando o mesmo problema ao fazer a fiação automática da classe de um de meus arquivos jar. Corrigi o problema usando a anotação @Lazy:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; @Autowired @Lazy private IGalaxyCommand iGalaxyCommand;
fonte
Você pode tentar anotar apenas sua implementação concreta com
@Component
? Talvez a seguinte resposta possa ajudar. É um problema semelhante. Normalmente coloco anotações do Spring nas classes de implementação.https://stackoverflow.com/a/10322456/2619091
fonte
A maneira correta é autowire AbstractManager, como Max sugeriu, mas isso deve funcionar bem também.
@Autowired @Qualifier(value="mailService") public MailManager mailManager;
e
@Component("mailService") @Transactional public class MailManager extends AbstractManager { }
fonte
Corri para isso recentemente e, como descobri, importei a anotação errada em minha classe de serviço. O Netbeans tem a opção de ocultar as declarações de importação, por isso não o via há algum tempo.
Eu usei em
@org.jvnet.hk2.annotations.Service
vez de@org.springframework.stereotype.Service
.fonte
veja mais neste url:
http://www.baeldung.com/spring-nosuchbeandefinitionexception
fonte
<context:component-scan base-package="com.*" />
mesmo problema chegou, eu resolvi mantendo as anotações intactas e no servlet do despachante : mantendo a varredura do pacote básico, pois
com.*.
isso funcionou para mim.fonte
Isso pode ajudá-lo a:
Eu tenho a mesma exceção em meu projeto. Depois de pesquisar enquanto descobri que estava faltando a anotação @Service para a classe onde estou implementando a interface que desejo @Autowired.
Em seu código, você pode adicionar a anotação @Service à classe MailManager.
@Transactional @Service public class MailManager extends AbstractManager implements IMailManager {
fonte
@Service
anotação contém@Component
. Ter ambos é redundante.Em vez de @Autowire MailManager mailManager, você pode simular o bean conforme mostrado abaixo:
import org.springframework.boot.test.mock.mockito.MockBean; :: :: @MockBean MailManager mailManager;
Além disso, você pode configurar
@MockBean MailManager mailManager;
separadamente na@SpringBootConfiguration
classe e inicializar como abaixo:@Autowire MailManager mailManager
fonte
Enfrentei o mesmo problema em meu aplicativo de inicialização de primavera, embora eu tivesse minhas varreduras específicas de pacote habilitadas, como
@SpringBootApplication(scanBasePackages={"com.*"})
Mas, o problema foi resolvido fornecendo
@ComponentScan({"com.*"})
em minha classe de aplicativo.fonte
Meu palpite é 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 as anotações são primeiro desabilitadas por use-default-filters = "false" e então apenas a anotação @Controller habilitada. Portanto, sua anotação @Component não está habilitada.
fonte
Se você estiver testando seu controlador. Não se esqueça de usar @WebAppConfiguration em sua classe de teste.
fonte
Fiz isso acontecer porque adicionei uma dependência autowired à minha classe de serviço, mas esqueci de adicioná-la às simulações injetadas em meu teste de unidade de serviço.
A exceção do teste de unidade parecia relatar um problema na classe de serviço quando o problema estava na verdade no teste de unidade. Em retrospecto, a mensagem de erro me disse exatamente qual era o problema.
fonte
A solução que funcionou para mim foi adicionar todas as classes relevantes ao
@ContextConfiguration
anotação para a classe de teste.A classe a ser testada
MyClass.java
,, tinha dois componentes autowired:AutowireA
eAutowireB
. Aqui está minha correção.@ContextConfiguration(classes = {MyClass.class, AutowireA.class, AutowireB.class}) public class MyClassTest { ... }
fonte