Spring MVC access form data - spring

I am new to spring mvc but I would like to know how I can access the data that the user inputs in a form.
these are some code snippets:
My controller
#Override
protected Object formBackingObject(HttpServletRequest request) throws Exception {
return new A();
}
where A is the class containing the 'model' that the form should return.
My view
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<form:form>
<table>
<tr>
<td><form:label path="amount">Amount:</form:label></td>
<td><form:input path="amount"/></td>
<td><form:errors path="amount"/></td>
</tr>
... some more fields
<tr>
<td><form:label path="message">Message:</form:label></td>
<td><form:input path="message"/></td>
<td><form:errors path="message"/></td>
</tr>
<tr>
<td colspan=3 align=right>
<button type="submit">Transfer</button>
</td>
</tr>
</table>
</form:form>
Q: How and where can I access the amount and message field in my controller to perform some action with the data? (perhaps after validating).

Appearently, the model was available in the onSubmit method:
#Override
protected ModelAndView onSubmit(HttpServletRequest request,HttpServletResponse response,
Object command, BindException errors) throws Exception {
ModelAndView mv = super.onSubmit(request,response,command,errors);
//TODO: SOME VALIDATING
A smth = (A)command;
//Do something with your object
return mv;
}

I assume class A has attributes amount and message with appropriate getters and setters.
Your controller method should then look like :
#RequestMapping("/url/for/the/form/action")
public String formBackingObject(#ModelAttribute A a, BindingResult error) {
// Spring automagically creates a A object and loads it with form parameters
// do you stuff, call services methods
return "viewname";
}
viewname is the name of the view, or can be "redirect:/other/url" if you use the post-redirect-get pattern.

Related

Mapping to List Object in Spring MVC when Page is not displayed by a Controller

