Using beans in servlets - servlets

I has a jsp page (index.jsp) with a form with two text fileds username and password like.
<form action="MyClass">
<input type="text" name="username" id="username" />
<input type="password" name="password" id="password" />
<input type="submit" />
</form>
On form submition i am invocking a servlet. I know that we can get the entered username and password values by using request methods,
request.getParameter("username");
request.getParameter("password");
But i don't want to use them , instead i want to store these values in a bean called BeanClass and i want to retrieve values from the bean in the sevlet. How can i get it??

You have to use <jsp:useBean/> action to instantiate the BeanClass with request or session scope in JSP.
Sample - EmpServlet.java
package com.me;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class EmpServlet extends HttpServlet {
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter pw=response.getWriter();
Emp emp=(Emp)request.getAttribute("emp");
pw.print(emp);
}
}
Emp.java : Emp bean
package com.me;
public class Emp {
private int age;
private String name;
public Emp() {
name="";
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean valid()
{
return age!=0 && name.length()!=0;
}
#Override
public String toString() {
return "Emp{" + "age=" + age + ", name=" + name + '}';
}
}
emp.jsp (view)
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<jsp:useBean id="emp" class="com.me.Emp" scope="request">
<jsp:setProperty name="emp" property="*"/>
</jsp:useBean>
<c:if test="${emp.valid()}">
<jsp:forward page="emp"/>
</c:if>
<form method="post" action="emp.jsp">
<br/><input type="text" name="age"/>
<br/><input type="text" name="name"/>
<br/><input type="submit"/>
</form>
web.xml
<servlet>
<servlet-name>EmpServlet</servlet-name>
<servlet-class>com.me.EmpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>EmpServlet</servlet-name>
<url-pattern>/emp</url-pattern>
</servlet-mapping>

To the point, you're looking for a MVC framework like JSF or Spring MVC. With JSF it'll look something like this:
<h:form>
<h:inputText value="#{bean.username}" required="true" />
<h:inputSecret value="#{bean.password}" required="true" />
<h:commandButton value="submit" action="#{bean.submit}" />
<h:messages />
</h:form>
with
#ManagedBean
#RequestScoped
public class Bean {
private String username;
private String password;
public void submit() {
// Do here your job.
}
// Add/generate getters and setters.
}
That's all. No need for a servlet.
If you really want to do it the low level servlet way, you'd need to populate the bean yourself. This can be convenienced with Apache Commons BeanUtils to save boilerplate code.
Bean bean = new Bean();
BeanUtils.populate(bean, request.getParameterMap());
request.setAttribute("bean", bean);
// ...
The <jsp:useBean> does not allow for the MVC approach, it's more a MV. You have to mingle the conversion/validation into model and control the request/response inside the view, tasks which a controller should do. MVC frameworks offer you a controller which takes all this nasty boilerplate tasks from your hands.

Related

Getting null values in Spring MVC controller when submitting data from the jsp

I have a jsp form with an input box, a domain object with get/set methods, and a controller. When I submit the form I get null values in the controller. The "set" method is never being called in the domain object when i submit the form but the object itself is being called.
Order.jsp
<portlet:defineObjects />
<portlet:actionURL portletMode="view" var="createNewOrderURL">
<portlet:param name="action" value="createNewOrder" />
</portlet:actionURL>
<div>
<form:form name="form" method="post" commandName="refOrder" action="${createNewOrderURL}" id="createOrder">
TestName : ${refOrder.name}<br/> <!-- here I get the correct value to display -->
<form:input path="referenceNum" />
<input type="submit" value="Submit" />
</form:form>
</div>
Order.java
public class Order {
private String name = "Name1";
private String referenceNum;
public Order(){
System.out.println("Inside Order.java");
System.out.println(getReferenceNum());
}
public Order(String name, String referenceNum) {
this.name = name;
this.referenceNum = referenceNum;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getReferenceNum() {
return referenceNum;
}
public void setReferenceNum(String referenceNum) {
this.referenceNum = referenceNum;
}
SalesOrderController.java
#RenderMapping
public String defaultRender(RenderRequest request, RenderResponse response, Model model) throws SQLException, NamingException{
model.addAttribute("refOrder",new Order());
return "SalesOrderEntry";
}
#ActionMapping(params={"action=createNewOrder"})
public void addNewOrder(ActionRequest request, ActionResponse response, #ModelAttribute("refOrder") Order order)throws NamingException, SQLException{
System.out.println("Inside addNewOrder method");
System.out.println("New Order is --> "+order.toString());
System.out.println("RefNum - "+order.getReferenceNum());
System.out.println("request.getParameter is "+request.getParameter("referenceNum"));
}
I get null for all the print statements in the controller. Have been trying to fix this for two days now and I can't find what's wrong. Would really appreciate if someone can help me get this to work.
Do you have the following in your src/main/webapp/WEB-INF/liferay-portlet.xml descriptor?
<requires-namespaced-parameters>false</requires-namespaced-parameters>
Also, you might want to take a look at the PortletMVC4Spring project, which is the successor to Spring Portlet MVC. The GitHub project contains archetypes that work in Apache Pluto and Liferay Portal. The requires-namespaced-parameters config option is conveniently set in the archetypes.

Spring4 Form Validation

I have a situation similar to the followa:
public class Shop {
#NotNull
String name;
#NotNull
String desc;
}
a button to show a form where I have to insert my user:
<form:form method="post" action="saveShop.html" modelAttribute="Shop">
<form:label path="name">Name:</form:label>
<form:input path="name" value="${shop.name}" />
<form:label path="desc">desc:</form:label>
<form:input path="desc" value="${shop.desc}" />
<input type="submit" value="Submit"/>
</form:form>
Controller:
#RequestMapping("/addShop")
public ModelAndView LoadFormPage(#ModelAttribute("Shop")Shop shop) {
ModelAndView model = new ModelAndView();
model.setViewName("/shop/addShop");
return model;
}
#RequestMapping(value = "/saveShop", method = RequestMethod.POST)
public ModelAndView saveShop(#Valid #ModelAttribute("Shop") Shop shop, BindingResult result) {
if (result.hasErrors()) { *do some*
} else { *do someelse* }
}
Even if I leave all fields blank (I have tried even with different data type) and submit the form the controller never recognize errors.
Can you help me?
Make sure to add below configs.
<bean id="myBeansValidator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
and
<mvc:annotation-driven validator="myBeansValidator">
and
<!-- Hibernate Validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>
Adapted from Spring MVC form validation not working

Spring StringTrimmerEditor trim all fields except password field

In registered a StringTrimmerEditor in a Spring controller.
Of course when I now enter a password starting or ending with whitespace it is trimmed as well. But an user doesn't recognize this trimming.
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, new StringTrimmerEditor(false));
}
So is it possible to 'exclude' the password field from trimming.
Should I register a StringTrimmerEditor for each field or just declare password as char[]?
Although this is an old question, if you still get tripped on this then here is how I solved this.
Say we have this form src/main/webapp/view/greet-form.html (I am using Thymeleaf)
<form action="/something" th:attr="action=#{/greet}" method="post" th:object="${student}">
<p><strong>Enter your first name</strong></p>
<p><input type="text" th:field="*{firstName}" th:value="*{firstName}"> <span class="error">*</span><br />
<span class="error_message" th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}"></span></p>
<p><strong>Enter your secret code</strong></p>
<p><input type="text" th:field="*{secretCode}" th:value="*{secretCode}"> <span class="error">*</span><br />
<span class="error_message" th:if="${#fields.hasErrors('secretCode')}" th:errors="*{secretCode}"></span></p>
<p><input type="submit" value="Submit"></p>
</form>
When the form is submitted, we want Spring to trim the value of firstName but leave secretCode as it is.
This is our form backing class, defined in src/main/java/Student.java. The trick is not to use String type for secretCode but some other custom type. This way, StringTrimmerEditor will not be used for the secretCode and the data will not be trimmed.
public class Student {
private String firstName;
private SecretString secretCode;
public Student() {
//
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public SecretString getSecretCode() {
return secretCode;
}
public void setSecretCode(SecretString secretCode) {
this.secretCode = secretCode;
}
}
Here is the definition of SecretString in src/main/java/SecretString.java
public class SecretString {
private String secret;
public SecretString() {
secret = "";
}
public SecretString(String secret) {
//mandatory null check
secret = (secret == null)? "" : secret;
this.secret = secret;
}
#Override
public String toString() {
return secret;
}
}
But now Spring will complain about not being able to convert String to SecretString. This can be solved with a custom property editor or a custom converter (if you are using Spring 3+). I used a custom converter like this.
First define the code in src/main/java/SecretStringConverter.java
import org.springframework.core.convert.converter.Converter;
public class SecretStringConverter implements Converter<String, SecretString> {
#Override
public SecretString convert(String source) {
return new SecretString(source);
}
}
Then register our converter class with a conversion-service factory bean (I am using src/main/webapp/WEB-INF/spring-mvc-demo-servlet.xml)
<context:component-scan base-package="your package" />
<mvc:annotation-driven conversion-service="app_conversion_service"/>
<bean id="app_conversion_service" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="SecretStringConverter"></bean>
</list>
</property>
</bean>
Set password as disallowed field
binder.setDisallowedFields("password");

Spring 3.1 Form binding with List<Date>

I have a form object
public class TestForm {
private long id;
private List<Date> dates;
// getters and setters for the above
}
And my controller has the following..
#RequestMapping(value = "/assignDummy", method = RequestMethod.POST)
public #ResponseBody
String assignDates(TestForm frm) {
System.out.println("frm:"+frm.getId()+", date:"+frm.getDates());
return "Everything is fine";
}
My form..
<form name="abc" method="post" action="assignDummy.htm">
<input type="text" name="id" value="1000">
<input type="text" name="dates[0]" value="4500000">
<input type="submit">
</form>
I get the following error..
Failed to convert property value of type 'java.lang.String' to
required type 'java.util.Date' for property 'dates[0]'; nested
exception is
org.springframework.core.convert.ConversionFailedException: Failed to
convert from type java.lang.String to type java.util.Date for value
'4500000'; nested exception is java.lang.IllegalArgumentException"
Any help is appreciated.
Thanks in advance
You are trying to put a String into Date without converting it, so it crashes.
You have to use a custom property editor in order to convert the input String into a Date.
Try to add in your controller
#InitBinder
public void initBinder(WebDataBinder binder) {
CustomDateEditor editor = new CustomDateEditor(new SimpleDateFormat("MM/dd/yyyy"), true);
binder.registerCustomEditor(Date.class, editor);
}

Spring3 MVC - how to impliment CRUD correctly on the same controller?

I am trying to create simple CRUD controller and view using Spring mvc.
I am able to:
Get the document list
Upload document
Deleted Document
If I would like to send the request using FORM,
How do i implement Download Document?
Should I use for every document?
Another thing - am i using the MVC framework correctly?
<html>
<body>
<!-- the list: -->
<c:forEach items="${documentList}" var="documentRow">
<Generate table here>
<!-- upload part -->
<form:form modelAttribute="uploadDocument" method="post" enctype="multipart/form-data">
<form:input path="fileData" type="file"/>
<input type="hidden" id="actUploadocument" name="action" value="uploadDocument" />
</form:form>
<!-- delete part -->
<form:form method="post" enctype="multipart/form-data">
<input type="hidden" id="documentId" value="" />
<input type="hidden" id="actUploadocument" name="action" value="deleteDocument" />
</form:form>
</body>
</html>
The CRUD controller?
#Controller
#RequestMapping("/documents")
public class DocumentsController
{
#Autowired
private MainService mainService;
#RequestMapping(method = RequestMethod.GET)
public String listDocuments(Model model) {
List<Document> docs = mainService.getAllDocuments();
model.addAttribute("documentList",docs);
model.addAttribute(new UploadDocument());
return "admin/documents";
}
#RequestMapping(method = RequestMethod.POST , params="action=uploadDocument")
public String uploadDocument(UploadDocument uploadDocument){
savedocument(uploadDocument);
return "redirect:/admin/documents.do";
}
#RequestMapping(method = RequestMethod.POST , params="action=removeDocument")
public String removeDocument(#RequestParam(value="documentId", required=true) String documentId){
savedocument(documentId);
return "redirect:/admin/documents.do";
}
#RequestMapping(method = RequestMethod.POST , params="action=downloadDocument")
public String downloadDocument(#RequestParam(value="documentId", required=true) String documentId,
HttpServletRequest request,HttpServletResponse response ) {
writeDocToResponse(documentId,response);
return null;
}
Basically all you need to open file download dialog is a set response properties to identify HTTPresponce as attachment.
For instance:
response.reset();
response.setContentType(getYourFileContentType());
response.setHeader("Content-Disposition","attachment; filename=\""+getYourFileName()+"\"");
Then you may call your service method to stream file.

Resources