When sending a redirect is it possible to see what are the parameters passed from the servlet we redirected to?
For exampe:
We redirect from servlet servletA
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws IOException, ServletException {
resp.sendRedirect(req.getContextPath()+"/foo#fooMethod:val1="+val1+"&val2="+val2);
}
So what does servlet servletB need to do to pick up val1/val2/fooMethod?
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws IOException, ServletException {
}
As just like your query parameters.
String value2 = req.getParameter("val2");
And same goes for remaining too.
And I belive you need to write ? instead of # to append the query parameters to the url.
See the reference on Sun/Oracle's java servlet site:
http://docs.oracle.com/javaee/6/api/javax/servlet/ServletRequest.html
You'd essentially have to do req.getParameter("val2")
will be a String Type and you can convert it to whatever type you need.
In the future if your parameter has more than one value you'd use getParameterValues(java.lang.String). You can pass arrays of Strings, etc.
Also
/foo#fooMethod:val1= should be
/foo?doGet:val1=yourValue&val2=yourNextValue&val3=yourNextNextValue
Related
#Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("orden", 11);
System.out.println("ord "+request.getParameter("orden"));//returns null
request.getRequestDispatcher("/view/a.jsp").forward(request, response);
}
//Why does this happen?
and in my jsp is the same result = null
You are setting an attribute and trying to get a parameter
request.setAttribute("orden", 11);
request.getAttribute("orden");
attribute and parameter are different things. As you are setting attribute, use getAttribute() to get the value.
System.out.println("ord "+request.getAtribute("orden"));
I have written the following code in service and post methods
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter p = response.getWriter();
p.println("<html><body>");
p.println("<form action = roomlog2 method = post>");
p.println("<input type = submit value = back>");
p.println("</form>");
p.println("</body></html>");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendRedirect("homepage.html");
}
But when i executed the code and click the back button the post method is not executing. I am getting following exception
java.lang.NumberFormatException: null
why the post method not redirecting to the "homepage.html"?why i am getting the exception?Kindly someone can tell me the error.
Just remove your implementation of the service() method, or have it call super.service(). That's how doPost() gets called. At present you're not calling it at all.
I am working on a filter, this code fails to execute/response.write if there is a 'forward' involved in the request. But it works fine for basic servlets that simply steam HTML content to the user. How can address "forwards" with this code.
For example, here is the filter that simple captures text content and attempts to manipulate that content.
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpSession session = request.getSession(false);
CharResponseWrapper responseWrapper = new CharResponseWrapper((HttpServletResponse) response);
chain.doFilter(request, responseWrapper);
final boolean commit1 = responseWrapper.isCommitted();
final boolean commit2 = response.isCommitted();
if (!commit2) {
final String res = responseWrapper.toString().replaceAll("(?i)</form>", "<input type=\"hidden\" name=\"superval\" value=\""+superval"\"/></form>");
response.getWriter().write(res);
}
return;
}
...
This works for most basic servlets, the goal is at the line with the "replaceAll".
Now, if I create a servlet with a 'forward' the code does not work, it fails at the line with 'if (!commit2)' because the stream is already committed apparently?
For example, if I make a request to this servlet and tie the filter to this servlet, then the filter does not execute completely.
public class TestCommitServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("TestCommitServlet2").forward(req, resp);
}
#Override
protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
And here is the servlet that I am forwarding to:
public class TestCommitServlet2 extends HttpServlet {
private static final long serialVersionUID = 1L;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
final PrintWriter out = resp.getWriter();
resp.setContentType("text/html");
out.println("<html><body>(v-1)testing<form action='test'><input type='submit' value='Run' /> </form></body></html>");
}
#Override
protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
Tl;dr : Do I have to make this call 'if (!commit2) {' The code works without it. Under this code, how would I avoid Response already committed or IllegalStateExceptions (around the line with response.getWriter().write(res);
More on the issue here:
https://codereview.stackexchange.com/questions/41260/capturing-content-within-a-j2ee-filter-and-then-replacing-this-text-request-for
I´m using Servlet API 3.0 to check this scenario.
What I found is the following. Using your code for the servlet and the filters when I call the TestCommitServlet2 , I´m able to see the following output.
http://localhost:8080/Question/TestCommitServlet2
(v-1)testing
Button here
com.koitoer.CharResponseWrapper#5b5b6746
When I call the servlet TestCommitServlet , Im able to see the following.
http://localhost:8080/Question/TestCommitServlet
(v-1)testing
Button here
this shown that filter is not apply to this forwarded request at all.
So, I remember that some filters can act in diverse DispatcherTypes as FORWARD, INCLUDE, ERROR, ASYNC and the commong REQUEST, what I decide is change the filter declaration to.
#WebFilter(filterName = "/MyFilter", urlPatterns = { "/TestCommitServlet2" }, dispatcherTypes = {
DispatcherType.FORWARD, DispatcherType.REQUEST })
public class MyFilter implements Filter {
Then when I excecute a GET over the servlet TestCommitServlet I got:
(v-1)testing
Button
com.koitoer.CharResponseWrapper#1b3bea22
the above shown that Filter is now applied to the forward request.
Also if I remove or comment lines for if (!commit2) { code still works, so there is no IllegalStateException as request need to pass over the filter which is who invoke the doChain method.
One note more, if you try to replace the content of the response using this.
responseWrapper.toString().replaceAll
You are doing it wrong as responseWrapper.toString() returns something like this CharResponseWrapper#5b5b6746, not the content, if you want to modify the response use a Wrapper that extends from HttpServletResponseWrapper and override the correct methos to manipulate the outpustream.
In case of an exception in my Java REST application I would like to log various information on causing HTTP request.
I can obtain the URI of the request and the HTTP headers via context injection
#Context
private UriInfo uriInfo;
#Context
private HttpHeaders headers;
But how can I obtain the HTTP method (GET, PUT, ...)?
I use Jersey. Don't know if this applies for you but ... :
import javax.servlet.http.HttpServletRequest;
#Context final HttpServletRequest request
The Request class has the method getMethod(). It returns the used HTTP method.
You are usually limiting the rest methods to one http method
#GET
#Produces("text/plain")
public String getClichedMessage() {
// Return some cliched textual content
return "Hello World";
}
Jersey is irrelevant (following the most upvoted answer.)
HttpServletRequest class of Java Servlet API has getMethod() method that returns the name of the HTTP method (GET, POST, PUT, etc).
But you do not always need it. For example, if you are in servlet, you have doGet, doPost methods.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//method is POST
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//method is GET
}
But you do need it, for example, in the filter:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws ServletException, IOException {
String method = ((HttpServletRequest) request).getMethod();
}
Speaking of the REST, different REST frameworks may provides various ways to obtain the HttpServletRequest object.
I've got this issue, recently I read about the REST arquitecture and it makes a perfect sense, so I'd like to achieve a RESTful web application.
Now, I'm following the Front Controller pattern that means that all of the URL mappings go to the controller.java servlet, I map the by specific URLs, not by using the /* wildcard,
the controller implements the four HTTP methods POST,GET,PUT,DELETE, each method calls the controllers service method and there I determine based on the HttpServletRequest and pathInfo the action to execute.
Controller.java
#Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
IAction action;
View view;
try {
action = ActionFactory.produceAction(req);
view = action.execute(req, resp);
switch (view.getDispatchMethod()) {
case REDIRECT:
resp.sendRedirect(resp.encodeURL(view.getResource()));
break;
case FORWARD:
req.getRequestDispatcher(view.getResource()).forward(req, resp);
break;
case INCLUDE:
req.getRequestDispatcher(view.getResource()).include(req,resp);
break;
default:
}
} catch (ActionFailedException uae) {
req.setAttribute("ActionName", "Action");
req.setAttribute("FailCause", uae.getMessage());
req.getRequestDispatcher(VIEW_FAIL.getResource()).forward(req, resp);
}
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.service(req, resp);
}
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.service(req, resp);
}
#Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.service(req, resp);
}
#Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.service(req, resp);
}
I've run into a particular issue when loading a specific order by the URI /orders/*, it is mapped to the controller servlet, the the action is executed and I load the appropriate order the action returns a View.java class
//ommited accessors and mutators for brevety.
public class View {
public enum DispatchMethod {
INCLUDE, FORWARD, REDIRECT
}
private DispatchMethod dispatchMethod;
private String resource;
public View(DispatchMethod dispatchMethod, String resource) {
this.dispatchMethod = dispatchMethod;
this.resource = resource;
}
}
Then the request is dispatched according to the getDispatchMethod() of the returned view.
Now, here is where the loop gets triggered, I use the following URL, myapp/orders/78965 /orders/* gets mapped to controller.java the appropriate action is executed and the correct order is found by the pathInfo() the returned view is new View(View.DispatchMethod.FORWARD,"order_details.jsp") the problem is that with the three available dispatch methods REDIRECT,FORWARD and INCLUDE a request is re-triggered on the URL and so on and on and on I never reach the order_details.jsp that renders the data.
So, how would you avoid the looping, as I'd like to preserve the URI displaying the order number I use the forward method, also, I'd like to do it using servlets, I've heard of the UrlRewriteFilter maybe in the future, but right now, how would it be done using "Plain Vanilla" since I'm using the Front Controller pattern, will it be necessary to add an additional servlet in the /orders/ URI ?
Any help or insights is truly appreciated.
EDIT 1:
Pasted the source code of the controller, a very basic one, I have my suspicions that the way the service method calls all of the overriden do[Method] of the servlet is triggering the loop and that it may be solved by splittig them.
Implementing a RESTful HTTP interface in Java is a lot easier using a JAX-RS implementation like RESTEasy or Jersey.
Using a Front Controller to dispatch requests to the right resource is a good approach, it's exactly the approach taken by these JAX-RS frameworks. I fear you may be re-inventing the wheel here by writing a bespoke URL parsing and dispatching mechanism when this can be taken off-the-shelf.
JAX-RS is a lightweight way to expose resources. By using a couple of simple annotations you can expose a REST interface without any plumbing required. For example:
public class Order {
#GET
#Path("/orders/{orderId}")
#Produces("text/html")
public void getOrder(#Context HttpServletResponse response,
#Context HttpServletRequest request,
#PathParam("orderId") String orderId) throws ServletException, IOException {
// ... create view and add to request here
request.getRequestDispatcher("orders.jsp").forward(request, response);
}
}
You can see how simple it is to attach this class to a URL path (using the #Path annotation), and how easily you can parse values from the URL using #PathParam. Since you get all the plumbing/dispatching/parsing off-the-shelf, you can concentrate on the bits of your app that are specific to your domain (such as what an order contains).