PDA

View Full Version : Go to successView() with a model


pranxas
Oct 11th, 2006, 07:55 AM
Hi

I need to make a controller that returns a ModelAndView to a successView with a model. The problem is that the same controller must also, if is the case, return to the formView with errors. I'm using a SimpleFormController and the code for now is:


public class LoginFormController extends SimpleFormController{

private UserManager userMan;
protected final Log logger = LogFactory.getLog(getClass());

public ModelAndView onSubmit(Object command, BindException errors) throws Exception{
String username=((PasswordGetter) command).getUser();
logger.info(((PasswordGetter)command).getUser());

String inputPass=((PasswordGetter) command).getPassword();

String realPass=userMan.getPassword(username);

if(realPass==null){
logger.info("user rejected");
errors.rejectValue("password","error.wrongPassword",null,"Wrong Password");
return new ModelAndView(this.getFormView(), errors.getModel());
}

else if(inputPass.equals(realPass)){
logger.info("returning from LoginFormController view to " + getSuccessView());
User person=userMan.getInfoList(username);
logger.info("teste="+person.toString());
logger.info("user.fname="+person.getFirst_name());
logger.info("user.lname="+person.getLast_name());

ModelAndView nModel= new ModelAndView(new RedirectView(getSuccessView()),errors.getModel());

return nModel;
}
else{
logger.info("password rejected");

errors.rejectValue("password","error.wrongPassword",null,"Wrong Password");
return new ModelAndView(this.getFormView(), errors.getModel());
}
}


How can I return the person object to the successView?

Thanks

Rui Gonçalves

Marten Deinum
Oct 11th, 2006, 08:47 AM
Well how about adding it to the model.


else if(inputPass.equals(realPass)){
User person=userMan.getInfoList(username);
Map model = errors.getModel();
model.put("person", person);
ModelAndView nModel= new ModelAndView(new RedirectView(getSuccessView()),model);
return nModel;
}

pranxas
Oct 11th, 2006, 10:06 AM
Hi again

My question now is: how can I catch the 'person' in the jsp? I've tried:

<c:forEach items="${person.person}" var="user">
<c:out value="${user.first_name}"/> <i>$<c:out value="${user.last_name}"/></i><br><br>
</c:forEach>
<c:out value="${person.first_name}"/> <c:out value="${person.getLast_name }"/>


and any of these works...

Thanks

Marten Deinum
Oct 11th, 2006, 10:33 AM
If you added the person to the model with the name person then in your jsp you can do


<c:out value="${person.first_name}/>


This also requires that in your User class you have a getter for the first_name property. Like so:


public String getFirst_name()


But to give a more precise answer, what is going wrong? Is nothing displayed? Are errors shown? Or something else?

Also make sure you have the correct taglibraries included in your jsp file.

Also you might want to check out the chapter regarding spring mvc in the reference guide. Especially the Spring MVC part (http://static.springframework.org/spring/docs/2.0.x/reference/mvc.html) and the part regarding JSTL (http://static.springframework.org/spring/docs/2.0.x/reference/view.html#view-jsp)

pranxas
Oct 11th, 2006, 10:43 AM
What happens it's that nothing is displayed.
The libraries that I use are:
<%@ taglib prefix="spring" uri="/spring" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

I've the respective getters and setters...

vasya10
Oct 11th, 2006, 07:41 PM
My understanding is, if you add your objects to ModelAndView and then do a RedirectView, the attributes will not be visible to the jsp.

The ModelAndView.addObject() simply adds the attributes to the request (--> request.setAttribute), while RedirectView does a sendRedirect internally, which means a new 'request' object.

In which case you store the data in session and retrieve that in the jsp (like using pageContext.getSession()).

Buf if you dont do RedirectView, and if the user simply browser-refreshes the successView, the browser will display the previous view/form (not expected behaviour).

veraction
Oct 11th, 2006, 07:53 PM
I also have been struggling with this issue.

@vasya10's last post:


In which case you store the data in session and retrieve that in the jsp (like using pageContext.getSession()).


This is the best solution, right? How would a code sample look for this? Googling "spring +pagecontext" doesn't return much. Is pageContext just like the session variables in request.getSession()?

And does this solution have these properties:
-After user submits form, they can refresh this new view without having a POST-refresh warning/issue
-One can somehow (how?) pass data from the form controller to the JSP page

[edit] I think I found something finally. Apparently the solution is more complicated than I originally thought: http://www.springframework.org/docs/reference/mvc.html

vasya10
Oct 11th, 2006, 08:45 PM
In your onSubmit , you can add:


WebUtils.setSessionAttribute("person", person);


In your jsp, you can reference the "pageContext" object directly (its an implicit object)


<%
Person p = (Person) pageContext.getSession().getAttribute("person");
p.getFirstName();
%>


If you want to use Jstl, you can still do:


<c: out value="${person.name}"/>


The c tag looks into both request object and pageContext objects to obtain the object.


-After user submits form, they can refresh this new view without having a POST-refresh warning/issue


When you do a redirectView, the POST warning will not happen, because now you are doing a http-GET on the servlet to retrieve the data.


One can somehow (how?) pass data from the form controller to the JSP page


I think the answer is yes - by using session (as mentioned above).

veraction
Oct 11th, 2006, 09:18 PM
Thanks for the quick response. That seems like something I'll have to utilize in an application I'm working on.

By the way, are these two things the same:

WebUtils.setSessionAttribute("person", person);

request.getSession().setAttribute("person", person);


I wonder if WebUtils could then provide my Validators with access to session variables.

Marten Deinum
Oct 12th, 2006, 03:38 AM
The ModelAndView.addObject() simply adds the attributes to the request (--> request.setAttribute), while RedirectView does a sendRedirect internally, which means a new 'request' object.

Well you are right :). Totally read past the part of RedirectView.

However if you are using a redirect view I also assume (I know I know never assume ;) ) you are redirecting to a page which also has a controller? You could pass the id of the user to this controller and retrieve the user in that controller putting it in the model (referenceData) and you should be good to go.

