I am trying to build a sample spring portlet, with LR 6.2 GA1.
Below is the source for the same https://docs.google.com/file/d/0By1kU5o_jlrublhUNXIxQ24wODQ/edit
On the ajax the parameters are not being fetched.The parameters always remain blank.
#Controller(value = "ProjectSearch")
#RequestMapping("VIEW")
public class ProjectSearch {
Log log_ = LogFactoryUtil.getLog(ProjectSearch.class);
#RenderMapping
public String handleRenderRequest(final RenderRequest request,
final RenderResponse response, Model model) {
System.out.println("ProjectSearch.handleRenderRequest()");
return "search_form";
}
#ResourceMapping("getProjectNameSuggestion")
public void getNameSuggestion(ResourceRequest request,
ResourceResponse response) throws IOException {
Map<String, String[]> map = request.getParameterMap();
for (Map.Entry<String, String[]> element : map.entrySet()) {
log_.info(element.getKey());
}
String entityName = ParamUtil.getString(request, "query");
log_.info("Entity name==>" + entityName);
}
}
#RenderMapping
public String handleRenderRequest(final RenderRequest request,
final RenderResponse response, Model model) {
System.out.println("ProjectSearch.handleRenderRequest()");
return "search_form";
}
#ResourceMapping("getProjectNameSuggestion")
public void getNameSuggestion(ResourceRequest request,
ResourceResponse response) throws IOException {
Map<String, String[]> map = request.getParameterMap();
for (Map.Entry<String, String[]> element : map.entrySet()) {
log_.info(element.getKey());
}
String entityName = ParamUtil.getString(request, "query");
log_.info("Entity name==>" + entityName);
}
}
Output-->05:23:24,148 INFO [http-bio-8080-exec-119][ProjectSearch:41] Entity name==>
Could any body tell me what is that I am doing wrong??
Solution:
Configure Requires Name Spaced Parameters to false in liferay-portlet.xml
Now need to do require Name spaced parameters to false then only form data is mapped in Action Request and Render Request. And also form data will be binding to model object or command object.
The following is configuration we need to do in liferay-portlet.xml file
<requires-namespaced-parameters>false</requires-namespaced-parameters>
Required Name Space Parameter Behavior in Liferay
Liferay 6.2 we have to append portlet Name space for every name of input element i.e. form input elements or request parameters names otherwise portlet action class ignore the parameters which does not have portlet name space to names.
Scenario
Jsp page
In the following form we are not appending portlet name space to form input element names.
<portlet:actionURL var="addEmployeeActionURL" name="addEmployee">
<portlet:param name="<%=ActionRequest.ACTION_NAME%>" value="addEmployee"/>
</portlet:actionURL>
<form action="<%=addEmployeeActionURL%>" name="emplyeeForm" method="POST">
Employee Name<br/>
<input type="text" name="employeeName" id="employeeName"/><br/>
Employee Address<br/>
<input type="text" name="employeeAddress" id="employeeName"/><br/>
<input type="submit" name="addEmployee" id="addEmployee" value="Add Employee"/>
</form>
Portlet Class Action Method
public class EmplyeePortletAction extends MVCPortlet {
public void addEmployee(ActionRequest actionRequest,
ActionResponse actionResponse) throws IOException, PortletException {
String employeeName=ParamUtil.getString(actionRequest,"employeeName");
String employeeAddress=ParamUtil.getString(actionRequest,"employeeAddress");
}
}
In above case employeeName and employeeAddress form input data not accessible in portlet class action .The form elements name are not appended with portlet name space such scenarios portlet class ignore those request parameters or form inputs
Solution:1
Need to append tag to every input element name.
Jsp page
<portlet:actionURL var="addEmployeeActionURL" name="addEmployee">
<portlet:param name="<%=ActionRequest.ACTION_NAME%>" value="addEmployee"/>
<portlet:param name="requestParam" value=" requestParamValue"/>
</portlet:actionURL>
<form action="<%=addEmployeeActionURL%>" name="emplyeeForm" method="POST">
Employee Name<br/>
<input type="text" name="<portlet:namespace/>employeeName" id="<portlet:namespace/>employeeName"/><br/>
Employee Address<br/>
<input type="text" name="<portlet:namespace/>employeeAddress" id="<portlet:namespace/>employeeName"/><br/>
<input type="submit" name="addEmployee" id="addEmployee" value="Add Employee"/>
</form>
Portlet Class Action Method
public class EmplyeePortletAction extends MVCPortlet {
public void addEmployee(ActionRequest actionRequest,
ActionResponse actionResponse) throws IOException, PortletException {
String employeeName=ParamUtil.getString(actionRequest,"employeeName");
String employeeAddress=ParamUtil.getString(actionRequest,"employeeAddress");
String requestParamValue=ParamUtil.getString(actionRequest,"requestParam");
}
}
Solution:2
We can make it false to following tag value in liferay-portlet.xml file
<requires-namespaced-parameters>false</requires-namespaced-parameters>
Solution:3
We can use alloy tag library form tags. When we use AUI tags it will append portlet name space to each input element name.
Jsp page
<%# taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
<aui:input type="text" name="employeeAddress" id="employeeName"/><br/>
<aui:input type="submit" name="addEmployee" id="addEmployee" value="Add Employee"/
<input type="text" name="<portlet:namespace/>employeeAddress" id="<portlet:namespace/>employeeName"/>
Is same As
<aui:input type="text" name="employeeAddress" id="employeeName"/>
http://www.liferaysavvy.com/2013/12/liferay-spring-portlet.html
http://www.liferaysavvy.com/2014/04/liferay-mvc-portlet-development.html
Related
So my bindingresult throws an error but I'm not able to see it for some reason and I'm not able to figure out what the problem is. I'm guessing the problem lies with the variable targetDate where there is a problem the type. I've pasted my controller and JSP code below. Any help is appreciated!
#Controller
public class ToDoController {
#Autowired
private ToDoService service;
// All date parameters displayed as mm/DD/yyyy
#InitBinder
protected void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("mm/DD/yyyy");
binder.registerCustomEditor(Date.class, new CustomDateEditor(
dateFormat, false));
}
#RequestMapping(value = "/list-todo", method= RequestMethod.GET)
// HttpSession allows access to the session
public String showToDo(ModelMap model, HttpSession httpSession) {
String user = (String) httpSession.getAttribute("name");
model.addAttribute("todos", service.retrieveTodos(user));
return "list-todos";
}
// redirect to update form
#RequestMapping(value = "/update-todo", method= RequestMethod.GET)
public String getUpdateForm(ModelMap model, #RequestParam int id) {
System.out.println("ID " + id);
// To work with command bean
model.addAttribute("id", id);
model.addAttribute("todo", service.retrieveTodo(id-1));
return "updateToDo";
}
// What does Valid do?
#RequestMapping(value = "/update-todo", method= RequestMethod.POST)
public String submitUpdate(ModelMap model, #Valid ToDo todo, BindingResult result) {
if (result.hasErrors()) {
System.out.println("ERROR" + result.getAllErrors());
// Redirect and pass on the id value
return "redirect:/update-todo?id=" + todo.getId();
}
System.out.println("Update todo" + todo);
service.updateToDo(todo);
model.clear();
return "redirect:/list-todo";
}
// Will be executed first
#RequestMapping(value = "/add-todo", method= RequestMethod.GET)
public String showAddForm(ModelMap model) {
model.addAttribute("todo", new ToDo());
return "addToDo";
}
/*
* Will be executed after form is submitted
* #Valid ToDo - command bean from addToDo.jsp.
* #Valid to validate the information
* #BindingResult showcases the result of the validation
*/
#RequestMapping(value = "/add-todo", method= RequestMethod.POST)
public String submitAddForm(ModelMap model , #Valid ToDo todo, HttpSession httpSession, BindingResult result) {
System.out.println("running" + result);
// If there is validation error , return to addToDos page for user to fix the error
if (result.hasErrors()) {
return "redirect:/showAddForm?id=?" + todo.getId();
}
String user = (String) httpSession.getAttribute("name");
service.addTodo(user, todo.getDescription(), todo.getTargetDate(), false);
// Clears the url e.g. name?=jyj123
model.clear();
// return to the url which executes the showToDO
return "redirect:/list-todo";
}
// delete to do entry
#RequestMapping(value = "/delete-todo", method= RequestMethod.GET)
public String deleteToDo(ModelMap model, #RequestParam int id) {
service.deleteTodo(id);
model.clear();
return "redirect:/list-todo"; }
}
My JSP
<%# taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%# include file = "common/header.jspf" %>
<%# include file = "common/nav.jspf" %>
<div class="container">
<H1>Update your task!</H1>
<form:form method="POST" commandName="todo">
<!-- Carry on the id value -->
<form:hidden path = "id"/>
<form:hidden path = "user"/>
<fieldset class="form-group">
<form:label path="description">Description:</form:label>
<form:input path="description" type="text" class="form-control"
required="required" />
<form:errors path="description" cssClass="text-warning" />
</fieldset>
<fieldset class="form-group">
<form:label path="targetDate">Target Date</form:label>
<form:input path="targetDate" type="text" class="form-control"
required="required" />
<form:errors path="targetDate" cssClass="text-warning" />
</fieldset>
<fieldset class="form-group">
<form:radiobutton path="completion" value="true" />
<form:radiobutton path="completion" value="false" />
</fieldset>
<button type="submit" class="btn btn-success" >Submit Update</button>
</form:form>
<spring:hasBindErrors htmlEscape="true" name="todo">
<c:if test="${errors.errorCount gt 0}">
<h4>The error list :</h4>
<font color="red">
<c:forEach items="${errors.allErrors}" var="error">
<spring:message code="${error.code}"
arguments="${error.arguments}"
text="${error.defaultMessage}"/><br/>
</c:forEach>
</font>
</c:if>
</spring:hasBindErrors>
</div>
<%# include file = "common/footer.jspf" %>
EDIT: bindingresult throws this
ERROR[Field error in object 'todo' on field 'targetDate': rejected value [Tue Jan 05 00:00:00 SGT 2021]; codes [typeMismatch.todo.targetDate,typeMismatch.targetDate,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [todo.targetDate,targetDate]; arguments []; default message [targetDate]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'targetDate'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.util.Date] for value 'Tue Jan 05 00:00:00 SGT 2021'; nested exception is java.lang.IllegalArgumentException]]
In your jsp you submit the form to "todo", not "update-todo". It would be nice to see your ToDo bean. Also: result.getAllErrors().
I'm trying to upload multiple images in Springboot.
Here is my form HTML:
<form th:action="#{${#httpServletRequest.requestURI}}" th:object="${formInput}" method="post" enctype="multipart/form-data" onsubmit="return validate();">
To take in multiple files:
<input type="file" onclick="radioButton()" onchange=" enableSubmit();" id = "fileInput" name="uploadingFiles[]" accept="image/*" multiple/>
Here is my controller:
#RequestMapping(value = "/userProfiles/{userId}/setup/Tool.html", method = RequestMethod.POST)
public void makeIAmVideo(#PathVariable Long userId, HttpServletResponse response, #RequestParam(value = "track_value") int trackNumber, #RequestParam("uploadingFiles") MultipartFile[] uploadingFiles) throws IOException {
UserProfile userProfile = userProfileRepository.findById(userId);
ArrayList<String> photos = new ArrayList<>();
String audioPath= audioPath1;
System.out.println(trackNumber);
for(MultipartFile file : uploadingFiles){
photos.add(file.getName());
}
}
But when I debug it, the photos are not uploaded in the photos array list, it's size stays 0.
Am I doing something wrong?
add these line in your form which contain this input field.
enctype="multipart/form-data"
How can I display an error message in the very same JSP when a user submits a wrong input? I do not intend to throw an exception and show an error page.
Easiest would be to have placeholders for the validation error messages in your JSP.
The JSP /WEB-INF/foo.jsp:
<form action="${pageContext.request.contextPath}/foo" method="post">
<label for="foo">Foo</label>
<input id="foo" name="foo" value="${fn:escapeXml(param.foo)}">
<span class="error">${messages.foo}</span>
<br />
<label for="bar">Bar</label>
<input id="bar" name="bar" value="${fn:escapeXml(param.bar)}">
<span class="error">${messages.bar}</span>
<br />
...
<input type="submit">
<span class="success">${messages.success}</span>
</form>
In the servlet where you submit the form to, you can use a Map<String, String> to get hold of the messages which are to be displayed in JSP.
The Servlet #WebServlet("foo"):
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/foo.jsp").forward(request, response);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Map<String, String> messages = new HashMap<String, String>();
request.setAttribute("messages", messages); // Now it's available by ${messages}
String foo = request.getParameter("foo");
if (foo == null || foo.trim().isEmpty()) {
messages.put("foo", "Please enter foo");
} else if (!foo.matches("\\p{Alnum}+")) {
messages.put("foo", "Please enter alphanumeric characters only");
}
String bar = request.getParameter("bar");
if (bar == null || bar.trim().isEmpty()) {
messages.put("bar", "Please enter bar");
} else if (!bar.matches("\\d+")) {
messages.put("bar", "Please enter digits only");
}
// ...
if (messages.isEmpty()) {
messages.put("success", "Form successfully submitted!");
}
request.getRequestDispatcher("/WEB-INF/foo.jsp").forward(request, response);
}
In case you create more JSP pages and servlets doing less or more the same, and start to notice yourself that this is after all a lot of repeated boilerplate code, then consider using a MVC framework instead.
See also:
Our Servlets wiki page
What is the best practice for validating parameters in JSP?
I see tag "form-validation", so maybe you should just use JavaScript and client form validation? If you need validation with JSP, handle form data, and redisplay the form with an error message or accept form data, if it's correct.
I'm not quite sure what you mean by "display error message". If you have a standard error handling, then you can always check for options:
<%
if(wrong option selected)
throw new Exception("Invalid option selected");
%>
Of course, this is just the notion; preferably, you'd have your own exception class. But then again, I'm not quite sure what you're after.
I am new to spring and I am trying to redirect to the same page if the form has errors. I am successful redirecting that but the problem is the form has a dynamic drop down and the values are not rendered when I return a model object. or when I do ModelAndView(new RedirectView("lookup")) I am able to render the dropdown values but I am unable to display the error messages.
code: jsp: lookup.jsp
<form:form name="lookupForm" method="POST" action="search.html" enctype="multipart/form-data" >
<div style= "color:red">
<form:errors path="empId" /></br>
<form:errors path="companyName" />
</div>
<form:label path="companyName">Company</form:label>
<select name= "companyList" path="companyName">
<option value="Select">Select</option>
<c:forEach var="element" items="${listCompany}">
<option value="${element.companyName}">${element.companyName}</option>
</c:forEach>
</select>
<form:label path="empId">Employee ID</form:label>
<form:textarea name="empId" path="empId" rows="5" cols="30"/>
<input type="submit" name="search" value="Search"/>
Controller:
#RequestMapping(value = "/lookup", method = RequestMethod.GET)
public ModelAndView lookupFormView(ModelAndView model,BindingResult result) {
List<Employee> listCompany = employeeDAO.getCompany();
Employee newContact = new Employee();
model.addObject("listCompany", listCompany);
model.addObject("command", newContact);
model.setViewName("lookup");
return model;
}
#RequestMapping(value = "/search", params = "search", method = RequestMethod.POST)
public ModelAndView lookupEmployee(HttpServletRequest request,HttpServletResponse response, #ModelAttribute("command") Employee emp,BindingResult result) throws Exception{
empValidator.validate(emp, result);
String lookupEmpId = null;
if (result.hasErrors()) {
return new ModelAndView(new RedirectView("lookup"));
//return new ModelAndView("lookup");
}
else{
-----
if i use this return new ModelAndView(new RedirectView("lookup")); its redirecting to lookup.jsp ,rendering the drop down valus but the error messages are not getting displayed.
if i use this return new ModelAndView("lookup"); its redirecting to lookup.jsp ,errors are displayed but the dynamic dropdown values are not rendered.
Please help me in finding which part of my code is wrong or Is their a way to display error messages and render dynamic dropdown values
Just return the view name and set the error message in the Model itself. Simply check the error message in the JSP if found then show it.
sample code:
#RequestMapping(value = "/search", params = "search", method = RequestMethod.POST)
public String lookupEmployee(HttpServletRequest request,HttpServletResponse response,
#ModelAttribute("command") Employee emp,BindingResult result) throws Exception{
empValidator.validate(emp, result);
String lookupEmpId = null;
if (result.hasErrors()) {
emp.setErrorMessage("Your error message.");
return "lookup";
}else{
...
return "successPage";
}
}
I have a form which a user is to use to upload a file to a local drive and also persist some data to the database. But this error message has come up which I would like to know how to deal with it.
HTTP Status 400 - The request sent by the client was syntactically incorrect.
The controller
#RequestMapping(value = "/main/user/setter/addpage", method =
RequestMethod.POST, params = "save")
public String saveProcess(#ModelAttribute("module") Module module,
#RequestParam("userId") Integer userId,
#RequestParam("name") String name,
#RequestParam("file") MultipartFile file,
BindingResult result, HttpSession session) {
if (result.hasErrors()) {
return "redirect:/main/user/setter/settingpage";
}
else
if(module != null){
try {
MultipartFile filea = module.getFileData();
InputStream inputStream = null;
OutputStream outputStream = null;
if (filea.getSize() > 0) {
inputStream = filea.getInputStream();
outputStream = new FileOutputStream("C:\\Test\\"
+ filea.getOriginalFilename());
System.out.println("Uploaded File Name");
System.out.println(filea.getOriginalFilename());
int readBytes = 0;
byte[] buffer = new byte[8192];
while ((readBytes = inputStream.read(buffer, 0, 8192)) !=
-1) {
outputStream.write(buffer, 0, readBytes);
}
outputStream.close();
inputStream.close();
session.setAttribute("success", "File Uploaded");
session.setAttribute("uploadFile", "C:\\Test\\"
+ filea.getOriginalFilename());
}
} catch (Exception e) {
e.printStackTrace();
}
}
// Delegate to service
moduleService.add(userId, module);
return "redirect:/main/user/setter/settingpage";
}
The form itself
<c:url var="processUrl" value="/main/user/setter/addpage?userId=2" />
<form:form modelAttribute="module" method="POST" action="${processUrl}" name="module"
enctype="multipart/form-data">
<form:label path="fileName">Document Title:</form:label>
<form:input path="fileName" name="name"/><br/>
<form:label path="documentPath">Coursework Sample:</form:label>
<form:input path="documentPath" type="file" name="file" id="file" size="43.9"/><br/>
<form:label path="liveDate">Live Date:</form:label>
<form:input path="liveDate"/><br/>
<input type="submit" name="save" value="Save" id="save"/>
<input type="submit" name="send" value="Send" id="send"/>
</form:form>
I'm trying to save the form first the I will use a separate method to send it.
Your method is declared as such:
public String saveProcess(#ModelAttribute("module") Module module,
#RequestParam("userId") Integer userId,
#RequestParam("name") String name,
#RequestParam("file") MultipartFile file,
BindingResult result, HttpSession session) ...
Assuming that you are trying to apply the BindingResult to the Module instance, you need to change the method definition so that the BindingResult comes right after the Module instance.
public String saveProcess(#ModelAttribute("module") Module module,
BindingResult result,
#RequestParam("userId") Integer userId,
#RequestParam("name") String name,
#RequestParam("file") MultipartFile file,
HttpSession session) ...
See the reference for more details
The Errors or BindingResult parameters have to follow the model object
that is being bound immediately as the method signature might have
more that one model object and Spring will create a separate
BindingResult instance for each of them [...]
See here.
The error HTTP Status 400 - The request sent by the client was syntactically incorrect. can come from a missing multipartResolver in the context (servlet-context.xml)
`<beans:bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />`
For more info, see the replies from SpringMVC-FileUpload - The request sent by the client was syntactically incorrect