Spring + JQuery dynamic binding - java

I am new to Spring and still learning. I want to make some more advanced form handling.
Currently my problem is dynamic list binding.
I want to have one text box, one list and add button. What is scenario?
User populates text box(with autocomplete) and cliks add button. After initiation add action, list gets populated without issuing request to server.
User adds few more items to list, and then submits form to server.
What is problem?
I dont know how to bind list or pass dynamic data to server.
Currently I have managed to get JSON response from Controller with list for autocomplete.
Is Spring forms suitable for this task? What is the right way to implement this?

Here's a stab at what I think you're trying to achieve. First: I'm assuming the issue isn't autocomplete/add to list, but rather what to do with the list in the MVC side. Let's say your command object has a property "employee names," defined as
List<String> getNames(){..}
void setNames(List<String>){..}
On the JSP side, you define the form list items like so:
<form:form>
<c:forEach items="${command.names}" var="name" varStatus="status">
<form:input path="names[${status.index}]" />
</c:forEach>
</form:form>
The real trick to making it "dynamic" with jQuery is to add to the form with the next increasing index. So somewhere you have:
<script type="text/javascript">
var count = ${fn:length(command.names)};
function addToList()
{
// add to form with name to "names[count]"
count++;
}
</script>
Putting it all together, you set the list in the controller formBackingObject to an AutoPopulatingList
That should be enough to get you started.

Related

How does the Spring forms .jsp tag library work?

So I have a .jsp page which has a form on it, like this (naturally this is a massive simplification):
<form:form commandName="myCommand" method="post">
<form:select path="values" class="select-tall" multiple="multiple" id="mySelect">
<option>first</option>
<option>second</option>
<option>third</option>
</form:select>
<button type="submit" class="button">Save</button>
</form:form>
When the submit button is pressed, the form is submitted(somehow) and the path= attributes are used to bind the data inside the form elements to the properties of an instance of a plain old java object. I understand how this POJO is specified, and I understand how the POST request is routed to the correct controller, but I don't understand where or how the form values are mapped to the given POJO.
What I don't understand is:
How does the spring tag library modify the form such that this binding takes place?
How would one go about doing this in a manual or ad-hoc fashion(using a Javascript onSubmit() method, say)?
Essentially my question is: How does the spring-form.tld tag library work?
Any resources, or even a high-level explanation in your own words, would be extremely helpful.
I've implemented a work-around solution in the mean time (dynamically adding items to a hidden form element), but I feel like this is hack-y and the wrong solution.

Spring mvc form post to different controller, or overthinking this

I made this way more confusing than it needed to be. Here is the simplified version.
1 - I have a drop down and a submit button on every page in the upper right hand corner. The drop down is a list of languages. The user can change the language and press the submit button to go to the language controller and update the current language.
public class LanguageController {
#ModelAttribute("languageList")
public LanguageList populateLanguageList() {
return LanguageDAO.all();
}
#RequestMapping("/setLanguage.mvc")
public ModelAndView setLanguage(
#ModelAttribute("languageForm") LanguageForm languageForm,
HttpServletRequest request,
HttpServletResponse response
){
//do stuff
}
}
<form:form modelAttribute="languageForm">
<form:select path="acctGrpId" >
<form:options items="${languageList}"/>
</form:select>
<input type="submit"/>
</form:form>
How would I make that available on every page? Given that the page might be a page where you are editing/creating a user so the "Controller" of that page is actually a UserController, or RoleController, or DepartmentController, not the LanguageController. I need this particular jsp to hit a specific controller regardless of what the page is doing.
You just specify different action attribute in different forms. There's no problem in having multiple forms on one page.
In your case it would be:
<form action="Context/adduser.mvc">
</form>
and
<form action="Context/addBookmark.mvc">
</form>
etc
I would love to help you on this, but I am unsure of your requirements.
Are you talking about BookMarkController having various methods and add/upload calling the methods?
or you want BookMarkController to have more than one form?
Could you please elaborate more on this?
I believe, you want all the jsp pages to post data to a controller which can save the form when a link is clicked. This is quite simple, you can add a savePage method in all the controllers and map the uri accordingly and from the savePage method you can reedirect the request to the specific controller which you have written to save the pages.
Hope this helps.
Your JSP is the view, which is separate from your controller. That's the beauty of MVC, the separation of the Model, View, and Controller. You shouldn't necessarily think of the view as being tied to a controller, or a page as having a "current" controller. Yes, we often make that association pretty strong because the controller handles populating the model attributes to render the view and processing the form post as a result of an action in the view, but really any controller can return any view as long as it populates the model correctly, and any view can submit to any controller. A view can even submit to different controllers at different times depending on the url that is followed.
So, in your case, as soulcheck says, you simply change the URL that the form submits to. Because the controllers are mapped by the #RequestMapping, changing the form's action will change the controller class and/or method that is called when the form is submitted as long as Spring MVC can find a suitable RequestMapping.
Is this what you are looking for?
What are the best practices around setting global model attributes in Spring MVC?
implement a HandlerInterceptor, and expose the data to every request

Set request attributes when a Form is POSTed

