Bind a form object to a ModelAttribute with a prefix? - spring

I have a legacy application that contains lots of forms from a previous framework that required a prefix for the entity. For example, an Item object with a name would have a form field of:
<input name="item.name" ... />
In my spring controller, I use a ModelAttribute as normal:
#ModelAttribute Item item
But the binding fails because spring does not expect the prefix for the item. Is there some way I can tell spring to ignore the prefix and bind without having to create a wrapper object or having to change the prefix from every form field?

If you are using jsp as your view, you will also need to add modelAttribute in your form as well, and make sure that you have declared getters for your form fields in Item object. Ex: getName()
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<form:form id="new-item-form"
method="post"
modelAttribute="item" ...>
<input name="item.name" ... />
</form:form>
If you're using Thymeleaf , then you have to add its XML namespace to your html, and then you can access model attributes in views with Thymeleaf using Spring EL as follows:
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
...
<p th:text="${item.name}">Name</p>
...
</html>

Related

How to remove Public render parameter from jsp or render phase of portlet class

I have two portlets :
1. Blog Portlet.
2. Author Portlet.
I used the concept of Public render parameter to send data (say key "urlTitle") from Blog portlet to Author portlet
But after sending "urlTitle" from Blog portlet how can I remove the data from Public render parameter
In Blog Portlet
EX code: view.jsp
<portlet:renderURL var="viewEntryURL">
<portlet:param name="struts_action" value="/blogs/view_entry" />
<portlet:param name="redirect" value="<%= currentURL %>" />
<portlet:param name="urlTitle" value="<%= entry.getUrlTitle() %>" />
</portlet:renderURL>
Send Data
Now how I can remove "urlTitle" form the public render parameter after data is sent.
Please give feedback.
-Thanks in advance
You could think about the following:
The LiferayPortletURL (the class that models portlet render, action and resource URLs tags) offers a method called setCopyCurrentRenderParameters
https://docs.liferay.com/portal/6.2/javadocs/com/liferay/portal/kernel/portlet/LiferayPortletURL.html#setCopyCurrentRenderParameters(boolean)
which when set to false, avoids copying render parameters, and the URLs are "cleaned" from those.
The caveat with this is that you would need to create a LiferayPortletURL in the back end doing the following:
LiferayPortletURL renderUrl = PortletURLFactoryUtil.create(
httpServletRequest,
themeDisplay.getPortletDisplay().getId(),
themeDisplay.getPlid(),
PortletRequest.RENDER_PHASE);
renderUrl.setCopyCurrentRenderParameters(false);
and after that pass it to your JSP set as an attribute (maybe renderRequest.setAttribute("renderUrl",renderUrl)?). I haven't done this for render URLs, but for resource URLs and it works!
You need to set
javax.portlet.init-param.copy-request-parameters=false
in your portlet class.

Spring Model Attribute overriding the Session Attribute with same name

I am very new to Spring world and trying a few things related to Spring MVC and session handling.
my question is that if we have Model Attribute and session attribute of same name then does the Model Attribute overrides the value of session attribute ?
In code snippet below (apologies for poor formatting, I am new here) I am adding an attribute names sessionAttribute into Model and Session. While accessing the same attribute in JSP I am getting value of Model Attribute ([name] as Model Attribute ).
#RequestMapping(value="/hello", method=RequestMethod.GET)
public String hello(#RequestParam(value="username", required=false,defaultValue="World") String name, Model model,HttpServletRequest req) {
model.addAttribute("sessionAttribute", name+" as Model Attribute");
System.out.println("In controller");
HttpSession hs=req.getSession();
hs.setAttribute("sessionAttribute","overridden Session attribute"); //prints"overridden Session attribute"
System.out.println(hs.getAttribute("sessionAttribute"));
return "someViewName";
}
Below is the View (someViewName) and it is printing the value of sessionAttribute as Model attribute
<%# page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!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>Spring4 MVC -HelloWorld</title>
</head>
<body>
<% HttpSession hs=request.getSession();
String sesstionAttr=(String)session.getAttribute("sessionAttribute");
out.println(sesstionAttr); //printin [name] as Model Attribute
%>
</body>
</html>
my question is that if we have Model Attribute and session attribute
of same name then does the Model Attribute overrides the value of
session attribute ?
In general, model and session are different things, therefore model attributes and session attributes are different. Model attributes are referring to the model properties (which you have in your view), and session attributes are stored in http session, so that if you add one attribute in session in one controller and then change a view, you can still access added attribute in another one.
So if you are inside of your controller method, adding the session attribute into session will not override the value in model attribute.
However, this may happen in one case - if you are using #SessionAttributes provided by Spring exactly for this reason.
When using #SessionAttributes after your method execution will be finished, Spring will load all attributes from your model, and add them into the session (so that if you have the same name it will be overridden). And next time you try to access the attribute from the session - you will see overridden value from model.
For me it looks like this is happening in your case. However I do not how you have configured your controller, so check if you have specified
SessionAttributes or not.

