Boa tarde pessoal. Eu novamente rs … seguinte criei uma página jsp onde o usuário digita alguns dados entre eles uma data. Quase todos os dados chegam no método que criei no spring sem problemas, com exceção de um. A data! Cara estou a dois dias tentando resolver isso e nada! A data chega com valor nulo no método. O que será que está acontecendo?
PS:. Por favor ignorem a bagunça no bean tarefa. É que estou mechendo nele ha um tempo tentando arrumar esse problema.
JSP:
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<html>
<head>
<title>Tarefa a Ser Alterada</title>
</head>
<body>
Informações da tarefa à ser alterada:<br />
<form action="alteraTarefa" method="post">
<input type="text" name="id" value="${tarefa.id}" readonly="true"><br />
Descrição:<br />
<textarea rows="5" cols="100" name="descricao">${tarefa.descricao}</textarea><br />
Finalizado? <input type="checkbox" name="finalizado" value="true" ${tarefa.finalizado?'checked':''}/><br />
Data de Finalização:<br />
<input type="text" name="dataFinalizacao">
<br />
<input type="submit" value="Alterar">
</form>
</body>
</html>
Metodo no Spring:
@RequestMapping("alteraTarefa")
public String altera(Tarefa tarefa){
TarefaDao dao = new TarefaDao();
System.out.println("data em tarefascontroller alteratarefa == " + tarefa.getDataFinalizacao());
dao.altera(tarefa);
return "redirect:listaTarefas";
}
Tarefa Java Bean:
package br.com.caelum.tarefas.model;
import java.util.Date;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.validation.constraints.Size;
import org.springframework.format.annotation.DateTimeFormat;
import com.sun.istack.internal.NotNull;
public class Tarefa {
private long id;
@NotNull @Size(min=5, max=100)
private String descricao;
private boolean finalizado = false;
@DateTimeFormat(pattern="yyyy-MM-dd")
private Calendar dataFinalizacao;
public void setId(long id){
this.id = id;
}
public long getId(){
return this.id;
}
public void setDescricao(String descricao){
this.descricao = descricao;
}
public String getDescricao(){
return this.descricao;
}
public void setFinalizado(boolean finalizado){
this.finalizado = finalizado;
}
public boolean getFinalizado(){
return this.finalizado;
}
public void setDataFinalizacao(String dataFinalizacao){
/*
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
String dataStr = "24/02/2012";
Date date = sdf.parse(dataStr);
Calendar cal = new GregorianCalendar();
cal.setTimeInMillis(date.getTime());
*/
try{
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date data = df.parse(dataFinalizacao);
Calendar calendario = new GregorianCalendar();
calendario.setTimeInMillis(data.getTime());
System.out.println("\n\nItens abaixo em tarefa setDataFinalizacao\n");
System.out.println("Data em setDataFinalizacao " + calendario.get(Calendar.DAY_OF_MONTH) + "/" + calendario.get(Calendar.MONTH) + "/" + calendario.get(Calendar.YEAR));
this.dataFinalizacao = calendario;
System.out.println("\nthis.dataFinalizacao == " + this.dataFinalizacao.get(Calendar.DAY_OF_MONTH) + "/" + this.dataFinalizacao.get(Calendar.MONTH) + "/" + this.dataFinalizacao.get(Calendar.YEAR));
}catch(NullPointerException ex){
//System.out.println("\n\n" + ex.getMessage() + " exceção null pointer em tarefa setDataFinalizacao\n");
System.out.println("\n\nExceção null pointer em tarefa setDataFinalizacao\n");
ex.printStackTrace();
}catch(ParseException ex){
System.out.println("\n\n" + ex.getMessage() + " exceção parse em tarefa setDataFinalizacao");
}
}
public Calendar getDataFinalizacao(){
return this.dataFinalizacao;
}
}
O problema é o seguinte, quando você envia uma data da JSP para o controller, essa data chega como uma String, porém você está esperando um Calendar, por isso o problema.
O Spring possui uma implementação que você pode adicionar ao seu controller, que dai ele faz a conversão:
private SimpleDateFormat dateFormat;
@Autowired
public SeuController(SimpleDateFormat dateFormat) {
this.dateFormat = dateFormat;
}
@InitBinder
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
Porém você só vai conseguir converter para java.util.Date. Como seu atributo é um Calendar, vai dar erro. Dai para resolver, ou você troca de Calendar para Date ou implementa sua propria classe de conversão nos padrões da classe CustomDateEditor. Pode usa-la como modelo para construir a sua.
[quote=romarcio]O problema é o seguinte, quando você envia uma data da JSP para o controller, essa data chega como uma String, porém você está esperando um Calendar, por isso o problema.
O Spring possui uma implementação que você pode adicionar ao seu controller, que dai ele faz a conversão:
private SimpleDateFormat dateFormat;
@Autowired
public SeuController(SimpleDateFormat dateFormat) {
this.dateFormat = dateFormat;
}
@InitBinder
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
Porém você só vai conseguir converter para java.util.Date. Como seu atributo é um Calendar, vai dar erro. Dai para resolver, ou você troca de Calendar para Date ou implementa sua propria classe de conversão nos padrões da classe CustomDateEditor. Pode usa-la como modelo para construir a sua.
[/quote]
Oi Romarcio. Então cara depois de vários ajustes tentando resolver esse problema, eu coloquei o método setDataFinalização para receber uma String e lá dentro eu converto para Calendar. Recebendo uma String deveria funcionar não?
Sim, você pode criar um atributo do tipo String na Entidade para receber a data que vem da JSP e depois converter para outro tipo.
Só não esqueça de alterar na JSP para esse novo atributo.
Qual a exceção que está dando, é a mesma de antes?
É sim continua dando NullPointerException
Cola a exceção para eu ver.
Na exceção aparece apenas null … como se o valor do calendario não estive sendo mandado pela jsp. Caso adiante segue o stackTrace:
java.lang.NullPointerException
at br.com.caelum.tarefas.dao.TarefaDao.altera(TarefaDao.java:130)
at br.com.caelum.tarefas.controller.TarefasController.altera(TarefasController.java:95)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:636)
Faz essa mudança:
@RequestMapping("alteraTarefa")
public String altera(@ModelAttribute("tarefa") Tarefa tarefa){
TarefaDao dao = new TarefaDao();
System.out.println("data em tarefascontroller alteratarefa == " + tarefa.getDataFinalizacao());
dao.altera(tarefa);
return "redirect:listaTarefas";
}
Só uma coisa, sua JSP não está nos padrões do Spring MVC. Você está usando Struts 2.
Ta legal farei essa mudança e posto aqui no que deu. Mas me diz uma coisa. Como assim a jsp está no padrão struts2? Tipo … o que deveria fazer nessa jsp para ela ficar no padrão do spring mvc?
Você deve construir a JSP com as tags fornecidas pelo Spring MVC. Se não fizer assim, ele não vai buscar seus dados.
Procure na internet por Tutoriais Spring 3 MVC que vai achar bastante material.
Um exemplo do JSP com Spring:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Add Event</title>
</head>
<body>
<h1>Add User</h1>
<c:url var="viewUsersUrl" value="/users.html" />
<a href="${viewUsersUrl}">View All Users</a>
<br /><br />
<c:url var="addUserUrl" value="/users/save.html" />
<form:form modelAttribute="user" method="POST" action="${addUserUrl}">
<form:label path="username">Username:</form:label>
<form:input path="username"/><br />
<form:label path="password">Password:</form:label>
<form:input path="password"/><br />
<input type="submit" value="Save User" />
</form:form>
</body>
</html>
Veja como muda as tags em relação as que você usa.
Fora que tem outras configurações que não sei se você fez.
A fonte do exemplo que passei: http://pbrajkumar.wordpress.com/2010/03/24/spring-3-0-mvc-hibernate-simplified-with-annotations-tutorial/