Formulário não envia dados para o Controller

Boa tarde galera.
Estou fazendo um sistema para treinar e não estou conseguindo gravar “UM” dos dados no banco.
Seguem códigos:

Tabela Estado:

	private Long id;
	private String nome;
	private String sigla;
	private Pais pais;

// Métodos getter e setter...

Aqui método adiciona da classe EstadoDAO


	public void adiciona(Estado estado){

		String sqlAdiciona = "insert into estado (nome, sigla, pais) values (?, ?, ?)";

		try {


			PreparedStatement stmtAdiciona = connection.prepareStatement(sqlAdiciona);

			stmtAdiciona.setString(1, estado.getNome().toUpperCase());
			stmtAdiciona.setString(2, estado.getSigla().toUpperCase());
			stmtAdiciona.setLong(3, estado.getPais().getId());

			stmtAdiciona.execute();
			stmtAdiciona.close();
			connection.close();

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}
	}

Agora a classe EstadoController


package br.com.homologacao.jdbc.modelo.spring.controller.local;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import br.com.homologacao.jdbc.modelo.local.Estado;
import br.com.homologacao.jdbc.modelo.local.Pais;
import br.com.homologacao.jdbc.modelo.local.dao.EstadoDAO;

@Controller
public class EstadoController {
	
	@RequestMapping("novoEstado")
	public String form(){
		return"local/estado/adicionaEstado";
		
	}
	
	@RequestMapping("adicionaEstado")
	public String adiciona(Estado estado, Long id){
		EstadoDAO estadoDAO = new EstadoDAO();
		Pais pais = new Pais();
		id = pais.getId();	// Não estou conseguindo receber esse campo diretamente do formulário.
	//	id = 107L; Mas se ele estiver dessa forma eu consigo gravar o Estado com a FK no banco, mas somente com esse código de País (107L).
		pais.setId(id);
		estado.setPais(pais);
		estadoDAO.adiciona(estado);
		return"local/estado/estadoAdicionado";
	}

O formulário adicionaEstado.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<jsp:useBean id="dao" class="br.com.homologacao.jdbc.modelo.local.dao.PaisDAO"></jsp:useBean>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Adiciona Estado - Homologação</title>
</head>
<body>

	<table align="center" border="1">
		<tr>
			<td>Sistema de Homologação
		</tr>
	</table>

	<h3>Inserindo um novo Estado - Sistema de Homologação</h3>

	<form name="adicionaEstado" method="post" action="adicionaEstado">
		Nome:	<input type="text" name="nome" value="${estado.nome}"/><br />
		Sigla:	<input type="text" name="sigla" maxlength="2" value="${estado.sigla}"/><br />
		País:	<select name="id">
					<option value="${pais.id}">Selecione o País</option>
					<c:forEach items="${dao.lista}" var="pais" >
						<option value="${pais.id}">${pais.nome}</option>
					</c:forEach>
				</select>
				<br />
     /*     Já tentei assim também mas não rolou!  
               País:    <input type="text" name="pais" value="${estado.pais}"/><br />  
     */
			<input type="submit" value="Adicionar" />
	</form>
</body>
</html>

E por fim o erro:


HTTP Status 500 - Request processing failed; nested exception is java.lang.NullPointerException

type Exception report

message Request processing failed; nested exception is java.lang.NullPointerException

description The server encountered an internal error that prevented it from fulfilling this request.

exception

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:929)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:824)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
	org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:798)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
root cause

java.lang.NullPointerException
	br.com.homologacao.jdbc.modelo.local.dao.EstadoDAO.adiciona(EstadoDAO.java:38)
	br.com.homologacao.jdbc.modelo.spring.controller.local.EstadoController.adiciona(EstadoController.java:28)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	java.lang.reflect.Method.invoke(Unknown Source)
	org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
	org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
	org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
	org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:917)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:824)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
	org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:798)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
note The full stack trace of the root cause is available in the Apache Tomcat/6.0.36 logs.

