I'm new to Spring MVC (3.1.1). Coming from a Rails and Struts1 world that is.
In Struts, our FormBeans automatically map to our controllers. For example:
# JS file
ExtJS.ajax({action:'update', value:42});
Then our controller can:
bean.getAction(); // 'update'
bean.getValue(); // 42
We instantiate the bean like:
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
MyBean bean = (MyBean) form;
....
}
Please forgive my ignorance, but how would I do the same thing in Spring MVC?
In jsp do something like this :
<%# taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<form:form name="frmFoo" id="frmFoo" action="/FormSubmitUrl" method="POST" modelAttribute="foo">
<form:select path="myField">
<form:errors path="myField" />
</form:form>
And just add the backing object to the model in your controller method :
#RequestMapping(value = "/MyFooForm", method = RequestMethod.GET)
public String getFoo(final Model model)
{
model.addAttribute("foo", foo);
return "fooForm.jsp";
}
Am going from, Spring MVC - Rails. I like Rails lot better :-). There are lot of start up tutorials for Spring MVC. But spring has a good tutorial that you can follow. But to begin with you will have to start with the spring-dispatch-servlet.xml. There you will define your association between views, controller and form. For example in this following snippet:
<bean name="/priceincrease.htm" class="springapp.web.PriceIncreaseFormController">
<property name="sessionForm" value="true"/>
<property name="commandName" value="priceIncrease"/>
<property name="commandClass" value="springapp.service.PriceIncrease"/>
<property name="validator">
<bean class="springapp.service.PriceIncreaseValidator"/>
</property>
<property name="formView" value="priceincrease"/>
<property name="successView" value="hello.htm"/>
<property name="productManager" ref="productManager"/>
</bean
Controller is the PriceIncreaseFormController and the priceIncrease is the equivalent command object. The corresponding view i.e. JSP will have
<form:form method="post" commandName="priceIncrease">
<table width="95%" bgcolor="f8f8ff" border="0" cellspacing="0" cellpadding="5">
<tr>
<td align="right" width="20%">Increase (%):</td>
<td width="20%">
<form:input path="percentage"/>
</td>
<td width="60%">
<form:errors path="percentage" cssClass="error"/>
</td>
</tr>
</table>
But I think you might get a complete picture from this place where I picked up the code from
http://static.springsource.org/docs/Spring-MVC-step-by-step/part4.html#step4.5 and the place where you can get Spring MVC's example code base is https://src.springframework.org/svn/spring-samples/mvc-basic
I was looking for this answer today based on some code in a project I inherited. What I found was that the if you create a controller action on a multiActionController. The form values can be mapped to a bean that would be the third paarameter on your handler action.
In my case I had a controller like this
public void submit(HttpServletRequest request,
HttpServletResponse response, SomeBean sb) {
{
//do something with sb - SomeBean
}
My issue was in figuring out how the values in my form were mapped to the controller action. There was no reference at all to the SomeBean within my jsp form. As it turns out Spring works the magic based on the controller action parameters and the names used in the form. It basically maps the values in the form to a bean that is used as the third parameter in the action method.
For example my SomeBean has some fields named byday and bymonth. It also has the corresponding byday and bymonth setters and getters (i.e. getBymonth(), setBymonth). In my for my submit action is mapped on submit and I have input values for byday and by month like so:
<select id="weekly_option" name="byday">
<option value="MON">Monday</option>
<option value="TUE">Tuesday</option>
<option value="WED">Wednesday</option>
<option value="THU">Thursday</option>
<option value="FRI">Friday</option>
<option value="SAT">Saturday</option>
<option value="SUN">Sunday</option>
</select>
I had to do some digging on how exactly the mappings were being done. I peeked into the MultiActionController source code to see that if does the following:
The controller figures out if you have a third parameter in your action (it must not be of the type HttpSession).
The MultiActionController then news up an instance of the third parameter (SomeBean). Based on the http request values it pushes over all the values from the HttpServleRequest over to the SomeBean object.
At this point it seems like it only works with properties that are strings. I imagine that you would have to extend MVC somehow if you wanted to work with properties other than strings within your bean.
Related
I would like to know how i could sumbit a form in mvc 4 without using a model binding to the view.
can some one please demontrate how? and how can i use that form in the controller?
It is very easy to use a form without any sort of Model binding.
Simple set up your for using either #using(Html.BeginForm()){ ... } or plain html.
<form id="myForm" action="/ControllerName/ActionName" method="Post">
<input type="text" name="foo" value="FOOOO" />
<input type="text" name="bar" value="Baaaar" />
<button type="submit">Submit</button>
</form>
When you post this to the ActionResult, your action result just needs to be set up to accept a string value named foo and one named bar
[HttpPost]
public ActionResult ActionName(string foo, string bar){
// your code here
return View();
}
I want to do a mcq with Spring mvc. I've got a class Mcq with a OneToMany relationship with the class Question, which has a OneToMany relationship with the class Answer. Thus Mcq have as property an Arraylist ListOfQuestions, and Question an Arraylist ListOfAnswers.
My controller is
#RequestMapping(value="displayMcq", method = RequestMethod.GET)
public String showMcq(Model model) {
Mcq mcq = mcqService.findById(new Long(1));
model.addAttribute("mcq", mcq);
return "displayMcq";
}
#RequestMapping(method = RequestMethod.POST)
public String displayQcmRepondu(#ModelAttribute("mcq2") Mcq mcq, BindingResult binding, SessionStatus status) {
if (binding.hasErrors()) {
return "displayMcq";
} else {
status.setComplete();
return "redirect:/mcqSuccess/";
}
}
and my view displayMcq.jsp is
<form:form modelAttribute="mcq" method="POST">
<ol>
<c:forEach items="${mcq.listOfQuestions}" var="question">
<li>
<c:out value="${question.label}" />
<br />
<ul>
<c:forEach var="answer" items="${question.listOfAnswers}">
<form:checkbox path="listOfQuestions" value="answer.id" label="${answer.label}" />
<br />
</c:forEach>
</ul>
</li>
</c:forEach>
</ol>
<input type="submit" value="Validate" />
</form:form>
My mcq is well displayed but the processing of the form fails. I stay on the displayMcq appearance with the error "Etat HTTP 405 - Request method 'POST' not supported".
So, could you explain me the problem, help me to proccess my mcq correctly and return the checked answers?
Note that your controller methods are mapped to different URLs (due to absence of value attribute on your POST method).
Since you don't have action attribute in <form:form>, it sends a POST request to the current page's URL on submit, but you don't have controller methods to handle POST request to that URL.
So, you need to map your POST method to the same URL as your GET method:
#RequestMapping(value="displayMcq", method = RequestMethod.POST)
public String displayQcmRepondu(...) { ... }
Thanks, that solved one problem, but when I validated, I had a message error like "Failed to convert property value of type java.lang.String[] to required type java.util.List for property...".
So I modified the controller method as
#RequestMapping(value="displayQcm", method = RequestMethod.POST)
public String displayQcmRepondu(#ModelAttribute ("mcqProcess") Mcq mcq, BindingResult binding, Model model, SessionStatus status) {
model.addAttribute("mcqProcess", mcq);
status.setComplete();
return "mcqSuccess";
}
where I want to display the checked answers in mcqSuccess.jsp but the mcq was not submitted. I show the page, but juste the written text.
If it can help, the mcqSuccess is
<h2>MCQ submitted</h2>
<ol>
<c:forEach items="${mcqProcess.listOfQuestions}" var="question">
<li>
<c:out value="${question.label}" />
<br/>
<ul>
<c:forEach var = "answer" items = "${question.listOfAnswers}">
<c:if test = "${answer.correct}">
<c:out value = "${answer.label}" />
</c:if>
<br/>
</c:forEach>
</ul>
</li>
</c:forEach>
</ol>
</div>
i have the following html in my view
<span style="float:right"> <label> Pattern :</label>
<select>
<option value="3*3">3*3</option>
<option value="6*6">6*6</option>
<option value="12*12">12*12</option>
</select>
</span>
what i want to do is that i want to call my action onchange lets say
if(3*3) call this
public function 3by3Action(){}
if(6*6) call this
public function 6by6Action(){}
if(12*12) call this
public function 12by12Action(){}
In Zend Framework, Actions are methods within a Controller class and are accessible via URL. For example, if your Controller class is called "MathController" and it contains an action called "sixBySixAction", then you would trigger this action by navigating to a URL that looks something like:
http://baseUrl/math/six-by-six
Notice that the name of the action method is camel case within the controller class but it is separated by dashes in the URL. This is a formatting requirement for Zend Framework. Also note that the controller class is named "MathController" but you only have to put "math" in the URL.
So, you could use JavaScript to assign an onChange handler for your select box which simply redirects to a particular URL which handles the change by accessing a particular action method within a particular controller class.
For more information on this, check out this page in the Zend Framework Programmer's Reference Guide.
As for the JavaScript part, here is an example of how to redirect upon a select box being changed. You'll need to modify this, of course, but it'll get you started:
<Script language="JavaScript">
function goto(form) { var index=form.select.selectedIndex
if (form.select.options[index].value != "0") {
location=form.select.options[index].value;}
}
</SCRIPT>
<FORM NAME="form1">
<SELECT NAME="select" ONCHANGE="goto(this.form)">
<OPTION VALUE="">-------Choose a Selection-------</OPTION>
<OPTION VALUE="index.htm">Home</OPTION>
<OPTION VALUE="web_development.htm">Web Development</OPTION>
<OPTION VALUE="html_codes.htm">HTML Tips</OPTION>
<OPTION VALUE="html_codes_chart.htm">HTML Code Chart</OPTION>
<OPTION VALUE="javascript_codes.htm">JavaScript Codes</OPTION>
<OPTION VALUE="216_color_chart.htm">Color Code Chart</OPTION>
</SELECT>
</FORM>
You need to be more specific on why you want to call your actions like that.
You can use AJAX to fetch some data produced by your actions or you can do a simple redirect. It depends on what you want to achieve.
The AJAX solution:
attach an onchange event handler to select
the handler issues an AJAX request to the server, to the correct action. You can easily output JSON data from the controller using $this->_helper->json($data)
you get back information from server and inject to your HTML document
change your html to this
<select id="your_id">
<option value="Threes">3*3</option>
<option value="Six">6*6</option>
<option value="Twele">12*12</option>
</select>
in js write this
$("#your_id").change(function() {
var action = $("#your_id").val();
var href= "Controller/"+action +"/";
var data = your data;
$.ajax({ type: "GET",
url: href,
data: data,
success: function(response){
//do what u wana do
}
});
}):
hope it works
I have a Map<Course, Role> courses belonging to the command object user and I want to select a role from roles[enum array] = Role.values for each course in the keyset. I populate the entries with all the courses I want and a default role and put this in the user in the model. Below is my form, but I can't figure out how to refer to the key (which is "course") for the map
<form:form method="POST" commandName="user">
<table>
<tr>
<td>User Name:</td>
<td><form:input path="name" /></td>
</tr>
<c:forEach var="course" items="${courseChoices}">
<tr>
<form:radiobuttons path="courses['${course}']" items="${roles}"/>
</tr>
</c:forEach>
</table>
<input type="submit" value="save changes">
<form:errors path="*" />
</form:form>
I have a propertyeditor bound to convert Course to String and back, which simply uses the entity id.
I am getting
InvalidPropertyException:
Invalid property 'courses[com.example.app.Course#7]' of bean class [com.example.app.User]:
Invalid index in property path 'courses[com.example.app.Course#7]';
nested exception is org.springframework.beans.TypeMismatchException:
Failed to convert property value of type 'java.lang.String' to required type 'com.example.app.Course' for property 'null';
nested exception is java.lang.NumberFormatException: For input string: "com.example.app.Course#7"
I don't know what is null, because I can see the Course with id 7 in my database.
Fundamentally, what is evaluating the path attribute and how does it understand the jsp context? Is this Spring expression language? I've been looking for resources to figure out how to pick values for my map keys from my set of roles, but I haven't found much.
I suppose you have a getter getId() or something similar in courses so instead of path="courses['${course}']" in the radiobuttons tag write path="courses['${course.id}']" (or course.whateverTheIdIsCalled for an id getter getWhateverTheIdIsCalled())
I am looking to find out the difference between the spring:bind and form:form tag libraries when submitting a form.
A snippet of my JSP is as follows:
<form:form modelAttribute="testRulesForm">
....
<td>
<form:checkbox path="rules[${counter.index}].isActive" value="rules[${counter.index}].isActive"/>
</td>
<td>
<form:select path="rules[${counter.index}].leftCondition.name">
<form:options items="${testRulesForm.ruleAttributes}" itemLabel="name" itemValue="name" />
</form:select>
</td>
<td>
<form:select path="rules[${counter.index}].operator">
<form:options itemLabel="operator" itemValue="operator" />
</form:select>
</td>
....
Seeing as I have my path variable specified and this will be bound to my modelAttribute, does this mean that I do not need spring:bind?
Thanks
Normally you don't need to use <spring:bind> if you already use form taglib.
They do basically the same with respect to model attributes, but tags from form taglib also generate HTML form markup, whereas with <spring:bind> you need to generate markup yourself.
The following code with form tags:
<form:form modelAttribute = "foo">
<form:input path = "bar" />
</form:form>
is similar to the following code with <spring:bind>:
<spring:bind path = "foo">
<form method = "get">
<spring:bind path = "bar">
<input name = "bar" value = "${status.displayValue}" />
</spring:bind>
</form>
</spring:bind>
<spring:bind> is useful when you need something customized, that cannot be achieved by form taglib.