In your first controller

else if(inputPass.equals(realPass)){
User person=userMan.getInfoList(username);
Map model = errors.getModel();
model.put("person", person);
ModelAndView nModel= new ModelAndView(new RedirectView(getSuccessView()+"uname=person.getUserName()));
return nModel;
}


Then in the referenceData method of your next controller

protected Map referenceData(HttpServletRequest request) throws Exception {
String username = ServletRequestUtils.getStringParameter(request, "uname");
User person = userMan.getInfoList(username);
Map model = new HashMap();
model.put("person", person);
}


Of when you have put it into the session you could also change the referenceData to this instead of adding code to your jsp page.


protected Map referenceData(HttpServletRequest request) throws Exception {
User person = (User) WebUtils.getSessionAttribute(request, "person");
Map model = new HashMap();
model.put("person", person);
}

pranxas
Oct 12th, 2006, 06:07 AM
Hi

Well, I tried the last suggestion, and I have an error that I don't know how to solve it. I have the first controller:


public ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response,Object command, BindException errors) throws Exception{
String username=((PasswordGetter) command).getUser();
logger.info(((PasswordGetter)command).getUser());

String inputPass=((PasswordGetter) command).getPassword();

String realPass=userMan.getPassword(username);

if(realPass==null){
logger.info("user rejected");
errors.rejectValue("password","error.wrongPassword",null,"Wrong Password");
return new ModelAndView(this.getFormView(), errors.getModel());
}

else if(inputPass.equals(realPass)){
logger.info("returning from LoginFormController view to " + getSuccessView());
User person=userMan.getInfoList(username);
logger.info("teste="+person.toString());
logger.info("user.fname="+person.getFirst_name());
logger.info("user.lname="+person.getLast_name());
//WebUtils.setSessionAttribute(request,"person", person);
//request.getSession().setAttribute("person", person);
//Map myModel=errors.getModel();
//myModel.put("person", person);

ModelAndView nModel= new ModelAndView(new RedirectView(getSuccessView()),"username",username);

return nModel;
}
else{
logger.info("password rejected");
errors.rejectValue("password","error.wrongPassword",null,"Wrong Password");
return new ModelAndView(this.getFormView(), errors.getModel());
}
}


and the url created by the controller is:
http://localhost:8080/springapp/groupsPage.htm?username=admin

the other controller is defined like this:


public class GroupFormController extends SimpleFormController{

private GroupManager groupMan;
protected final Log logger = LogFactory.getLog(getClass());
private UserManager userMan;

public ModelAndView onSubmit(Object command, BindException errors){

String gName=((GroupOperations)command).getName();
String gDescription=((GroupOperations) command).getDescription();
logger.info("name="+gName);
logger.info("desc="+gDescription);
String empty="";
if(gName.equals(empty)){
errors.rejectValue("name", "error.missingData");
return new ModelAndView(this.getFormView(),errors.getModel()) ;
}
else{
int state=groupMan.addGroup(gName, gDescription);
logger.info("state="+state);
if(state==0){
errors.rejectValue("name","error.existantGroup",null,"Grupo existente");
return new ModelAndView(this.getFormView(), errors.getModel());
}
else return new ModelAndView(new RedirectView(getSuccessView()),errors.getModel());
}

}

public void setGroupManager(GroupManager go){
this.groupMan=go;
}

protected Map referenceData(HttpServletRequest request) throws Exception {
logger.info("inside referenceData");
String username = ServletRequestUtils.getStringParameter(request, "username");
logger.info("still inside referenceData");
User person = userMan.getInfoList(username);
Map model = new HashMap();
model.put("person", person);
return model;
}
}



And the error is:

2006-10-12 11:06:03,019 INFO [permissions.GroupFormController] - inside refereceData
2006-10-12 11:06:03,199 ERROR [org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/springapp].[springapp]] - Servlet.service() for servlet springapp threw exception
java.lang.NoClassDefFoundError: org/springframework/web/bind/ServletRequestUtils
at permissions.GroupFormController.referenceData(Grou pFormController.java:53)

What's the problem. Why can't I get the string username ?

Thanks

Rui Gonçalves

Marten Deinum
Oct 12th, 2006, 06:15 AM
It appears as if the ServletRequestUtils cannot be found. Maybe there is an old spring version in your classpath or one of the reference libraries is not compatible.

My guess is that in your development environment you have a Spring 2.0 jar and on your server classpath an Spring 1.2.x jar somewhere (or maybe an old version milestone/rc of Spring 2.0 jar).

pranxas
Oct 12th, 2006, 06:47 AM
Maybe it's that, but I changed all the included jars to the new ones and still having the same error. Besides the jars changing, do I need to do anything else?

Marten Deinum
Oct 12th, 2006, 07:06 AM
Check your classpath for old spring jars. Make sure in your development environment and server you have the same spring jars.

Else try RequestUtils instead of ServletRequestUtils that is the one shipped with Spring 1, in Spring 2 it is deprecated. If the errors still occur, then it might be that you are missing a jar on your classpath.

pranxas
Oct 12th, 2006, 10:36 AM
You were right. I solved the problem.
Thanks a lot!