Apache Tomcat/6.0.36

Os input’s do nome e da sigla estão funcionando normalmente, mas quando chega no pais, trava!
A questão é que esse select ou até mesmo o input pais, não está enviando o valor para o “pais.setId(id);” do Controller

Confesso a vocês que já estou duas noites e três dias sem dormir direito por causa disso.
Já procurei aqui e em outros fóruns mas não encontrei a solução.
Até encontrei algumas pessoas com problemas parecidos e [RESOLVIDOS], mas não postaram a solução encontrada.
Fico no aguardo da ajuda de todos.

cara,

pelo que entendi o erro ai está na ligação entre a view e o controler.

veja essa parte do erro e observe alinha do EstadoController.java, o erro é pq estado é null.

    br.com.homologacao.jdbc.modelo.spring.controller.local.EstadoController.adiciona(EstadoController.java:28)  

Dá uma lida nessa parte do tutorial:

http://static.springsource.org/docs/Spring-MVC-step-by-step/part2.html

vlw

Passei a parte errada,

dá uma olhada nessa parte:

http://static.springsource.org/docs/Spring-MVC-step-by-step/part4.html#step4.6

Olá emanuelmm.
Vi os links que você me enviou, mas todos os que eu vejo são referentes a uma única tabela no banco de dados.
No meu caso quando fiz o teste com a tabela Pais, funcionou perfeitamente (adicionar, alterar, excluir e listar). Mas como a tabela Estado tem um atributo Pais pais, o formulário não envia os dados para esse campo, causando o NullPoint…
Se você tiver outra ideia, por favor, ajude-me.
Obrigado!

        Pais pais = new Pais();  
        id = pais.getId(); 

Nao entendi foi essa parte, porque você [EDITED] INICIALIZOU Pais e depois tá tentando pegar o atributo id.

Cara,

analisando seu problema com calma acho que entendi o seu problema.

Nao estou vendo a classe EstadoDAO, mas acredito que dentro dela você deve está inserindo um registro na tabela ESTADO e que na tabela estado existe um campo pais_id.

Nesse caso, o que você precisa é apenas do ID do pais pra setar no campo pais_id da tabela ESTADO nao é isso?

Uma solução bastante simples para resolver seu problema seria apenas criar no POJO de Estado um atributo inteiro paisId e receber essa cara diretamente do FORM. Dessa forma vocÊ evita a necessidade de mapear esse realcionamento, já que você nao está usando JPA nem nada.

Qualquer coisa posta ai a classe EstadoDAO…

vlw

emanuelmm, seguem as classes Estado e EstadoDAO

package br.com.homologacao.jdbc.modelo.local;

import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.NotEmpty;

public class Estado {
	

	private Long id;
	@NotBlank(message="Nome não pode ser vazio")
	private String nome;
	@NotBlank(message="Sigla não pode ser vazio")
	@Size(min=2)
	private String sigla;
	
	@NotEmpty(message="Escolha um País")
	private Pais pais;
	
	public Long getId(){
		return this.id;
	}
	public void setId(Long id){
		this.id = id;
	}
	
	public String getNome(){
		return this.nome;
	}
	public void setNome(String nome){
		this.nome = nome;
	}
	
	public String getSigla(){
		return this.sigla;
	}
	public void setSigla(String sigla){
		this.sigla = sigla;
	}
	
	public Pais getPais(){
		return this.pais;
	}
	public void setPais(Pais pais){
		this.pais = pais;
	}
	
	//	Construtor de Estado.
	public Estado(){
		
	}
	//	Construtor que recebe o nome do Estado.
	public Estado(String nome){
		this.nome = nome;
	}

}

EstadoDAO


package br.com.homologacao.jdbc.modelo.local.dao;

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

import br.com.homologacao.jdbc.ConnectionFactory;
import br.com.homologacao.jdbc.modelo.local.Estado;
import br.com.homologacao.jdbc.modelo.local.Pais;

public class EstadoDAO {

	private Connection connection;