I am trying to map the value from Front end to Back Bean which is a List. Now the problem is that the page/view is not displayed by a Spring controller it is a jsp which is being displayed by CMS(content management system). So I cant initialse List and add elements to it and pass as a mode attribute
This is how my bean looks
public class LodgingAvailabilityRequest implements Serializable
{
private List<GuestCount> guestCounts = new ArrayList<GuestCount>();
public List<GuestCount> getGuestCounts() {
return guestCounts;
}
public void setGuestCounts(List<GuestCount> guestCounts) {
this.guestCounts = guestCounts;
}
and the GuestCount has the count field
public class GuestCount implements Serializable
{
private Double count;
this is how my JSP looks like
<jsp:useBean id="lodgingAvailability" class="com.pegasus.gen.LodgingAvailabilityRequest" scope="request"/>
<jsp:useBean id="guestCount" class="com.pegasus.gen.GuestCount" scope="request"/>
<body>
<form:form method="POST" action="/lodgingbyroom" modelAttribute="lodgingAvailability">
<table>
<tr>
<td>Count: <form:input path=guestCounts[0].count /></td>
</tr>
<td><input type="submit" value="Submit lodgingAvailability request by ROOM type"/></td>
</tr>
</table>
</form:form>
Now using above code gives me Array Out of Bounds exception so I tried couple of things as mentioned in some other posts
Changed to this <td>Count: <form:input path="${guestCounts[0].count}" /></td> I dont get any compilation error but the vaue in controller is not getting mapped. The list is empty.
Added a for loop but this didnt work as expected since the list is empty and it wont enter the loop.
<c:forEach items="${lodgingAvailability.guestCounts}" varStatus="counter">
<tr>
<td>Count: <form:input path="guestCounts[${counter.index}].count" /></td>
</tr>
</c:forEach>
This is how my controller looks, where the form gets submitted
#RequestMapping(value = "/lodgingbyroom", method = RequestMethod.POST)
public String lodgingAvailabilityByRoom(ModelMap model, LodgingAvailabilityRequest request,
RedirectAttributes redirectAttributes) {
final RestTemplate restTemplate = new RestTemplate();
final Map<String, List<DXARoom>> groupByRoom = restTemplate
.postForEntity(pegasusPath + "/lodgingbyroom", request, Map.class).getBody();
redirectAttributes.addFlashAttribute("pegasusResponse", groupByRoom);
}
I was able to Fix the above problem. Since the list was not having any elements in it the only way to make it work is add a dummy element to list. So you can traverse the list and then map the values
<% lodgingAvailability.getGuestCounts().add(guestCount) ;%>
<% lodgingAvailability.getGuestCounts().add(guestCount) ;%>
<c:forEach items="${lodgingAvailability.guestCounts}" varStatus="counter">
<tr>
<td>Count: <form:input path="guestCounts[${counter.index}].count" /></td>
</tr>
</c:forEach>
for this piece of code to work make sure that you declare the beans
<jsp:useBean id="lodgingAvailability" class="com.pegasus.gen.LodgingAvailabilityRequest" scope="request"/>
<jsp:useBean id="guestCount" class="com.pegasus.gen.GuestCount" scope="request"/>

How to display image from mysql database using spring mvc

I am storing BLOB type image in MySQL database using Spring MVC for item class Item (itemId, itemName, itemPrice, itemContent, itemImage). I successfully stored image in database but when I'm trying to display it in my jsp, it is showing something binary like [B#7fb0c025.
How can I display proper image in JSP (image is stored in MySQL database table)
My model class:
#Entity
#Table(name="item")
public class Item {
#Id
#Column(name="ItemId")
#GeneratedValue
private Integer itemId;
#Column(name="ItemName")
private String itemName;
#Column(name="ItemContent")
private String itemContent;
/*
#Column(name="ItemImage")
private ByteArray ItemImage;
*/
#Column(name="ItemPrice")
private int itemPrice;
#Column(name="ItemImage")
private byte[] itemImage;
"addItem.jsp" to add item attributes along with the image in database.
<form:form modelAttribute="itemAttribute" enctype="multipart/form-data" method="POST" action="${Url}">
<table>
<tr>
<td><form:label path="itemId"></form:label></td>
<td><form:input path="itemId" type="hidden"/></td>
</tr>
<tr>
<td><form:label path="itemName">ItemName:</form:label></td>
<td><form:input path="itemName"/></td>
</tr>
<tr>
<td><form:label path="itemPrice">ItemPrice:</form:label></td>
<td><form:input path="itemPrice"/></td>
</tr>
<tr>
<td><form:label path="itemContent">ItemContent:</form:label>
<td><form:input path="itemContent"/>
</tr>
<tr>
<form:label for="itemImage" path="itemImage">itemImage:</form:label>
<form:input path="itemImage" type="file" />
</tr>
</table>
<input type="submit" value="Save" />
</form:form>
The JSP page to display item attributes along with the image.
CategoryId:
<tr>
<td><form:label path="categoryName">CategoryName:</form:label></td>
<td><form:input path="categoryName"/></td>
</tr>
</table>
<input type="submit" value="Save" />
<table width: 100%; text-align:center">
<tr>
<th>ItemId</th>
<th>ItemName</th>
<th>ItemPrice</th>
<th>ItemFeatures</th>
<th>Edit</th>
<th>Delete</th>
<th>ItemImage</th>
</tr>
<tbody>
<c:forEach items="${categoryAttribute.item}" var="item">
<tr>
<c:url var="editCUrl" value="/item/edit?bid=${categoryAttribute.categoryId}&cid=${item.itemId}" />
<c:url var="deleteCUrl" value="/item/delete?id=${item.itemId}" />
<td><c:out value="${item.itemId}" /></td>
<td><c:out value="${item.itemName}"/></td>
<td><c:out value="${item.itemPrice}"/></td>
<td><c:out value="${item.itemContent}"/></td>
<td>EditItem</td>
<td>DeleteItem</td>
<td><c:out value="${item.itemImage}"/></td>
</tr>
</c:forEach>
How can I properly display the image which is stored in the database? I guess I'm doing it wrong by displaying image like this in JSP.
But how can I display the image here in JSP?
I'm finally able to display the image on my jsp.
what i did.
I separately created a controller like this.
#Controller
#RequestMapping("/myImage")
public class ImageController {
#Resource(name="categoryService")
private CategoryService categoryService;
#Resource(name="itemService")
private ItemService itemService;
#RequestMapping(value = "/imageDisplay", method = RequestMethod.GET)
public void showImage(#RequestParam("id") Integer itemId, HttpServletResponse response,HttpServletRequest request)
throws ServletException, IOException{
Item item = itemService.get(itemId);
response.setContentType("image/jpeg, image/jpg, image/png, image/gif");
response.getOutputStream().write(item.getItemImage());
response.getOutputStream().close();
and in the jsp i did this
<img src="/Project1/myImage/imageDisplay?id=${item.itemId}"/>
And the image was successfully displayed.
I wrote below code in my controller and it's working fine for me.
In my project, User contain Profile Object which has photo #Lob.
Modify this code as per your attributes.
byte[] encodeBase64 = Base64.encode(user.getProfile().getPhoto());
String base64Encoded = new String(encodeBase64, "UTF-8");
mav.addObject("userImage", base64Encoded );
In JSP file, I wrote code
<img src="data:image/jpeg;base64,${userImage}" />
For this, you require common-codec jar.
Also, you can use a custom tag for showing image.
One more thing you can do for displaying the image in jsp from database.
suppose you need to display images of all user in jsp.
for this you can create your own custome jstl tag which contain code for converting byte image to base64 image.
here in my project the image is in Profile class
i.e user.getProfile().getPhoto()
package com.spring.tags;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import javax.servlet.jsp.tagext.TagSupport;
import org.apache.commons.codec.base64.Base64;
public class UserImage extends SimpleTagSupport {
private byte[] usrImage;
public void setUsrImage(byte[] usrImage) {
this.usrImage = usrImage;
}
#Override
public void doTag() throws JspException, IOException {
System.out.println("tag lib");
try {
JspWriter out = getJspContext().getOut();
if (usrImage != null && usrImage.length > 0) {
byte[] encodeBase64 = Base64.encode(usrImage);
String base64Encoded = new String(encodeBase64, "UTF-8");
out.print("data:image/jpeg;base64,"+base64Encoded);
}
} catch (Exception e) {
throw new JspException("Error: " + e.getMessage()); }
}
}
create tld file in WebContent. i have create file in my taglib folder
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd">
<tlib-version>1.0</tlib-version>
<short-name>ui</short-name>
<uri>/taglib/userimage</uri>
<tag>
<name>image</name>
<tag-class>com.spring.tags.UserImage</tag-class>
<body-content>empty</body-content>
<info>This Tag Displayes current user profile image</info>
<attribute>
<name>usrImage</name>
<required>true</required>
<description>Provide a display format</description>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
Now you can write code in jsp for displaying image.
<img src="<ui:image usrImage='${user.profile.photo}' />
Every time no need to convert image in controller just pass byte image to jsp and our custome tag will convert byte image and dispay it in view page.
Note: include custome tag file in jsp file
<%# taglib uri="/taglib/userimage.tld" prefix="ui"%>
However, i was using native query to get the ArrayList<> so i could not use setter and getter method in my controller to obtain the bytes to encode to Base64, instead i created a #Transient field in my Dao class to do encode to base64 and it worked.
In my dao
#Transient
private String imgUtility;
//getter method for encoding
public String getImgUtility() throws UnsupportedEncodingException {
byte[] encodeBase64 = Base64.encodeBase64(getImage());
String base64Encoded = new String(encodeBase64, "UTF-8");
return base64Encoded;
}
and in the jsp view you can do this
<img src="data:image/jpeg;base64,${tempCust.imgUtility}"/>

Getting => java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'enumLanguage' available as request attribute

I am using Spring form to get inputs from client (if i use normal html input). If i use Spring form input i got error : java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'enumLanguage' available as request attribute
this is my JSP:
<form:form commandname="enumLanguage" action="${pageContext.request.contextPath}/enumLanguage/create.action" method="post" modelAttribute="enumLanguage" >
<fieldset class="langStep">
<legend>Language Details</legend>
<table class="langpadding">
<tr>
<td><label>Name:</label></td>
<td><form:input path="name" cssClass="textbox2"></form:input></td>
<td><label class="llangpadding">Short Name:</label></td>
<td><form:input path="shortName" cssClass="textbox2"></form:input></td>
</tr>
</table>
Save<span class="icon icon3"></span>
</form:form>
and this is my Controller:
#RequestMapping( value="/enumLanguage/create.action", method=RequestMethod.POST)
public ModelAndView create(#ModelAttribute EnumLanguage enumLanguage) throws Exception {
ModelAndView mvc = null;
try{
List<EnumLanguage> enumLanguages = new ArrayList<EnumLanguage>();
enumLanguages.add(enumLanguage);
List<EnumLanguage> enumLanguagesList = enumLanguageService.create(enumLanguages);
mvc = new ModelAndView("setup/EnumLanguageList");
} catch (Exception e) {
}
return mvc;
}
Make sure you have your #ModelAttribute set to the model when rendering the view
Make sure you made available in the view a model attribute with a key enumLanguage which is the value of the commandname of the form.
So the controller method that returns the view containing the form that you posted should look something like this.
#RequestMapping(value = "/language-details.do", method = RequestMethod.GET)
public ModelAndView initLanguageDetailsView() {
ModelMap model = new ModelMap();
EnumLanguage enumLang = new EnumLanguage();
//setters blah blah
//...
//make it available to the view
model.addAttribute("enumLanguage", enumLang);
return new ModelAndView("language-details", model);
}

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'newReward' available as request attribute

I'am new to Spring MVC, following the "Spring in Action" book, creating my own project from scratch. I get the following exception when trying to reach 'reward.jsp':
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'reward' available as request attribute
Contents of my classes:
reward.jsp
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# taglib uri="http://www.springframework.org/tags/form" prefix="sf"%>
<html>
<head>
<title>Rewards</title>
</head>
<body>
<h1>Rewards module</h1>
<h2>Add reward</h2>
<sf:form action="add" method="post" modelAttribute="reward">
Reward name:<sf:input path="name" />
Point value:<sf:input path="pointValue" />
<input type="submit" value="Add">
</sf:form>
<br />
<h2>Reward list</h2>
<table>
<c:forEach var="reward" items="${rewardList}">
<tr>
<td>${reward.name}</td>
<td>${reward.pointValue}</td>
<td>delete</td>
</tr>
</c:forEach>
</table>
It works just fine when I delete form inputs.
RewardController.java
#Controller
public class RewardController {
#Autowired
private RewardService rewardService;
#RequestMapping("/reward")
public String listRewards(Map<String, Object> model) {
model.put("rewardList", rewardService.listReward());
return "reward";
}
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String addReward(#ModelAttribute("reward") Reward reward,
BindingResult result) {
rewardService.addReward(reward);
return "redirect:/reward";
}
#RequestMapping("/delete/{rewardId}")
public String deleteContact(#PathVariable("rewardId") long rewardId) {
rewardService.removeReward(rewardId);
return "redirect:/reward";
}
}
Change your listRewards method, so that it add the form backing object to the model map model.put("reward", new Reward()).
#RequestMapping("/reward")
public String listRewards(Map<String, Object> model) {
model.put("rewardList", rewardService.listReward());
model.put("reward", new Reward())
return "reward";
}

Spring, modelmap, getting attributes from the jsp

I develop an MVC application with spring framework and some other frameworks (and I'm a beginner). I have a controller to manage jsp handling, for example when I want add new person to my 'person list' I call a instantiate a person object and I pass it to the jsp view corresponding to the add method. And I do that by this a method like this:
#RequestMapping(value = "/persons/add", method = RequestMethod.GET)
public String getAdd(Model model) {
logger.debug("Received request to show add page");
// Create new UserDomain and add to model
// This is the formBackingOBject
model.addAttribute("personAttribute", new UserDomain());
// This will resolve to /WEB-INF/jsp/addpage.jsp
return "addpage-tiles";
}
My problem is that now, I want to pass to add to the model two different Objects, for example, I want to pass the 'new UserDomain()' and also an other object which is from an other table in my database, for example a 'new UserSecurity()'.
I think I should use a 'modelMap' instead of the 'model.addAttribute...', but I can't do this, so if someone could help me.
I get my model from the jsp by a code like :
<form:form modelAttribute="personAttribute" method="POST" action="${saveUrl}">
<table>
<tr>
<td><form:label path="firstName">First Name:</form:label></td>
<td><form:input path="firstName"/></td>
</tr>
<tr>
<td><form:label path="lastName">Last Name</form:label></td>
<td><form:input path="lastName"/></td>
</tr>
<tr>
<td><form:label path="userName">User name</form:label></td>
<td><form:input path="userName"/></td>
</tr>
<tr>
<td><form:label path="email">E-mail</form:label></td>
<td><form:input path="email"/></td>
</tr>
</table>
<input type="submit" value="Save" />
thank you a lot for helping me.
Simply passing more than one object to the view is not a problem -- just use model.addAttribute multiple times, and then you can access both objects.
However, if you want to edit more than one model in <form:form> you'll need to create a class that contains both of the objects:
public class UserDomainSecurity {
private UserDomain userDomain;
private UserSecurity userSecurity;
// getters and setters for both
}
Then pass an instance of this into the view:
model.addAttribute("userDomainSecurity", new UserDomainSecurity());
And use it in the form:
<form:form commandName="userDomainSecurity" method="POST" action="${saveUrl}">
...
<form:input path="userDomain.firstName"/>
....
<form:input path="userSecurity.someSecurityProperty"/>
It's sometimes annoying to have to create all these additional classes, but it is somewhat logical. The wrapper class creates kind of namespaces in the form and thus separates the individual objects that you want to edit.
I wanted to add on this as it's really the present problem I have encountered minutes ago.
In this case, I assumed that you're UserSecurity and UserDomain are relative to each other.
Let say you have,
public class UserDomain {
public UserSecurity userSecurity
public String firstName;
public String lastName;
// getters and setters...
}
and you have your UserSecurity something like,
public class UserSecurity {
public String someSecurityProperty;
// getters and setters...
}
Since userSecurity property can be accessed publicly, then you can just do what you have did in your Controller,
#RequestMapping(value = "/persons/add", method = RequestMethod.GET)
public String getAdd(Model model) {
logger.debug("Received request to show add page");
// Create new UserDomain and add to model
// This is the formBackingOBject
model.addAttribute("userDomainSecurity", new UserDomain());
// This will resolve to /WEB-INF/jsp/addpage.jsp
return "addpage-tiles";
}
then just access it in your addpage.jsp like it's an object property like below,
<form:form commandName="userDomainSecurity" method="POST" action="${saveUrl}">
...
<form:input path="firstName />
<form:input path="lastname />
....
<form:input path="userSecurity.someSecurityProperty"/>
as you notice, I access the someSecurityProperty by the property declared in UserDomain class.

Resources