Java - modelandview in modelandview

How can I addObject to modelandview with modelandview parameter? I mean something like that:
ModelAndView mav = new ModelAndView();
mav.setViewName("index");
ModelAndView m = new ModelAndView();
m.addObject("test", t, '1');
mav.addObject("site", m);
I mean I have a index file witch I deal like a template and I want to parse it to other file (template)
My second question:
Is this good solution? If not, please tell me what is preffered:)
Sorry, I'm new to Java EE and Spring
edit: source code
ModelAndView is just a container used by Spring's MVC request handling. Every object you add to ModelAndView will be added as request attribute (request#setAttribute) and then available within your JSP.
Nesting ModelAndView does not make any sense. You can just forward the request from your JSP file and all the model attributes will be still set on the request and available.
Regarding your approach:
I would say that having template JSP (such as your index) can be used. I personally prefer having TAG file with layout and then JSP files being enclosed within this layout.
<%# tag language="java" description="Content border for layout decoration." trimDirectiveWhitespaces="true" %>
<!DOCTYPE html>
<html lang="cs">
<head profile="http://www.w3.org/2005/10/profile">
<meta charset="utf-8" />
</head>
<body>
<div class="pageContent">
<jsp:doBody />
</div>
</body>
</html>
-
<%# include file="/WEB-INF/taglib.jspf"%>
<layout:admin>
THIS IS MY CONTENT
</layout:admin>
Alternatively you can use templating engine such as Apache Tiles.

spring mvc addAttribute to model, how to get it from jsp javascript

i have a controller with a model which i do addAttribute("show", "yes");
how do I retrieve this value inside javascript?...assuming I have jstl
Inserting it in a javasript would be the same as showing it in the html code of the jsp.
Try to do this:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...
Show value is <c:out value="${show}"/>
if you can see the value in the JSP then JSTL is working. In any other case there may be another problem. For example that your configuration ignores EL. You can add this at the top of your JSP:
<%# page isELIgnored="false" %>
When you see the value in the HTML code then the JSTL is working in that case you can use it in Javascript. As your setting the value for tha variable "show" to yes it cannot be used as a boolean value (because it should be true or false). In this case you should use it as a string adding quotations
<script type="text/javascript">
var showVar = '<c:out value="${show}"/>';
alert("The variable show is "+showVar);
</script>
You can use Firebug to check that your javascript is working and you don't have any error on it.

extending spring form tag library attributes