	public EstadoDAO(){
		this.connection = new ConnectionFactory().getConnection();
	}

	public EstadoDAO(Connection connection){
		this.connection = connection;

	}

	public void adiciona(Estado estado){

		String sqlAdiciona = "insert into estado (nome, sigla, pais) values (?, ?, ?)";

		try {


			PreparedStatement stmtAdiciona = connection.prepareStatement(sqlAdiciona);

			stmtAdiciona.setString(1, estado.getNome().toUpperCase());
			stmtAdiciona.setString(2, estado.getSigla().toUpperCase());
			stmtAdiciona.setLong(3, estado.getPais().getId());

			stmtAdiciona.execute();
			stmtAdiciona.close();
			connection.close();

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}
	}

	public void altera(Estado estado){

		String sqlAltera = "update estado set nome=?, sigla=?, pais=? where codigo=?";

		try {
			PreparedStatement stmtAltera = connection.prepareStatement(sqlAltera);

			stmtAltera.setString(1, estado.getNome().toUpperCase());
			stmtAltera.setString(2, estado.getSigla().toUpperCase());
			stmtAltera.setLong(3, estado.getPais().getId());
			stmtAltera.setLong(4, estado.getId());

			stmtAltera.execute();
			stmtAltera.close();
			connection.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}

	}

	public void remove(Estado estado){

		String sqlRemove = "delete from estado where codigo=?";

		try {
			PreparedStatement stmtRemove = connection.prepareStatement(sqlRemove);
			
			stmtRemove.setLong(1, estado.getId());

			stmtRemove.execute();
			stmtRemove.close();
			connection.close();

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}
	}

	public List<Estado> getLista(){

		try {
			ArrayList<Estado> estados = new ArrayList<Estado>();
			String sqlLista = "select e.codigo, e.nome, e.sigla, p.nome from estado e " +
					"join pais p on e.pais = p.codigo";

			PreparedStatement stmlLista = connection.prepareStatement(sqlLista);
			ResultSet rs = stmlLista.executeQuery();

			while(rs.next()){
				Estado estado = new Estado();

				estado.setId(rs.getLong("e.codigo"));
				estado.setNome(rs.getString("e.nome"));
				estado.setSigla(rs.getString("e.sigla"));
				estado.setPais(new Pais(rs.getString("p.nome")));

				estados.add(estado);
			}
			rs.close();
			stmlLista.close();
			connection.close();

			return estados;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}

	}
	
	public List<Estado> getId(Long id){
		
		ArrayList<Estado> estado = new ArrayList<Estado>();
		String sqlId = "select * from estado e join pais p on e.pais = p.codigo";
		
		try {
			PreparedStatement stmtId = connection.prepareStatement(sqlId);
			ResultSet rs = stmtId.executeQuery();
			
			while(rs.next()){
				if(id == rs.getLong("e.codigo")){
					Estado estados = new Estado();
					estados.setId(rs.getLong("e.codigo"));
					estados.setNome(rs.getString("e.nome"));
					estados.setSigla(rs.getString("e.sigla"));
					estados.setPais(new Pais(rs.getString("p.nome")));
				}
				
			}
			return estado;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}
	}
}

Tenta fazer o que eu disse.

Nessa Linha do EstadoDAO

           stmtAdiciona.setLong(3, estado.getPais().getId());  

você pode substituir por:

           stmtAdiciona.setLong(3, estado.getPaisId());  

No casoo o atributo paisId no Pojo de Estado vocÊ cria como log, eu tinha falado pra criar como int.

emanuelmm.
Não deu certo. Na verdade, aconteceu que algumas classes como a própria class Pais apresentou erro. Não entendi porque, já que Pais não herda nada de Estado. Da forma que você está me apresentando eu já tinha pensado em fazer, mas aí o Estado não estaria herdando um país e sim, somente enviando um id para o Long pais e quem se encarregaria de fazer a relação seria a SQL, certo?.
Fico no aguardo e obrigado por estar me ajudando.