Spring 3 MVC - Model not displaying in JSP Page - java

On the surface, this question will sound a lot like questions that may have been asked previously on SOF but I tried those answers long ago and no luck.
(For example, this question spring 3 not rendering model in jsp)
So I had a Spring 2.0 Controller that extended CancellableFormController, and it contained the following to bind the Command Object to the Form on JSP page render:
public class MyFormController extends CancellableFormController {
....
protected Object formBackingObject(HttpServletRequest request) throws ServletException {
MyCommand myCommand = new MyCommand();
... // add some list info to command object etc in preparation for page render
return myCommand;
}
....
}
The JSP Page looked something like the following:
<form:form method="post" commandName="myCommand">
<c:forEach items="${myCommand.myList}" var="myItem" varStatus="index">
</form:form>
To be clear, between the form tag definitions, a list of items was displayed on the JSP page. This is before any form submission has occurred (ie. at page render time). And what a beautifully simple world we lived in. Everything worked first time and there was peace on earth... sorry, enough sarcasm! ;)
OK, so I happily tried to upgrade this old code to Spring 3 and annotations. My current problem is ONLY getting the Command object to render on page load. When I enter data into form fields and submit the form etc, the data gets bound correctly. What I am trying to do is pre-populate the Command object, and then render that content into the JSP page before the form is populated and submitted.
I initially tried this:
#Controller
#RequestMapping(value = "/myContextPath")
public class MyFormController {
...
#RequestMapping(method = RequestMethod.GET)
public ModelAndView initForm(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mv = new ModelAndView("myTilesViewName");
MyCommand myCommand = new MyCommand();
...
mv.addObject("myCommand", myCommand);
return mv;
}
...
}
Then I tried each of the following methods (the Controller class construct being the same as the above):
#RequestMapping(method = RequestMethod.GET)
#ModelAttribute("myCommand")
public String initForm(HttpServletRequest request, HttpServletResponse response) throws Exception {
MyCommand myCommand = new MyCommand();
....
return "myTilesViewName";
}
#RequestMapping(method = RequestMethod.GET)
public String initForm(ModelMap model, HttpServletRequest request, HttpServletResponse response) throws Exception {
MyCommand myCommand = new MyCommand();
...
model.addAttribute("myCommand", cmd);
return "myTilesViewName";
}
I don't wish to add any confusion. I "imagine" that the answer to this problem is likely the same if I were just returning the view name of a JSP page... However, I am using Apache Tiles to handle the page selection. My definition looks something like:
<definition name="myTilesViewName" extends=".myTemplate">
<put-attribute name="title" value="MyTitle" type="string" />
<put-attribute name="body" value="/WEB-INF/jsp/myPage.jsp" />
</definition>
Please remember everything worked perfectly before with the Spring 2 CancellableFormController code. I have not changed the Tiles config or JSP pages at all so don't believe they are the source of this problem.
Thank you so much to anyone who can offer any assistance. It is certainly appreciated!
UPDATE:
This issue finally related to a Client side (JSP page) related problem. My assumption that "nothing had changed other than in the Controller" was incorrect. Sincere apologies to those who took the time to read this post and consider solutions. For anyone else reading with the same symptoms, please double check your View pages (JSP) and ensure they are syntactically correct for rendering. In my case, I had moved a JSP (with around 2000 lines of code) into a subfolder and broken a relative link to a nested jsp import declaration.

Related

Display Arraylist on jsp page