I'm using Spring's form tag library in a Spring MVC application that I am developing. The company I am working for has implemented some company-wide policies based on the definition of custom attributes for certain tags. For instance, by default (though the inclusion of a standard javascript file) all tags have their values automatically converted to upper case. In order to disable this one would define their tag with a custom attribute in the following way:
<input type="text" uppercase="false" />
The problem is that the addition of these custom attributes to a spring:form tag causes an error at runtime. I've pasted the error below.
org.apache.jasper.JasperException: /WEB-INF/jsp/reportCriteria.jsp(45,5) Attribute uppercase invalid for tag input according to TLD
My question is: is there any way to extend the TLD to allow for these attributes, or is there any other way add these custom attributes to these spring:form tags?
Ok, 2 years later... here we go!
HOW TO CREATE OUR OWN TAG EXTENDING CLASSIC ONE WITH NEW ATTRIBUTES IN SPRING MVC 3
1. Create your own taglib.tld
You need to create your own TLD file. There you are going to add the new attribute you are going to use. The best option is copy/paste spring-form.tld. You can find it in spring-mvc package (org.springframework.web.servlet-.jar).Search in META-INF folder.
Feel free to put it directly inside WEB-INF or in a subfolder. I putted it in /WEB-INF/tld.
Now search inside your new TLD file for the tag you are going to modify. I modified input tag, so i had to search for:
...
<tag>
<description>Renders an HTML 'input' tag with type 'text' using the bound value.</description>
<name>input</name>
<tag-class>org.domain.tags.CustomTags</tag-class>
<body-content>empty</body-content>
<attribute>
...
Copy from to and paste it below. Change the of the new tag for your own name. Mine was myInput. So now we have this:
...
<tag>
<description>Renders an HTML 'input' tag with type 'text' using the bound value.</description>
<name>input</name>
<tag-class>org.springframework.web.servlet.tags.form.InputTag</tag-class>
<body-content>empty</body-content>
<attribute>
...
</tag>
<tag>
<description>Renders an HTML 'input' tag with type 'text' using the bound value.</description>
<name>myInput</name>
<tag-class>org.domain.tags.CustomTags</tag-class>
<body-content>empty</body-content>
<attribute>
...
</tag>
SUMMARY: now I have a new file called taglib.tld here: /WEB-INF/tld/taglib.tld. Pay attention to the <tag-class> part
In your own new tag add a new attribute (copy/paste another one) call render.
<attribute>
<description>Enables/Disables the field rendering</description>
<name>render</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<type>java.lang.Boolean</type>
</attribute>
Now we have created the taglib file we need. Let's see how to use it.
2. Create your own handler
Now we are going to create the class that will handle the new attribute (and the classic ones). I created the class CustomTags.java en el paquete org.domain.tags. Let's see first the code and explain it:
package org.domain.tags;
import javax.servlet.jsp.JspException;
import org.springframework.web.servlet.tags.form.InputTag;
import org.springframework.web.servlet.tags.form.TagWriter;
public class CustomTags extends InputTag {
private static final long serialVersionUID = 1L;
private boolean render;
public boolean isRender() {
return render;
}
public void setRender(boolean render) {
this.render = render;
}
protected int writeTagContent(TagWriter tagWriter) throws JspException {
if(render){
super.writeTagContent(tagWriter);
return SKIP_BODY;
}
else
return SKIP_BODY;
}
}
Of course, if we are going to add some features to the Input tag of Spring framework, we must extend it in order to mantain the rest of the features. As you can see, we have just added the render private attribute as boolean (in taglib.tld we also put it).
We have added to the getter and setter methods for this attribute.
Finally we have overwrite the writeTagContent method in order to make the JSP do what we want. In this case we want the input field to be shown if render is true. Otherwise the field can't be shown. That's why we call the writeTagContent of the parent class.
If we need to make some changes on the tag behaviour, this method is the right place to do them.
3. Using the new tag.
Now we only need a JSP with a form to use the new tag. It's easy to do, so i only let here the code:
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib prefix = "newtags" uri = "/WEB-INF/tld/taglib.tld" %>
<!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>Spring 3.0 MVC Series: Welcome World</title>
</head>
<body>
<h1>User Data</h1>
Please, fill the fields with your information:<br>
<newtags:form name="userForm" id="userForm" modelAttribute="userForm" action="user.htm" method="POST">
Name: <newtags:myInput type="text" name="textName" path="userName" render="true" size="50" /><newtags:errors path="userName" /><br>
Surname: <newtags:myInput type="text" name="textSurname" path="userSurname" render="true" size="50" /><newtags:errors path="userSurname" /><br>
Age: <newtags:myInput type="text" name="textAge" path="userAge" render="true" size="2" /><newtags:errors path="userAge" /><br>
Example: <newtags:myInput type="text" name="textSurname" render="false" size="20" path="userSurname"/>
<hr>
<input type="submit" value="Next" />
</newtags:form>
</body>
</html>
Now instead of calling springframework tld, we call our own TLD. As you can see the only field that is not going to be shown is Example one.
Good Luck all!
It's implemented in Spring 3.0 (SPR-5931).

Resources