Struts 2 - Apostila Caelum

32 respostas
J

Boa tarde .

Então galera , estou precisando de uma força.

Estou fazendo o exercício 11.8 da apostila da Caelum , no qual seria para adicionar uma tarefa , no BD por meio do Struts2.

Porém eu estou tomando uma excpetion nada agradável .

java.lang.RuntimeException: java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost/CFR

Primeiramente , no mesmo projeto , eu tenho uma classe na qual “testa” minha conexão e está certinho .

Eu tenho classes na qual testam alguns comandos do SQL , inserir , excluir etc. , também está rodando PERFEITAMENTE.

Então , eu não sei oque pode ser .

Eu já add o JAR do mySQL no projeto , já add no BuildPath e ele está na LIB.

Ele da erro nessa classe, quando eu tento usar o TarefaDAO

package br.com.cfr.action;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;

import br.com.cfr.jdbc.dao.TarefaDAO;
import br.com.cfr.jdbc.modelo.Tarefa;

public class AdicionaTarefasAction {

	//private Contato contato;
	private Tarefa tarefa;
	
	@Action(value = "adicionaTarefa" , results = {
			@Result(name = "ok" , location ="tarefa-adicionada.jsp")
	})
	
	public String execute() {
		//new ContatoDAO().adiciona(contato);
		new TarefaDAO().adiciona(tarefa);
		return "ok";
	}

	public Tarefa getTarefa() {
		return tarefa;
	}

	public void setTarefa(Tarefa tarefa) {
		this.tarefa = tarefa;
	}
	
}

Eis meu TarefaDAO

package br.com.cfr.jdbc.dao;

  
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import br.com.cfr.jdbc.ConnectionFactory;
import br.com.cfr.jdbc.modelo.Tarefa;
  
public class TarefaDAO {  
      
    Connection connection;  
      
    public TarefaDAO(){  
        this.connection = new ConnectionFactory().getConnection();  
    }  
      
    public void adiciona (Tarefa tarefa){  
          
        String sql = "insert into tab_tar descricao value(?)";  
          
        try {  
            PreparedStatement stmt = connection.prepareStatement(sql);  
            stmt.setString(1, tarefa.getDescricao());  
              
            stmt.execute();  
            stmt.close();                 
        } catch (SQLException e){  
            throw new RuntimeException (e);  
        }  
          
          
          
    }  
  
}

E também meu ConnectionFactory

