For a customer, I need to write a Servlet which can print values in a form post. The form is hosted on another server and looks somewhat like this:
<form action="http://myserver/myServlet" method="POST">
<input type="text" id="someName" value="someInterestingValue"/>
<input type="submit" value="submit" />
</form>
I have a Tomcat 5.0.28 server available, running on a Java 1.4 jdk, so I made a simple servlet:
public class ProxyServlet extends HttpServlet {
public void doPost(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
PrintWriter out = res.getWriter();
Enumeration a =req.getAttributeNames();
while (a.hasMoreElements()){
String attrname = (String) a.nextElement();
out.println(attrname+"="+req.getAttribute(attrname)+"<br/>");
}
out.close();
}
}
When I go to the servlet by URL everything looks as expected. When I send a GET request with some parameters, I can see those as attributes in the debugger in the doGet() method (method was left out for brevety).
However, in the doPost(), my form fields seem to be missing. I've looked into the Tomcat logfiles, and nothing special is logged. I tried to add a crossdomain.xml to some directories but did not find a way to change this behaviour.
So to be clear: The Form as listed above is on server A. My servlet runs on an existing legacy Tomcat/Java application hosted on server B. When the form is of type "POST" none of the fields arrive at the Servlet on server B. Apache is NOT "in front" of Tomcat.
Is there some configuration setting I am missing in Tomcat?
Any tips or suggestions where to look next?
Help is greatly appreciated.
Request attributes? Don't you need to access them as request parameters using HttpServletRequest#getParameter() and so on?
Which adds more confusion is that you said that it works in the doGet(). How does its code look like then? Does it also access them as attributes? That would in a normal JSP/Servlet environment (i.e. you aren't using some filter which copies the parameters to attributes or so) have been impossible.
This has nothing to do with cross-site. As BalusC said, use getParameter... instead of getAttribute... methods
Found the problem. After a whole day of searching and coding, it all boils down to the fact that my code was working fine. The problem is in the form. the line:
<input type="text" id="someName" value="someInterestingValue"/>
Should read:
<input type="text" name="someName" value="someInterestingValue"/>
For people mentioning "getParameter" instead of "getAttribute" you are totally correct. In my test code I had both just to be sure (because I thought I lost it...) but both were not returning results, as the browser was simply not sending the name/value pairs.
I guess posting this on Stackoverflow did help, because I had to explain and re-read my problem I thought the "id=" looked funny. Coding is finding bugs in pieces of text you are overlooking...
Related
I am trying to validate 2 model attributes on one action using spring validation framework. The purpose is to validate the lookUpbean (search criterion) on click of Search button and then to validate the resultant bean also i.e memberShipbean once we get it from the services so that we can show warnings to the user if some fields are empty in the resultant bean.
<form:form method="POST" modelAttribute="lookupPageBean" id="lookupForm" name="lookupForm"
action="lookupMembership.htm">
<td class="error">
<form:errors path="membershipNumber" />
<form:input class="medium-textbox" id="membershipNumber" path="membershipNumber" />
<button type="submit" class="Active-button-small">
<fmt:message key="button.go" />
</button>`
#RequestMapping(method = RequestMethod.POST, value = URLMappingConstant.MEMBERSHIP_LOOKUP)
public String viewMembership(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response,
#ModelAttribute(UIConstant.LOOKUP_PAGE_BEAN) LookupPageBean lookupPageBean, BindingResult result,
#ModelAttribute(UIConstant.MEMBERSHIP_BEAN) MembershipPageBean membershipPageBean, BindingResult error) throws WebMTracksException
{
membershipValidator.validate(lookupPageBean, result);
membershipValidator.validate(membershipPageBean, error);
}
Now what is happening is first validation is working fine however during second validation
the error messages are not shown on the resultant jsp ,
however the errors are reported till this controller layer in the “error” binding results.
Also in the validation layer
ValidationUtils.rejectIfEmpty(errors, UIConstant.BUSINESSNAME,ValidationMSGConstants.BUSINESS_NAME)
This method always returns validation errors even if the field is not empty.
First question is can we have multiple model attributes in one action. I read it somewhere on internet but could not find any implementation of the same. Please help me to resolve this issue. Also let me know if you can think of any other working solution for this problem but I would like to use only the spring framework for the both the validations as that helps to maintain the existing design of the application.
I do not think you have bind multiple Model Attributes to the same form, which I believe is what you are asking. I am not even sure what that request would look like, from an HTTP stand point, as I don't believe Spring would have a way to detangle all the bean's properties, especially if the names overlap. What you may want to consider doing is wrapping your LookupPageBean and MembershipPageBean into one "form bean".
As for the error messages, you may want to take a look at the spring:bind tag. It may do what you are needed to get the binding errors from the second Model Attribute.
I am trying to get some data from a Form with jersey and i though it would be an easy task to accomplish, however I am getting an error when I try to POST something.
Caused by: java.lang.IllegalStateException: The #FormParam is utilized when the content type of the request entity is not application/x-www-form-urlencoded
at org.glassfish.jersey.server.internal.inject.FormParamValueFactoryProvider$FormParamValueFactory.ensureValidRequest(FormParamValueFactoryProvider.java:126)
at org.glassfish.jersey.server.internal.inject.FormParamValueFactoryProvider$FormParamValueFactory.getForm(FormParamValueFactoryProvider.java:111)
at org.glassfish.jersey.server.internal.inject.FormParamValueFactoryProvider$FormParamValueFactory.get(FormParamValueFactoryProvider.java:94)
at org.glassfish.jersey.server.internal.inject.AbstractHttpContextValueFactory.provide(AbstractHttpContextValueFactory.java:65)
at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:80)
... 36 more
I think this is the relevant part of the stack trace.
Now for the code I am using:
#POST
#Path("/delete")
#Produces("application/json")
public String delete(#FormParam("id")String id){
And I am trying to POST using a test html page like this:
<form action="<path to the server>/delete" method="post">
primary_id: <input type="text" name="primary_id" /><br />
<input type="submit" value="Submit" />
</form>
I've been trying to make it work but no chance. I have tried adding the #Consumes() annotation with multipart-form-data but can't really make it work. I hope someone can give me a hand.
Thank you all for the help. With some code reviewing i found the problem. Even though I don't think anyone else will make this particular mistake I'll post it anyway for future reference.
The problem was that I am not using a standard web server. I've implemented a netty server with Jersey and the problem was in that said implementation. The problem was that i wasn't passing the headers in the HTTP request to Jersey as I should. I was loosing the Content-Type in the middle of the operation, this means that Jersey couldn't identify the message type.
So, for future reference, for anyone having a similar problem while trying to implement a non-standard server using jersey: when you don't pass the media type correctly (there is a method called getMediaType() in the ContentRequest class that is used, among other things, to validate the Content-Type when #FormParam is used) you will get this type of Exception.
Again, thank you all for the help :)
Your code is working fine except you need to change
<input type="text" name="id" />
Since you havent define #Consumes(), by default delete method consumes mediaType="application/x-www-form-urlencoded" .
I have tested your code and it is working perfectly fine here. My suggestion is check your jersey jar files Specially jsersey-server.jar file in your lib folder.
You are naming your input as "primary_id", but you are receiving "id" name in your #FormParm annotation. Change the id and name in your input tag to "id".
Also if you are consuming application/x-www-form-urlencoded, add this attribute to your form tag: enctype="application/x-www-form-urlencoded"
I have implemented JCaptcha in my web application and it works fine but when cookies of the browser is blocked it always fail and return false.
the servlet code is as follows:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userCaptchaResponse =request.getParameter("jcaptcha");
boolean captchaPassed = SimpleImageCaptchaServlet.validateResponse(request, userCaptchaResponse);
if(captchaPassed){
System.out.println("success!!"+userCaptchaResponse);
RequestDispatcher rd=request.getRequestDispatcher("Result.jsp");
rd.forward(request, response);
//response.sendRedirect("Result.jsp");
}else{
System.out.println("failure!!"+userCaptchaResponse);
response.sendRedirect("Index.jsp"+"?id=false");
}
}
and code in jsp page is
<tr align="center">
<td align="right" width="33%"><img height="60px" width="140px" src="jcaptcha.jpg" /></td>
<td align="left" width="33%" valign="middle"><input type="text" name="jcaptcha" value="" /></td>
</tr>
I want my captcha to work irrespective of whether the cookies are blocked or not!!!
is there any solution for this or any other method to implement captcha in java
I am using jdk 1.7 and tomcat 7 as runtime environment.
The problem with your captcha lookup is that it relies on a User session. Which is in my opinion a design flaw. If cookies are blocked the session will not be linked to the user.
There are other libraries e.g. SimpleCatcha. Or other services like recaptcha.
Basically if you have a library which generates you a captcha you might implement it like this as pseudo algorithm which is not session dependent:
For every form including a captcha:
Generate temporary captcha
Generate a hard to guess and unique identifier (maybe with a uuid).
Link the unique identfier with the correct answer server side and persist it temporarily
Provide the unique identifier in the generated form
If a user sends the form he will provide the guess and the uuid you might lookup this pair on your server side.
Invalidate the UUID and the Image wether or not the user entered the correct answer.
If this is too slow from a performance perspective you might consider to have a background process to fill up a fixed size FILO container/queue to hold precomputed captchas.
JCaptcha doesn't work if the cookies are disabled. There is a bug: http://jcaptcha.octo.com/jira/browse/JASTR-3
You can try another library, for example recaptcha.
I am pretty new to servlets and web development in general.
So basically I have a servlet that queries a database and returns some values, like a name. What I want is to turn the name into a link that opens a details page for that name (which another servlet would handle). How can I send the name to the other servlet so it can query a database for the relevant details?
Maybe I'm taking the wrong approach?
Edit: I am using Tomcat 5.5
Pass it as request parameter.
Either add it to the query string of the URL of the link to the other servlet which is then available by request.getParameter("name") in the doGet() method.
link
Or add it as a hidden input field in a POST form which submits to the other servlet which is then available by request.getParameter("name") in the doPost() method.
<form action="otherservlet" method="post">
<input type="hidden" name="name" value="${name}" />
<input type="submit" />
</form>
See also:
Servlets info page - contains a Hello World
Not sure if I understand correctly, but you may look at javax.servlet.RequestDispatcher and forward the url to the second servlet.
The url could be created using the name:
http://myhost.mydomain/my.context/servlet2.do?name=John
I would create the URL either in the first servlet or in a client using a configurable template for the URL. This way both servlets are clearly separated - you can even have each one on different machine.
I have a doubt regarding the use of servlets.
In the application I'm building I use Html pages to ask the user for info.
Imagine a Html page that lets the user request to see on the screen the content of a data base. What I'm doing is:
1.- From the Html page I'm calling a servlet that will open a connection with the database.
2.- The servlet builds the web page that the user will see.
My question is: is there any other way of doing this? Do I have to build the web page in the servlet or is there any way of sending the information contained in the database to an .html file which will build the web page (in my case I need to show on the screen a table containing all the information) ?
Thanks
Servlets are meant to control, preprocess and/or postprocess requests, not to present the data. There the JSP is for as being a view technology providing a template to write HTML/CSS/JS in. You can control the page flow with help of taglibs like JSTL and access any scoped attributes using EL.
First create a SearchServlet and map it on an url-pattern of /search and implement doGet() and doPost() as follows:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Preprocess request here and finally send request to JSP for display.
request.getRequestDispatcher("/WEB-INF/search.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Postprocess request here. Get results from your DAO and store in request scope.
String search = request.getParameter("search");
List<Result> results = searchDAO.find(search);
request.setAttribute("results", results);
request.getRequestDispatcher("/WEB-INF/search.jsp").forward(request, response);
}
Here's how the JSP /WEB-INF/search.jsp would look like, it makes use of JSTL (just drop JAR in /WEB-INF/lib) to control the page flow.
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
...
<form action="search" method="post">
<input type="text" name="search">
<input type="submit" value="search">
</form>
<c:if test="${not empty results}">
<p>There are ${fn:length(results)} results.</p>
<table>
<c:forEach items="${results}" var="result">
<tr>
<td>${result.id}</td>
<td>${result.name}</td>
<td>${result.value}</td>
</tr>
</c:forEach>
</table>
</c:if>
Note that JSP is placed in /WEB-INF to prevent users from direct access by URL. They are forced to use the servlet for that by http://example.com/contextname/search.
To learn more about JSP/Servlets, I can recommend Marty Hall's Coreservlets.com tutorials. To learn more about the logic behind searchDAO, I can recommend this basic DAO tutorial.
To go a step further, you could always consider to make use of a MVC framework which is built on top of the Servlet API, such as Sun JSF, Apache Struts, Spring MVC, etcetera so that you basically end up with only Javabeans and JSP/XHTML files. The average MVC frameworks will take care about gathering request parameters, valitate/convert them, update Javabeans with those values, invoke some Javabean action method to process them, etcetera. This makes the servlet "superfluous" (which is however still used as being the core processor of the framework).
In addition to Servlets, Java has JSP pages, which are a mix of HTML and custom tags (including the Java Standard Tag Library or JSTL) which are eventually compiled into Servlets.
There are other technologies for making web applications, including things like Java Server Faces (JSF), Apache Struts, Spring, etc... Spring in particular is very widely used in modern web application development.
Ultimately, though, it's like Brian Agnew said... you have to communicate back and forth from the browser to the server. These are just various technologies to facilitate that.
Ultimately the browser has to send a request to the server for the database info. You can do this in many ways:
build the whole page in the servlet (perhaps the simplest)
build a page in the servlet containing (say) XML data, and the browser renders it into HTML (via XSL/Javascript etc.). That may be suitable if you want the browser to control the formatting and presentation.
build a page containing AJAX requests to go back to the server and get the data. That may be more suitable for data that updates regularly, or more interactive applications.
There are numerous ways to skin this cat. I suspect you're doing the simplest one, which is fine. I would tend towards this without explicit requirements that mean I need to do something else. Further requirements that complicate matters may include paging the data if there's too much to fit on the screen. All the solutions above can be made to incorporate this in some fashion.
My java is rusty but...
in your Data Access layer, iterate over the result set and build a custom object and insert it into an ArrayList;
class DataAccess {
public ArrayList foo() {
// Connect to DB
// Execute Query
// Populate resultSet
ArrayList result = new ArrayList();
while (resultSet.hasNext()) {
CustomObject o = new CustomObject();
o.setProperty1(resultSet.getInt(1));
o.setProperty2(resultSet.getString(2));
// and so on
result.add(o);
}
return result;
}
}
Call this method from your Servlet. After you have populated the ArrayList, put it on the Request object and forward on to your .jsp page
ArrayList results = DataAccessClass.foo();
Request.setAttribute("Results", results);
In your jsp, build your markup using scriptlets
<% foreach (CustomObject o in Request.getAttribute("Results"))
{%>
<td><%= o.getProperty1()</td>
<td><%= o.getProperty2()</td>
<% } %>
Good luck