I'd like to map a servlet for every url ending with "/jsfinspector". For example:
http://localhost/myapp/pages/somewhere/jsfinspector
http://localhost/myapp/jsfinspector
Is it possible to do that? In a very simple way, without declaring all possible url patterns in web.xml?
The Servlet API doesn't support that.
Your best bet is creating a #WebFilter("/*") which forwards to #WebServlet("/jsfinspector") when the URL matches, as shown below:
if (request.getRequestURI().endsWith("/jsfinspector")) {
request.getRequestDispatcher("/jsfinspector").forward(request, response);
} else {
chain.doFilter(request, response);
}
You can if necessary extract the original request URI in servlet as below:
String originalRequestURI = (String) request.getAttribute(RequestDispachter.FORWARD_REQUEST_URI);
You could think about creating a filter to intercept every request and eventually redirect the flow. https://docs.oracle.com/javaee/6/tutorial/doc/bnagb.html
Related
All, I'm trying to upload a file in dam in CQ using assestManager and then trying to set values in metadata. Then I'm retrieving all the data one by one and storing in a list, and set it to request object and pass it to new jsp page using 'rd.forward(request, response);' but I'm getting error as:
javax.jcr.AccessDeniedException: Access denied.
even though all the access are given.
Code:-
String redirect = request.getParameter(":redirect"); //content/nextgen/marine/podupload.html
RequestDispatcher rd = request.getRequestDispatcher(redirect);
rd.forward(request, response); // throws me error as access denied
I'm assuming your initial request is a POST?
If so, try the following:
SlingHttpServletRequest newRequest = new SlingHttpServletRequestWrapper(request) {
public String getMethod() {
return "GET";
}
};
newRequest.getRequestDispatcher("/content/nextgen/marine/podupload.html")
.forward(newRequest, response);
If this is a GET request that you are trying to forward then it's a permission issue. If this is a POS or PUT request then you will need a SlingHttpServletRequestWrapper to wrap and modify your request as a GET request forward.
This is simply because sling cannot forward POST requests.
I feel like this should be easy. I have an app where all I am trying to do is have a form page (index.jsp) that calls a servlet (CheckInfo.java) which sets a new header (myHeader) and redirects the user to another page (redirect.jsp). All of these files are on the same server. The index.jsp is sending the request just fine and CheckInfo is processing and redirecting, but myHeader is not showing up on redirect.jsp. I've read several posts talking about response.sendRedirect sends a 302 which doesn't pass headers and that I should use RequestDispatcher, but nothing seems to work. Is there no way to send headers from a servlet to a jsp?
Here is the servlet code:
response.setHeader("myHeader", "hey there");
response.sendRedirect("redirect.jsp");
I have also tried this:
response.setHeader("myHeader", "hey there");
RequestDispatcher view = request.getRequestDispatcher("redirect.jsp");
view.forward(request, response);
And I have this in redirect.jsp:
System.out.println(request.getHeader("myHeader"));
This does not print anything.
If the answer to my question is no... then I would settle for a way to set the header once I got back to the jsp. My reverse proxy is looking for a specific header to determine whether or not to perform an action. Obviously I tried response.addHeader() on redirect.jsp, but the page has already loaded at that point so that just made me feel dumb.
response.setHeader("myHeader", "hey there");
response.sendRedirect("redirect.jsp");
You are adding it as response header and it is 302 response. Browser on seeing a 302 response will just look for Location header and fire a new request to this location. Custom headers in the response are untouched whereas you are expecting these custom response headers to be included in the request (to new redirect location) which is not being sent.
Solution:-
1. you can use request dispatcher and forward the request instead of external redirect. And you need to use request attributes here.
2. you can call submit form using an ajax request may be jquery like and handle the response manually(for 302 response) but would not suggest you to use this approach as it is not a cleaner and intuitive approach. Just mentioning so that you know there are other ways to achieve this.
The problem is that the redirect() method of the response initiates a new request altogether, thereby loosing the attributes that were set before redirecting. Luckily there is a fluent way of solving the problem still. See below
response.setHeader("myHeader", "hey there");
request.getRequestDispatcher("redirect.jsp").forward(request, response);
Then in your destination you can do response.getHeaders("myHeader")
I have tested the code.
I hope it's clear that in case of asking the client to redirect to another URL - the browser shall not honor the cookies.
However, the 2nd method - where server forwards the request is feasible. The main mistake appears to be in mutating the response while we are supposed to change the request.
Then again, one cannot directly mutate a HttpServletRequest object. Here is one way to do so:
HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request){
public String getHeader(String name) {
String value = super.getHeader(name);
if(Strings.isNullOrEmpty(value)) {
...
value = myNewHeader;
}
return value;
}
public Enumeration<String> getHeaders(String name) {
List<String> values = Collections.list(super.getHeaders(name));
if(values.size()==0) {
...
values.add(myNewHeader);
}
return Collections.enumeration(values);
}
public Enumeration<String> getHeaderNames() {
List<String> names = Collections.list(super.getHeaderNames());
names.add(myNewHeaderName);
...
return Collections.enumeration(names);
}
}
Followed by:
RequestDispatcher view = request.getRequestDispatcher("redirect.jsp");
// OR (If you can get servletContext)
RequestDispatcher view = servletContext.getRequestDispatcher("redirect.jsp");
view.forward(requestWrapper, response);
Reference:
https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletRequestWrapper.html
For the headers case - getHeader(), getHeaders() and getHeaderNames() fn in the reqWrapper obj need Overriding.
Similarly you can override cookies and params.
See also: Modify request parameter with servlet filter
NOTE: It might not be possible to forward a req to an endpoint which expects a different MIME type.
A client side redirect creates a new HTTP request/response pair.
This link may help you more on debugging perspective -
Sending Custom headers
The problem is that the servlet can't include response from another one. Well, I have one servlet called "Query" which has such block:
RequestDispatcher dispatcher = request.getRequestDispatcher("/servlets/counter");
if (dispatcher != null) {
out.println("<br>Number of visits: ");
request.setAttribute(Counter.ATTRIBUTE, Query.class.getName());
dispatcher.include(request, response);
}
out.println("</body>");
It is designed to include another servlet's response into the current servlet. Then, I have the other servlet called "Counter" which has this line:
if (counterName == null) counterName = (String)request.getAttribute(ATTRIBUTE);
So, when I run "Query" there is no output from "Counter". You can review the full project from this repository Thank you in advance!
I figured it out! Mistake was at the .getRequestDispatcher method. The parameter has to contain not servlet's class location, but it's mapping. Thanks to this post
I wrote a spring-mvc controller method to get an array of values in the request parameter.The method looks like below
/**
Trying to get the value for request param foo which passes multiple values
**/
#RequestMapping(method=RequestMethod.GET)
public void performActionXX(HttpServletRequest request,
HttpServletResponse response,
#RequestParam("foo") String[] foo) {
......
......
}
The above method works fine when the request url is in below format
...?foo=1234&foo=0987&foo=5674.
However when the request url is in below format the server returns 400 error
...?foo[0]=1234&foo[1]=0987&foo[2]=5674
Any idea how to fix the method to cater to the second format request url?
This is not possible with #RequestParam. What you can do is implement and register your own HandlerMethodArgumentResolver to perform to resolve request parameters like
...?foo[0]=1234&foo[1]=0987&foo[2]=5674
into an array. You can always checkout the code of RequestParamMethodArgumentResolver to see how Spring does it.
Note that I recommend you change how the client creates the URL.
The server is supposed to define an API and the client is meant to follow it, that's why we have the 400 Bad Request status code.
I resolved this issue using the request.getParameterMap().Below is code.
Map<String,String> parameterMap= request.getParameterMap();
for(String key :parameterMap.keySet()){
if(key.startsWith("nameEntry")){
nameEntryLst.add(request.getParameter(key));
}
}
I have a servlet which acts as a front controller.
#WebServlet("/*")
However, this also handles CSS and image files. How can I prevent this?
You have 2 options:
Use a more specific URL pattern such as /app/* or *.do and then let all your page requests match this URL pattern. See also Design Patterns web based applications
The same as 1, but you want to hide the servlet mapping from the request URL; you should then put all static resources in a common folder such as /static or /resources and create a filter which checks if the request URL doesn't match it and then forward to the servlet. Here's an example which assumes that your controller servlet is a #WebServlet("/app/*") and that the filter is a #WebFilter("/*") and that all your static resources are in /resources folder.
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());
if (path.startsWith("/resources/")) {
chain.doFilter(request, response); // Goes to default servlet.
} else {
request.getRequestDispatcher("/app" + path).forward(request, response); // Goes to your controller.
}
See also How to access static resources when mapping a global front controller servlet on /*.
I know this is an old question and I guess #BalusC 's answer probably works fine. But I couldn't modify the URL for the JSF app am working on, so I simply just check for the path and return if it is to static resources:
String path = request.getRequestURI().substring(request.getContextPath().length());
if (path.contains("/resources/")) {
return;
}
This works fine for me.