package br.com.cfr.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class ConnectionFactory {
	
	public Connection getConnection(){
		
		System.out.println("Conectando ao banco");
		
		try {
			return DriverManager.getConnection("jdbc:mysql://localhost/CFR" , "root" , ""); 
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

}

E a JSP

<html>
	<body>
		<h3>Adicionar tarefas</h3>
		<form action ="adicionaTarefa" method="post">
		Descrição: <br/>
		
		<textarea name="tarefa.descricao" rows="5" cols="100" ></textarea> <br />
		
		<input type= "submit" value ="Adicionar">
		
		</form>	
	
	</body>
</html>

E quanto a perguntas sobre o banco de dados : Meu banco não tem senha e não tem usuario . Por isso eu uso ROOT. E como já falei eu estava conseguindo acessar , modificar , o banco normalmente , só agora que eu fui mexer com Struts2 que deu errado.

Será que está faltando algum JAR ??
Ah , eu uso o TomCat 7.0.

Eis um print para provar que o jar esta ná lib e está devidamente adicionado no BuidPath , e também , todos os JAR´S necessários para rodar o Struts2 também estão ai .

E estão funcionando pois eu fiz o primeiro exemplo da apostila e funcionou certinho.

Desde já agradeço .

32 Respostas

J

UP UP UP

G

Cara. Pela mensagem de erro parece que voc~e se esqueceu de adicionar o driver do mysql ao projeto. O mysql_connector…

S

O JAR do driver está na pasta WEB-INF/lib junto com os outros JARs?
Se funciona o seu programa de testes fora da Web, eu chutaria que seu JAR está na pasta errada. Pra funcionar na Web, precisa estar no WEB-INF/lib.

Abraços

I

pois é, eu também não tinha conseguido fazer funcionar com meu mysql, não sei se a apostila é pra uma versão mais antiga, ou o que eu fiz de errado.

Só sei q eu comentei a linha abaixo do hibernate.properties

# hibernate.dialect = org.hibernate.dialect.MySQLInnoDBDialect

e coloquei essa aqui no lugar

hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

começou a funcionar que é uma maravilha.

Fora esse pequeno detalhe, gostaria de dizer que esta apostila é muito boa, na verdade a melhor pra alguem que quer começar java na minha opinião.

Abraços

J

Então , está na pasta LIB sim .

Po , eu já tentei de tudo e não consegui …

Só pude pensar em algumas coisas… :

1° Eu esqueci de colocar algum JAR do Struts 2.

2° Eu uso o WAMP com o MySQL , talvez seja isso .

3° Sobre oque o nosso amigo citou acima , eu não uso Hibernate . :confused:

Eu já procurei no nosso amigo google e mudei a string de conexão para 127.0.0.1 (acho que é isso) , e continua o mesmo erro.

Quem souber alguma coisa , alguma luz , agradeço e muito .

S

Ta dando pau no carregamento do driver. Tenta mais uma coisa: forçar o carregamento explicito (isso era necessario antigamente mas nao deveria precisar a partir do java 6).

La na ConnectionFactory, acrescenta uma linha antes do return com o carregamento do driver:

Class.forName("com.mysql.jdbc.Driver");

Testa de novo e manda os resultados!

Abraços

J

Vlw gente , pelo menos o errou mudou :smiley:

Agora é esse.

java.lang.RuntimeException: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘descricao value(‘dd’)’ at line 1

Parece que tem algo errado na minha string do SQL mais não consiguo saber oq …

J

Gente muito obrigado !!!

Consegui resolver o erro .

Eu resolvi porém não entendi …

Eu mudei minha string de inserir no banco para:

“insert into tab_tar (descricao , finalizado) value(?,?)”;

E adicionei tbm :

stmt.setBoolean(2, tarefa.isFinalizado());

OK , até ai beleza , estou adicionado este campo , e funcionou legal !!.

Porém , porque funcionou ??

Sendo que no meu banco , a coluna finalizado está como NULL , então ela deve aceitar parâmetros nulos sem reclamar , porque ela não aceitou ??

E porque o outro campo da coluna não reclamou ??

Tem algo a ver com a variável ser booleana ??

Abraço e obrigado mais uma vez !!!

J

Então , gente , vou aproveitar o tópico , pois surgiu mais uma dúvida , quanto ao exercício 11.12

Eu compilo a JSP e quando vou carregar a página gera a exception :

org.apache.jasper.JasperException: An exception occurred processing JSP page /WEB-INF/content/lista-tarefas.jsp at line 22

19:


20: $[tarefa.id]
21: $[tarefa.descricao]
22: <c:if test = “${tarefa.finalizado eq false}”>
23: Não finalizado
24: </c:if>
25: <c:if test = “${tarefa.finalizado eq true}”>

javax.el.PropertyNotFoundException: Property ‘finalizado’ not found on type java.lang.String

Pelo oque eu entendi , é que realmente o finalizado não é uma String , ele é um boolean !

Aonde que eu indico isso ???

Segue minha JSP :

<%@ taglib  uri ="http://java.sun.com/jsp/jstl/core" prefix ="c" %>
<%@ taglib  uri ="http://java.sun.com/jsp/jstl/fmt" prefix ="fmt" %>

<html>
	<body>
		<a href = "formulario-tarefas.jsp" >Criar nova tarefa</a>
		
		<br /> <br />
		
		<table>
			<tr>
				<th>Id</th>
				<th>Descricao</th>
				<th>Finalizado</th>
				<th>Data de finalizacao</th>
			</tr>
			
			<c:forEach items = "$[tarefas]"	var ="tarefa">
				<tr>
					<td>$[tarefa.id]</td>
					<td>$[tarefa.descricao]</td>
					<c:if test = "${tarefa.finalizado eq false}">
						<td>Não finalizado</td>
					</c:if>	
					<c:if test = "${tarefa.finalizado eq true}">
						<td>Finalizado</td>
					</c:if>		
					<td>
						<fmt:formatDate value="${tarefa.dataFinalizacao.time}" pattern ="dd/MM/yyyy"/>
					</td>
				</tr>			
			</c:forEach>	
		</table>	
	</body>
</html>

E minha Action :

package br.com.cfr.action;

import java.util.List;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;

import br.com.cfr.jdbc.dao.TarefaDAO;
import br.com.cfr.jdbc.modelo.Tarefa;

public class ListaTarefasAction {
	
	private List<Tarefa> tarefas;
	
	@Action(value = "listaTarefas" , results = {
		@Result (name = "ok" , location ="lista-tarefas.jsp")
	})
	
	public String execute() {
		tarefas = new TarefaDAO().lista();
		return "ok";
	}
	
	public List<Tarefa>getTarefas() {
		return tarefas;
	}
	

}

O dataFinalizacao dá o mesmo erro , pois ele tbm não é uma String e sim um DATE. aonde eu faço o cast ??

Ah , e quando eu comentos os dois até “funciona” , porém gera a página com o LINK :

Criar nova tarefa

Porém ele gera o 404 , não achando a página de jeito algum …

Bom , obrigado gente e até + .

J

Gente eu tentei e tentei e nada e ainda ele não lista nada !! Ele traz o código mesmo .

Id Descricao Finalizado Data de finalizacao
$[tarefa.id] $[tarefa.descricao]

Estranho… alguém pode me dar uma luz???

S

João, a EL é com chaves, não colchetes.

${tarefa.id}

J

Opa , muito obrigado !

Realmente era isso o erro…

E quanto a URL errada que gerava o 404 , eu apenas tirei a extensão .jsp do link :

Porém , ele não está trazendo do banco :confused: .

Creio que deve ser algo errado , no método lista , do TarefaDAO .

Segue ele :

public List<Tarefa> lista() {
		try {
			List<Tarefa> tarefas  = new ArrayList<Tarefa>();
			PreparedStatement stmt = this.connection.prepareStatement("select * from tab_tar");
			ResultSet rs = stmt.executeQuery();
			
			while (rs.next()){
				
				Tarefa tarefa = new Tarefa();
				tarefa.setId(rs.getLong("id"));
				tarefa.setDescricao(rs.getString("descricao"));
				tarefa.setFinalizado(rs.getBoolean("finalizado"));
				
				Calendar data = Calendar.getInstance();
				data.setTime(rs.getDate("Tarefa"));
				tarefa.setDataFinalizacao(data);
				
				tarefas.add(tarefa);
			}
			rs.close();
			stmt.close();
			return tarefas;	
			
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}	
	}

Eu apenas estou trazendo os dois pois o dataFinalizacao e o finalizado eu não estou passando para o BD.

O finalizado está vindo 0 no bd… .

Eu já conferi no MySQl , para ver se estava salvado , e está sim .

Quem puder me ajudar valeu .

J

UP UP UP

J

Alguém por favooorr…

UP UP UP

C

João dá uma olhada se você realmente criou o campo com nome finalizado no seu bd, porque no meu caso eu também fiz pela caelum e coloquei finalizada, no caso para tarefa finalizada, pode ser por conta disto que está dando o erro, no mais não estou vendo nada de errado…

L

E não esqueça de liberar teus recursos (rs, stmt) dentro do bloco finally, não dentro do try.
Abraço!

J

Gente , obrigado pelas respostas , porém eu não consegui descobrir o erro …

Mais alguém??

C

João vai lá no banco e dá um desc tarefa e manda o print pra ver como está a estrutura no teu banco…

J

Eu não sei por o print aqui .

Vou tentar copiar a estrutura e colar .

id bigint(20) Não auto_increment
dataFinalizacao date NULL
finalizado tinyint(1) NULL
descricao varchar(255) lNULL

O estranho é que ele add numa boa , porém não tras nada …

J

Bom eu tentei ir para o próximo exercicio porém , pelo oque eu estou vendo nao vai ser nada facil…

AVISO: Could not find action or result
There is no Action mapped for namespace / and action name removeTarefa. - [unknown location]

Ele gera o 404 .

HTTP Status 404 - There is no Action mapped for namespace / and action name removeTarefa.

Quando eu tento remover alguma tarefa…

Pelo visto não vai dar para passar para o próximo ser resolver esse problema…

Será que tem algo errado com o método que eu uso para listar??

segue meu DAO

package br.com.cfr.jdbc.dao;

  
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import br.com.cfr.jdbc.ConnectionFactory;
import br.com.cfr.jdbc.modelo.Tarefa;
  
public class TarefaDAO {  
      
    Connection connection;  
      
    public TarefaDAO(){  
        try {
			this.connection = new ConnectionFactory().getConnection();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  
    }  
      
    public void adiciona (Tarefa tarefa){  
          
        String sql = "insert into tab_tar (descricao , finalizado) value(?,?)";  
          
        try {  
            PreparedStatement stmt = connection.prepareStatement(sql);  
            stmt.setString(1, tarefa.getDescricao());  
            stmt.setBoolean(2, tarefa.isFinalizado());
              
            stmt.execute();  
            stmt.close();                 
        } catch (SQLException e){  
            throw new RuntimeException (e);  
        }  
          
          
          
    }

	

	public List<Tarefa> lista() {
		try {
			List<Tarefa> tarefas  = new ArrayList<Tarefa>();
			PreparedStatement stmt = this.connection.prepareStatement("select * from tab_tar");
			ResultSet rs = stmt.executeQuery();
			
			while (rs.next()){
				
				Tarefa tarefa = new Tarefa();
				tarefa.setId(rs.getLong("id"));
				tarefa.setDescricao(rs.getString("descricao"));
				tarefa.setFinalizado(rs.getBoolean("finalizado"));
				
				Calendar data = Calendar.getInstance();
				data.setTime(rs.getDate("Tarefa"));
				tarefa.setDataFinalizacao(data);
				
				tarefas.add(tarefa);
			}
			rs.close();
			stmt.close();
			return tarefas;	
			
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}	
	}

	public void remove(Tarefa tarefa) {
		
		try {
			PreparedStatement stmt = connection.prepareStatement("delete from tab_tar where id=?");
			stmt.setLong(1, tarefa.getId());
			stmt.execute();
			stmt.close();
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
    }
		
	}

Bom obrigado para quem fica, mais eu preciso dormir amanha tenho que acordar cedo para trabalhar , muito OBRIGADO mesmo!!!

C

Bom se está persistindo e não está recuperando então acho que o erro realmente é no teu código, faz o seguinte, me manda aew ele pra eu dar uma olhada aqui, já fiz isso com outro problema e terminou dando certo vamos ver com o teu…
se quiser pra ficar mais fácil manda pra aqui ow…

J

Ok , eu estou colocando lá agora.

Bom se você puder me ajudar , muito OBRIGADOOOOOOOOOOOOO!!!

Eu não consigo imagina o erro que possa ser …

J

CONSEGUI , pelo menos gerar algum erro !!

O meu erro era que eu estava acessando o jsp puro . e não a action .

Porém agora quando eu tento acessar a action acontece isso .

java.lang.RuntimeException: java.sql.SQLException: Column ‘Tarefa’ not found.

Gente eu tenho uma dúvida como eu declaro uma variável BOOLEAN no mySQL ???

Por vias das dúvidas criei uma String mesmo para não dar problema…

segue o código do meu DAO (creio que o erro esteja nele)

package br.com.cfr.jdbc.dao;

  
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import br.com.cfr.jdbc.ConnectionFactory;
import br.com.cfr.jdbc.modelo.Tarefa;
  
public class TarefaDAO {  
      
    Connection connection;  
      
    public TarefaDAO(){  
        try {
			this.connection = new ConnectionFactory().getConnection();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  
    }  
      
    public void adiciona (Tarefa tarefa){  
          
        String sql = "insert into tab_tar (descricao , finalizado) value(?,?)";  
          
        try {  
            PreparedStatement stmt = connection.prepareStatement(sql);  
            stmt.setString(1, tarefa.getDescricao());  
            stmt.setString(2, tarefa.getFinalizado());
              
            stmt.execute();  
            stmt.close();                 
        } catch (SQLException e){  
            throw new RuntimeException (e);  
        }  
          
          
          
    }

	

	public List<Tarefa> lista() {
		try {
			List<Tarefa> tarefas  = new ArrayList<Tarefa>();
			PreparedStatement stmt = this.connection.prepareStatement("select * from tab_tar");
			ResultSet rs = stmt.executeQuery();
			
			while (rs.next()){
				
				Tarefa tarefa = new Tarefa();
				tarefa.setId(rs.getLong("id"));
				tarefa.setDescricao(rs.getString("descricao"));
				tarefa.setFinalizado(rs.getString("finalizado"));
				
				Calendar data = Calendar.getInstance();
				data.setTime(rs.getDate("Tarefa"));
				tarefa.setDataFinalizacao(data);
				
				tarefas.add(tarefa);
			}
			rs.close();
			stmt.close();
			return tarefas;	
			
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}	
	}

	public void remove(Tarefa tarefa) {
		
		try {
			PreparedStatement stmt = connection.prepareStatement("delete from tab_tar where id=?");
			stmt.setLong(1, tarefa.getId());
			stmt.execute();
			stmt.close();
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
    }
		
	}

Obrigado gente !

C

Desculpa a demora para pelo menos te dar uma resposta eu vou olhar o que você fez agora e depois te dou um feedback do que pode ser melhorado e quais são os problemas que estão gerando erro, vou dar uma olhada no que você me mandou agora a tarde e te digo se consegui ou não…

L

Up up up

J

UP UP UP

Alguém???

L

Up

W

tente:

public List&lt;Tarefa&gt; lista() { ... Calendar data = Calendar.getInstance(); // data.setTime(rs.getDate("Tarefa")); // você não tem a coluna tarefa na tabela data.setTime(rs.getDate("dataFinalizacao")); tarefa.setDataFinalizacao(data); ... }

L

num tem data…

W

não entendi. o valor é nulo (você não inseriu a data no registro)? a tabela não tem um campo de data?

X

Off-poste;
Eu tb estou estudando pela apostila da caelum…
Tb estou na parte de struts 2 mais estou com problema na ativida 11.6…
Eu fiz um topico de poder olhar agradeço…

vlw…

C

Amigos, esse tópico me ajudou bastante a resolver o problema que tive com o FJ-21, foi exatamente o que aconteceu com o nosso amigo João .
Sendo que eu reparei uma coisa estranha.

Quando nosso amigo sérgio sugeriu que inseríssemos a linha:

Class.forName("com.mysql.jdbc.Driver"); no nosso ConnectionFactory o erro mudava. E realmente consegui descobrir o erro que tinha em meu código assim como o joão conseguiu… No meu caso eu havia removido uma coluna de minha tabela e esqueci de trocar no stmt. portanto eu fazia uma referencia inexistente e tomava um nullpointer.

Então foi ae que eu reparei algo diferente. Na subida do servidor ele lança uma excessão de “InstanceAlreadyExistsException”. ou seja, me informa que eu ja possuo a instância do driver não havendo a necessidade de eu forçar essa instância.

Resumindo, quando eu forcei a instância do driver conforme sugerido pelo Sergio, o struts me mostrou o real erro que eu tinha, quando n fiz isso ele me deu um erro completamente diferente do meu problema, me dando um drivernotfound ao invés de um nullpointer.

Será que isso vai ocorrer em todos os problemas semelhantes que eu tiver referente a banco no Strusts2 ? Se for isso é uma coisa bem falha do struts.

Obs: meu servidor de aplicação é o Jboss e não apache tomcat como o do joão.

Absss rapaziada.

Criado 8 de outubro de 2011
Ultima resposta 24 de out. de 2011
Respostas 32
Participantes 10