I am trying to display the following ArrayList in the .jsp page shown but I can't seem to see any values once I run my portlet, where is the problem?
code.java
public class TestPortlet extends MVCPortlet {
public void displayProcess(ActionRequest request, ActionResponse response) {
ArrayList<String> process = new ArrayList<>();
process.add("a");
process.add("b");
process.add("c");
process.add("d");
process.add("e");
request.setAttribute("processName", process);
}
}
The jsp page is as shown:
<%# include file="/init.jsp"%>
<jsp:useBean id="processName" class="java.util.ArrayList" scope="request" />
<aui:select id="process" name="processitems">
<c:forEach items="${processName}" var="process">
<aui:option value="${process}">
${process}
</aui:option>
</c:forEach>
</aui:select>
Any help would be much appreciated.
Not sure if this is a complete answer, but some steps to figure out what the problem is. I'm taking your question as well as some comments:
You're implementing a portlet action handler, from there, you won't forward/dispatch to a particular jsp: A portlet's ACTION phase is only good for changing the state, while displaying the result is part of the VIEW phase. The code that you've posted (though it's obviously simplified) looks like it rather wants to live in doView().
In fact, that may be all you need: If you just display the portlet, only the VIEW phase will be triggered. Just displaying the portlet will not trigger the action handler, which you can validate in a debugger.
For the JSP: All you say is you "can't seem to see" any of the results. Validate where your problem is: Is the list there? Does enumerating the list work? Is your problem with the AUI taglib? You can easily check this by removing all of the other tags and rather generate pure output by removing a bit.
When you look at the output's source and any of the JSP stuff survives (e.g. the ${processName}, or <aui:select..>, <c:forEach...>, then you'll know that this is the root cause for "not seeing" anything. You might miss a taglib or other.
Last: I've never tried this, but <aui:select> is a tag that's meant to be used within a form, and I'm not sure what it does outside of a form - you may want to surround it with <aui:form ....> and see what happens then.
I found the solution:
I was to use:
public void displayProcess(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException {
instead of
public void displayProcess(ActionRequest request, ActionResponse response) {
and at the bottom of my method the following:
renderRequest.setAttribute("process", process);
super.render(renderRequest, renderResponse);
On the jsp page, at the topmost point; receive the ArrayList that you are passing as:
<% ArrayList<String> process = (ArrayList) request.getAttribute("process"); %>
.
The results are as follows:

JSP form going as empty randomly after submitting with post request

JSP form going as empty randomly after submitting with post request. I am using springboott with embedded tomcat in a openshift container. I have seen similar request in 2016 but no reply. Any help is highly appreciated.
JSP:
<textarea id="dataArea" cols="111" rows="28" name="data" Class="prj" onkeydown="limitCounter(this, countdown);" onkeyup="limitText(this, countdown);" onchange="limitText(this, countdown);" onclick="trueCount(this, countdown);">${frm.data}</textarea>
<img src="/prj/web/images/data_button.gif" border="0" style="cursor:hand" title="ALT + S" onclick="javascript:saveData()">
Javascripts:
function saveComments()
{ document.forms[0].action='<%=contextPath%>/saveData';
document.forms[0].submit(); self.close();
}
Controller:
#RequestMapping(value = "/saveData", method ={RequestMethod.POST})
public ModelAndView saveData(ModelMap modelMap, #ModelAttribute("frm") dataForm frm, BindingResult bindingResult, HttpServletRequest request, HttpServletResponse response)
throws Exception { }
We had both these RequestMethod.GET and RequestMethod.POST and removed the GET from the controller, but it did not work.
This code is working fine for 50 to 60 occurrences and the next one fails and the form is empty. We have enabled the logger and it showed the empty form. The immediate next action is working fine. Note: This action is performed from the popup screen. Please let me know if you need any more details
Finally the issue is resolved.
The issue is with the self.close() right after the submit action.
The root cause is the browser and it is triggering the self.close() before the submit action. We have removed the self.close() from there and close it after we received the response from controller. This fixed the issue. Thanks for the below post which helped us to identify the root cause.
Submit a form in a popup, and then close the popup

Springroo calling method from Controller or create menu item

I tried to figure it out by myself, but i did not get it either how to create my own menu category/item to link to a new page or just call a method from my controller in the view.
I implemented Spring batch for XML/Database stuff, it's working fine, i put the call of this method inside the "list all" method to test it until i find a way call this method in the view.
Thank you for your time.
For creating my menu Entry and my controller, i did in roo shell :
controller class --class ~.web.DataTransferController --preferredMapping /datatransfer
Then my method :
#RequestMapping(value = "/exportdatatoxml" , method=RequestMethod.GET)
private void runExportDataTOXML(HttpServletRequest request, HttpServletResponse response) throws SQLException {
...
}
And in my jspx
<input type="button" onclick="location.href='${pageContext.request.contextPath}/datatransfer/exportdatatoxml'" value="Export to XML" />
i should look harder.

How do I get data from the form inputs in a Freemarker template into a spring MVC controller?

I am trying to receive simple text input from a form generated by a freemarker template. The correct method is being invoked, but the model is empty, where I am expecting it to be populated.
I am working in the context of a pre-existing application, or I would have tossed this combination aside long ago and gone to a straight Spring MVC/JSP implementation.
I have been through every tutorial on the web, and many postings on this very topic in stackoverflow, and I am still failing to grasp something. Whatever I am missing may be so elementary that no one bothers to post it.
The examples from within the application are not very helpful because they are constructed with sufficient indirection that I can't see how they work at all.
Freemarker template
<#import "/spring.ftl" as spring />
<#spring.bind "model"/>
<form name="model" method="post">
<input type="text" name="user" id="user" value="${model.user}"/>
<input type="hidden" id="submission" name="submission"/>
<input type="submit" name="test" id="test" value="Test" onclick="document.getElementById('submission').value = 'test'"/>
</form>
Controller code:
#RequestMapping(value = "/config", method = RequestMethod.POST)
public ModelMap postConfig(#ModelAttribute("model") ModelMap model) {
logger.debug("User name was {}", model.get("user")); // Why is model empty here?
return model;
}
In the end, I was unable to use the ModelMap as an input. What I believe is the reason is that, while Spring has a million ways to accomplish any given task, the freemarker integration is not as robust as the jsp integration.
There is a little known but widely used feature of spring that resolves form elements to method parameters by name. Based on other people's comments I don't believe it is well documented. But, since it is core to the Groovy on Grails framework, I believe it is safe to consider it to be core to Spring.
The solution I finally used is this:
#RequestMapping(value = "/config", method = RequestMethod.POST)
public ModelMap postConfig(String user) {
logger.debug("User name was {}", user); // Why is model empty here?
// ... snip ...
model.put("user", user);
return model;
}
Spring resolves form entities to the controller method parameters by type and name. It's a bit inconvenient for my intention, but it gets the data where I can work with it.

doGet and doPost in Servlets

I've developed an HTML page that sends information to a Servlet. In the Servlet, I am using the methods doGet() and doPost():
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
String id = req.getParameter("realname");
String password = req.getParameter("mypassword");
}
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
String id = req.getParameter("realname");
String password = req.getParameter("mypassword");
}
In the html page code that calls the Servlet is:
<form action="identification" method="post" enctype="multipart/form-data">
User Name: <input type="text" name="realname">
Password: <input type="password" name="mypassword">
<input type="submit" value="Identification">
</form>
When I use method = "get" in the Servlet, I get the value of id and password, however when using method = "post", id and password are set to null. Why don't I get the values in this case?
Another thing I'd like to know is how to use the data generated or validated by the Servlet. For example, if the Servlet shown above authenticates the user, I'd like to print the user id in my HTML page. I should be able to send the string 'id' as a response and use this info in my HTML page. Is it possible?
Introduction
You should use doGet() when you want to intercept on HTTP GET requests. You should use doPost() when you want to intercept on HTTP POST requests. That's all. Do not port the one to the other or vice versa (such as in Netbeans' unfortunate auto-generated processRequest() method). This makes no utter sense.
GET
Usually, HTTP GET requests are idempotent. I.e. you get exactly the same result everytime you execute the request (leaving authorization/authentication and the time-sensitive nature of the page —search results, last news, etc— outside consideration). We can talk about a bookmarkable request. Clicking a link, clicking a bookmark, entering raw URL in browser address bar, etcetera will all fire a HTTP GET request. If a Servlet is listening on the URL in question, then its doGet() method will be called. It's usually used to preprocess a request. I.e. doing some business stuff before presenting the HTML output from a JSP, such as gathering data for display in a table.
#WebServlet("/products")
public class ProductsServlet extends HttpServlet {
#EJB
private ProductService productService;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Product> products = productService.list();
request.setAttribute("products", products); // Will be available as ${products} in JSP
request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response);
}
}
Note that the JSP file is explicitly placed in /WEB-INF folder in order to prevent endusers being able to access it directly without invoking the preprocessing servlet (and thus end up getting confused by seeing an empty table).
<table>
<c:forEach items="${products}" var="product">
<tr>
<td>${product.name}</td>
<td>detail</td>
</tr>
</c:forEach>
</table>
Also view/edit detail links as shown in last column above are usually idempotent.
#WebServlet("/product")
public class ProductServlet extends HttpServlet {
#EJB
private ProductService productService;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Product product = productService.find(request.getParameter("id"));
request.setAttribute("product", product); // Will be available as ${product} in JSP
request.getRequestDispatcher("/WEB-INF/product.jsp").forward(request, response);
}
}
<dl>
<dt>ID</dt>
<dd>${product.id}</dd>
<dt>Name</dt>
<dd>${product.name}</dd>
<dt>Description</dt>
<dd>${product.description}</dd>
<dt>Price</dt>
<dd>${product.price}</dd>
<dt>Image</dt>
<dd><img src="productImage?id=${product.id}" /></dd>
</dl>
POST
HTTP POST requests are not idempotent. If the enduser has submitted a POST form on an URL beforehand, which hasn't performed a redirect, then the URL is not necessarily bookmarkable. The submitted form data is not reflected in the URL. Copypasting the URL into a new browser window/tab may not necessarily yield exactly the same result as after the form submit. Such an URL is then not bookmarkable. If a Servlet is listening on the URL in question, then its doPost() will be called. It's usually used to postprocess a request. I.e. gathering data from a submitted HTML form and doing some business stuff with it (conversion, validation, saving in DB, etcetera). Finally usually the result is presented as HTML from the forwarded JSP page.
<form action="login" method="post">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="login">
<span class="error">${error}</span>
</form>
...which can be used in combination with this piece of Servlet:
#WebServlet("/login")
public class LoginServlet extends HttpServlet {
#EJB
private UserService userService;
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userService.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user);
response.sendRedirect("home");
}
else {
request.setAttribute("error", "Unknown user, please try again");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
}
You see, if the User is found in DB (i.e. username and password are valid), then the User will be put in session scope (i.e. "logged in") and the servlet will redirect to some main page (this example goes to http://example.com/contextname/home), else it will set an error message and forward the request back to the same JSP page so that the message get displayed by ${error}.
You can if necessary also "hide" the login.jsp in /WEB-INF/login.jsp so that the users can only access it by the servlet. This keeps the URL clean http://example.com/contextname/login. All you need to do is to add a doGet() to the servlet like this:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
}
(and update the same line in doPost() accordingly)
That said, I am not sure if it is just playing around and shooting in the dark, but the code which you posted doesn't look good (such as using compareTo() instead of equals() and digging in the parameternames instead of just using getParameter() and the id and password seems to be declared as servlet instance variables — which is NOT threadsafe). So I would strongly recommend to learn a bit more about basic Java SE API using the Oracle tutorials (check the chapter "Trails Covering the Basics") and how to use JSP/Servlets the right way using those tutorials.
See also:
Our servlets wiki page
Java EE web development, where do I start and what skills do I need?
Servlet returns "HTTP Status 404 The requested resource (/servlet) is not available"
Show JDBC ResultSet in HTML in JSP page using MVC and DAO pattern
Update: as per the update of your question (which is pretty major, you should not remove parts of your original question, this would make the answers worthless .. rather add the information in a new block) , it turns out that you're unnecessarily setting form's encoding type to multipart/form-data. This will send the request parameters in a different composition than the (default) application/x-www-form-urlencoded which sends the request parameters as a query string (e.g. name1=value1&name2=value2&name3=value3). You only need multipart/form-data whenever you have a <input type="file"> element in the form to upload files which may be non-character data (binary data). This is not the case in your case, so just remove it and it will work as expected. If you ever need to upload files, then you'll have to set the encoding type so and parse the request body yourself. Usually you use the Apache Commons FileUpload there for, but if you're already on fresh new Servlet 3.0 API, then you can just use builtin facilities starting with HttpServletRequest#getPart(). See also this answer for a concrete example: How to upload files to server using JSP/Servlet?
Both GET and POST are used by the browser to request a single resource from the server. Each resource requires a separate GET or POST request.
The GET method is most commonly (and is the default method) used by browsers to retrieve information from servers. When using the GET method the 3rd section of the request packet, which is the request body, remains empty.
The GET method is used in one of two ways:
When no method is specified, that is when you or the browser is requesting a simple resource such as an HTML page, an image, etc.
When a form is submitted, and you choose method=GET on the HTML tag. If the GET method is used with an HTML form, then the data collected through the form is sent to the server by appending a "?" to the end of the URL, and then adding all name=value pairs (name of the html form field and value entered in that field) separated by an "&"
Example:
GET /sultans/shop//form1.jsp?name=Sam%20Sultan&iceCream=vanilla HTTP/1.0 optional headeroptional header<< empty line >>>
The name=value form data will be stored in an environment variable called QUERY_STRING.
This variable will be sent to a processing program (such as JSP, Java servlet, PHP etc.)
The POST method is used when you create an HTML form, and request method=POST as part of the tag. The POST method allows the client to send form data to the server in the request body section of the request (as discussed earlier). The data is encoded and is formatted similar to the GET method, except that the data is sent to the program through the standard input.
Example:
POST /sultans/shop//form1.jsp HTTP/1.0 optional headeroptional header<< empty line >>> name=Sam%20Sultan&iceCream=vanilla
When using the post method, the QUERY_STRING environment variable will be empty.
Advantages/Disadvantages of GET vs. POST
Advantages of the GET method:
Slightly faster
Parameters can be entered via a form or by appending them after the URL
Page can be bookmarked with its parameters
Disadvantages of the GET method:
Can only send 4K worth of data. (You should not use it when using a textarea field)
Parameters are visible at the end of the URL
Advantages of the POST method:
Parameters are not visible at the end of the URL. (Use for sensitive data)
Can send more that 4K worth of data to server
Disadvantages of the POST method:
Can cannot be bookmarked with its data
The servlet container's implementation of HttpServlet.service() method will automatically forward to doGet() or doPost() as necessary, so you shouldn't need to override the service method.
Could it be that you are passing the data through get, not post?
<form method="get" ..>
..
</form>
If you do <form action="identification" > for your html form, data will be passed using 'Get' by default and hence you can catch this using doGet function in your java servlet code. This way data will be passed under the HTML header and hence will be visible in the URL when submitted.
On the other hand if you want to pass data in HTML body, then USE Post: <form action="identification" method="post"> and catch this data in doPost function. This was, data will be passed under the html body and not the html header, and you will not see the data in the URL after submitting the form.
Examples from my html:
<body>
<form action="StartProcessUrl" method="post">
.....
.....
Examples from my java servlet code:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter out = response.getWriter();
String surname = request.getParameter("txtSurname");
String firstname = request.getParameter("txtForename");
String rqNo = request.getParameter("txtRQ6");
String nhsNo = request.getParameter("txtNHSNo");
String attachment1 = request.getParameter("base64textarea1");
String attachment2 = request.getParameter("base64textarea2");
.........
.........

Categories

Resources