Ajuda - Injeção de Dependências (Spring)

Boa tarde. Estou fazendo o curso de Java pela apostila da Caelum, e no capítulo de Injeção de Dependências estou tendo o seguinte erro:

Error creating bean with name ‘tarefasController’ defined in file [C:\apache-tomcat-8.0.35\wtpwebapps\tarefas\WEB-INF\classes\br\com\tarefas\controller\TarefasController.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [br.com.tarefas.dao.TarefaDao]: : No qualifying bean of type [br.com.tarefas.dao.TarefaDao] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [br.com.tarefas.dao.TarefaDao] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}

O projeto do curso tem a seguinte estrutura:

  • Tarefa (DTO)
  • TarefaDAO
  • TarefasController

Antes desse capítulo, a conexão com banco era iniciada no construtor da DAO e estava tudo funcionando perfeitamente.

Nesse capítulo, estamos criando um DataSource no arquivo de contexto do Spring e colocando as anotações @Repository na TarefaDAO e @Autowired na TarefasController, e removendo a instanciação da DAO nos métodos da Controller. As diferenças da apostila pro meu caso são:

  • Não estou usando banco MySQL e sim Oracle;
  • Não tenho as bibliotecas do curso, então baixei pelo Maven;

Segue códigos:

• BIBLIOTECAS BAIXADAS NO MAVEN</>

	<!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
	<dependency>
		<groupId>commons-dbcp</groupId>
		<artifactId>commons-dbcp</artifactId>
		<version>1.4</version>
	</dependency>

	<!-- https://mvnrepository.com/artifact/commons-pool/commons-pool -->
	<dependency>
		<groupId>commons-pool</groupId>
		<artifactId>commons-pool</artifactId>
		<version>1.6</version>
	</dependency>

• XML CONTEXTO SPRING - DATASOURCE (Oracle, na apostila é MySQL)

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
	<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
	<property name="url" value="jdbc:oracle:thin:@PC:1521:xe" />
	<property name="username" value="usuario" />
	<property name="password" value="senha" />
</bean>

• TAREFA DAO

@Repository
public class TarefaDao {

private Connection connection;

/* -- REMOVIDO NO CAPITULO DE INJEÇÃO DE DEPENDÊNCA, PARA USAR O DATASOURCE DEFINIDO NO XML
public TarefaDao() {
	this.connection = new ConnectionFactory().getConnection();
}
*/

@Autowired
public TarefaDao(DataSource dataSource) {
	  try {
	    this.connection = dataSource.getConnection();
	  } catch (SQLException e) {
	    throw new RuntimeException(e);
	  }
	}

• TAREFA CONTROLLER

@Controller
public class TarefasController {

private final TarefaDao dao;

@Autowired
public TarefasController(TarefaDao dao) {
	this.dao = dao;
}

@RequestMapping("novaTarefa")
public String form() {
	return "tarefa/formulario";
}

@RequestMapping("listaTarefas")
public String lista(Model model) {
	// TarefaDao dao = new TarefaDao();
	model.addAttribute("tarefas", dao.lista());
	return "tarefa/lista";
}

Olá,

Experimente excluir final de: private final TarefaDao dao;

Não deu certo. Na verdade, o erro já ocorre no console ao subir o Tomcat, e não ao acessar a página.

@leo1107 no momento não tenho nenhuma app em spring p/ simular, vou tentar ajuda-lo nas cegas. faz o que vinicius falou e remove o construtor da controller e add a anotacao @Autowired direto no atributo @Autowired private TarefaDao dao;

Se parar de dar erro ao subir app, ai verifica se o atributo não irá ficar null.

@cviniciusm
@RaulCrash

Segui a orientação acima e também não deu certo, ocorreu erro no console novamente e o Tomcat não subiu. Será que está errado alguma coisa no DataSource?

Error creating bean with name ‘tarefasController’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private br.com.tarefas.dao.TarefaDao br.com.tarefas.controller.TarefasController.dao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [br.com.tarefas.dao.TarefaDao] 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)}

Achei em outros sites algumas pessoas com esse mesmo problema, segui o conselho de um usuário:

No construtor “TarefaDao”, trocar:

  • public TarefaDao(DataSource dataSource) {

por

  • public TarefaDao(BasicDataSource dataSource) {

importei:

  • import org.apache.commons.dbcp.BasicDataSource;

Pois segundo o colega, tem que usar esse tipo pois é a classe do Bean criado para o DS.

Mesmo assim, não deu certo, o problema continua.

Olá,

Você configurou o arquivo spring-context.xml dentro da pasta WEB-INF, conforme a apostila ? :

<?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:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
		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">
	<context:component-scan base-package="br.com.caelum.tarefas" />
	<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>

"
A primeira coisa que faremos nesse arquivo é habilitar o uso de anotações do Spring MVC e configurar pacote base da aplicação web para o Spring achar as nossas classes:

<mvc:annotation-driven />
<context:component-scan base-package="br.com.caelum.tarefas" />

"

Se você fez isso corretamente, então um erro comum dos inciantes é a configuração incorreta do servidor de aplicação Tomcat: durante a criação do servidor dentro do Eclipse evite adicionar o seu projeto nesse momento. Conclua a instalação do servidor. Em seguida, adicione o seu projeto no servidor Tomcat.

Olá,

Você sabia que pode criar o seu projeto fj21-tarefas atualizado usando o SetupMyProject (http://setupmyproject.com/) ?

Basta seguir o assistente.

@cviniciusm

Obrigado pelo retorno.

O spring foi configurado corretamente, o projeto estava todo funcionando com Spring MVC, aí nesse capítulo de injeção de dependências que emperrou.

Teste dessa maneira, isso partindo que a configuração está ok, já que você disse que funcionava

private transient TarefaDao dao;

@Autowired
public TarefasController(final TarefaDao dao) {
	this.dao = dao;
}