Is there any way to set request attributes (not parameters) when a form is posted?
The problem I am trying to solve is: I have a JSP page displaying some data in a couple of dropdown lists. When the form is posted, my Controller servlet processes this request (based on the parameters set/specified in the form) and redirects to the same JSP page that is supposed to display addition details. I now want to display the same/earlier data in the dropdown lists without having to recompute or recalculate to get that same data.
And in the said JSP page, the dropdown lists in the form are populated by data that is specified through request attributes. Right now, after the Form is POSTed and I am redirected to the same JSP page the dropdown lists are empty because the necessary request attributes are not present.
I am quite the n00b when it comes to web apps, so an obvious & easy solution to this problem escapes me at the moment!
I am open to suggestions on how to restructure the control flow in the Servlet.
Some details about this app: standard Servlet + JSP, JSTL, running in Apache Tomcat 6.0.
Thanks.
.. and redirects to the same JSP page ..
You shouldn't fire a redirect here, but a forward. I.e. do not do
response.sendRedirect("page.jsp");
but rather do
request.getRequestDispatcher("page.jsp").forward(request, response);
This way the original request remains alive, including all the parameters and attributes. A redirect namely instructs the client to fire a brand new request, hereby garbaging the initial request.
In JSP you can access request parameters by ${param} in EL and you can access request attributes the same way with ${attributeKey} where attributeKey is the attribute key which you've used to set the object in the request scope in the servlet as follows:
request.setAttribute("attributeKey", someObject);
As to retaining HTML input values in a JSP, you just need to set the <input> element's value attribtue accordingly with the request parameter value:
<input name="foo" value="${param.foo}">
This prints the outcome of request.getParameter("foo") in template text. This has however a XSS risk, better is to escape any user-controlled input with help of JSTL's fn:escapeXml() as follows:
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
...
<input name="foo" value="${fn:escapeXml(param.foo)}">
Retaining the selected option in a dropdown is a bit different story. You basically need to set the selected attribute of the <option> element in question. Assuming that you're -as one usually would do- using JSTL's <c:forEach> tag to display a Map<String, String> or maybe a List<JavaBean> of option values, you can solve it as follows (assuming ${countries} is a Map<String, String> which you've placed as an attribute in the request, session or application scope):
<select name="country">
<c:forEach items="${countries}" var="country">
<option value="${country.key}" ${country.key == param.country ? 'selected' : ''}>${country.value}</option>
</c:forEach>
</select>
This prints the selected attribute when the currently iterated option key equals the submitted one in the request parameter map.

How do I bind HTML table data to a java object in a spring controller?

I have a spring MVC application using JSP as my view technologies with Jquery for AJAX. I have a table such as the following:
<table>
<tr>
<td>name1</td>
<td>value1</td>
<td>setting1</td>
</tr>
<tr>
<td>name2</td>
<td>value2</td>
<td>setting2</td>
</tr>
</table>
I need to serialize this table so that it can later be bound to an object in my controller. However the jquery serialize() method only works on form fields. What would be the best approach to get the table data into the HTTP request so that I can later bind it to a java object?
EDIT:
I have a java object that has a collection so
class MyOject {
private List<AnotherObject> items = new ArrayList<AnotherObject>();
// standard getters and setters
}
class AnotherObject {
private name;
private value;
private setting;
// getters and setters
}
In the screen the user is creating new items on the fly. When the user is done, they submit the form and then I need to process all the items in the list and instantiate a new collection with those items.
For display purposes I am creating a new table row when an item is created.
The <Form> tag is how you tell the browser "Put this stuff in the web request." That's how you get object binding in Spring. What is your reason for not using a Form? You don't necessarily have to put it in a form in the page, you could give your table elements IDs and fetch their contents in the javascript if you really needed to.
Edit: I think maybe it's hard to answer because it's not clear why you want the browser to give you back things that you gave it in the first place. Maybe what you really need is the #SessionAttributes() annotation on your controller so that you can preserve State of the original page shown to the user?
More Edit:
kk, see now. If what you want is Spring web data binding then create a form in parallel as you add more table rows. e.g.,
<form id="myObject" action="whateverYouNeedHere.htm" method="post">
<input type="hidden" id="items[0].name" name="items[0].name" value="foo"/>
<input type="hidden" id="items[0].value" name="items[0].value" value="bar"/>
<input type="hidden" id="items[0].setting" name="items[0].setting" value="buzz"/>
<input type="hidden" id="items[1].name" name="items[1].name" value="foo"/>
<input type="hidden" id="items[1].value" name="items[1].value" value="bar"/>
....
Then just submit that and it will bind right on for you. If you did mean to handle the content yourself, then you probably could use XHR as someone else mentioned.
Use the Spring Data Binding and Validation API to bind it into a Java object of your own design. That documentation is web-agnostic; check out the later chapter to see how the web tier leverages it.
You'll want an abstraction beyond a table, I presume.
in order to stick your table information into a java object, you will first need to send it to the server.. for that you will need to either send it via XHR or in a form.
in order to serialize the object you will need to write some javascript/jquery.
i could write it for you, but your requirements are somewhat vague when it comes to how your table will look, nor do i want to guess about what the java object you want to add your data to looks like.

Two pass JSP page rendering

Suppose an example. I have following interface:
public interface DataSource<T> {
Future<T> fetch();
}
This datasource can do asynchronous data fetching. And we have following tag for using datasource in JSP:
<html>
<d:fetch from="${orderDS}" var="orders">
<c:foreach in="${orders}" var="order">
<div class="order">
<c:out value="${order.title}" />
</div>
</c:foreach>
</d:fetch>
</html>
So, what I want? I want JSP rendering engine to call my custom tag (FetchTag in this example) twice. On first call FetchTag will do DataSource.fetch() call and save Future locally as a object field. On second call FetchTag do Future.get() call and will be blocked until data becomes available.
Is there any way to do such a thing?
I think a better design would not try to alter JSP rendering. Put all that database code on the server side, where it belongs, and use an AJAX call to get that data from a server-side component.
In general, I've found that embedding stuff in custom tag libraries is a bad idea. JSTL and/or Spring tag libraries are all that I need. If I feel like my UI needs to do more, I'm thinking about it incorrectly.
For JS disabled clients, I'd just make them do the round trip for the data and not try to do it in the background. Give them a choice: wait or turn on JS.

Categories