At the moment I am trying to make my own canonical links in Java web.
I got this in my web.xml
<servlet-mapping>
<servlet-name>ControllerServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
ControllerServlet will call a factory that will use the getPathInfo() to call the correct class to handle this. The method that will handle the requests looks like
public void handleRequest(HttpServletRequest request, HttpServletResponse response) {
try {
RequestDispatcher view = request.getRequestDispatcher("../Overview.jsp");
view.forward(request, response);
} catch (Exception ex) {
System.out.println("error");
}
}
Now when I want to visit my page I will surf to
http://localhost/firstfolder/overview
The pathinfo I get is /firstfolder/overview, this redirects correctly to /Overview.jsp but after that it keeps redirecting to /Overview.jsp and ultimately crash. Leaving the end user with an empty page. Any idea how I can stop this unlimited looping and just serve the page?
Related
I've asked a question before about clean urls in java/jsp website and I got answer of it that I will need to configure my web.xml file like this
<servlet>
<servlet-name>yourjsp</servlet-name>
<jsp-file>/yourjsp.jsp</jsp-file> // here you can give jsp location
</servlet>
<servlet-mapping>
<servlet-name>yourjsp</servlet-name>
<url-pattern>/yourjsp</url-pattern>
</servlet-mapping>
So my question is that do I really have to map every URL or pattern in web.xml file?
What If I am developing a website which has USERs (NOT A SOCIAL NETWORK for GOD'S SAKE) but some type of community/forum system then I would like to use domain/UERnAME or domain/QUESTION or domain/question/what-ever-your-question-is etc, so any suggestion for that? And I want to clarify that I am still learning JAVA/JSP development and I'd like to learn it at beginner level of me.
Thank you all for helping me.
After Servlet 3.0, you don't need to use the web.xml file to map the URL to the desired resource/page.
You can do something like this:
#WebServlet("/UserController")
public class UserController extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/test.jsp");
rd.forward(request, response);
}
}
Where the URL would be http://your-domain/UserController
You can read a bit more about it here: http://java.dzone.com/articles/checking-out-what-new-servlet
I am wondering if it is possible to dispatch a request from a servlet to a Jersey (JAX-RS implementation) resource class. I am trying to do it but it doesn't seem to work and according to my logging, the jersey resource is never reached.
Code examples are below. Is what I'm trying to do impossible for some reason?
Please note, the Jersey resource works correctly when I access it directly in a web browser via the address bar.
Also please note that 'RequestDispatcher.forward()' works as expected. It is just 'include' that doesn't.
The servlet
//The Jersey dispatcher url-filter is set to '/api/*'
String servletID = "/api/items";
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(servletID);
dispatcher.include(request, response);
The Jersey resource
#GET #Path("/items")
#Produces ({MediaType.TEXT_XML})
public JAXBElement<Items> getItems(#PathParam("project") String project) throws IOException, JAXBException {
log.debug("reached getItems");
//Omitted code that returns 'Items' object wrapped in JAXBElement
}
Relevant parts of web.xml
<servlet>
<servlet-name>jerseyDispatcher</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>uk.co.web.api.resource</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>jerseyDispatcher</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
It is possible you forward the request.
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
RequestDispatcher requestDispatcher = null;
requestDispatcher = httpServletRequest.getRequestDispatcher("/items");
dispatcher.forward(request, response);
return;
However note if you receive a GET request and try to forward to a POST resource,
It will throw a 405 error.
Edit:
Let me understand what you are trying to achieve, if you need write content to response output stream you could use jersey Resource Filter.
public class YourResourceFilter implements ResourceFilter
{
public ContainerRequestFilter getRequestFilter()
{
return new ContainerRequestFilter()
{
#Override
public ContainerRequest filter(ContainerRequest containerRequest)
{
//Pre- editing the request
return containerRequest;
}
};
}
#Override
public ContainerResponseFilter getResponseFilter()
{
return new ContainerResponseFilter()
{
#Override
public ContainerResponse filter(ContainerRequest containerRequest, ContainerResponse containerResponse)
{
// after the request has been completed by your jersey resource
return containerResponse;
}
};
}
}
I got it to work, sort of (Jersey 2.13) by configuring Jersey as a filter, and not a servlet, in web.xml. Then, you can tell the container to apply the filter to included requests too:
<filter-mapping>
<filter-name>Jersey Web Application</filter-name>
<url-pattern>/api/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
RequestDispatcher.include will then work for request handled by Jersey, too. There's a caveat, though. Jersey calls response.getOutputStream, so all output must be performed through said output stream - this rules out JSP pages, that use response.getWriter instead. So, unless you figure out how to work around the problem, forget about including a Jersey resource in a JSP page or, vice versa, including the result of evaluating a JSP as part of a REST response.
I would like some help in understanding a particular behaviour of java Filters: I wrote a simple Filter which gets all user requests and, if a non-logged user requires a restricted resource, the filter forwards user to the home page. Here is my code:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
// place your code here
HttpServletRequest req = (HttpServletRequest) request;
String uri = req.getRequestURI();
System.out.println("\n\nFILTERING...\n\n");
//Se la risorsa appartiene all'area ristretta e l'utente non รจ
//loggato lo sbatto fuori
if(uri.contains("restricted") && (req.getSession(false) == null || req.getSession(false).getAttribute("user") == null)) {
System.out.println("\n\nCannot access\n\n");
//((HttpServletResponse) response).sendRedirect("/Hotel/index.jsp");
req.getRequestDispatcher("/index.jsp").forward(request, response);
}
else {
// pass the request along the filter chain
System.out.println("\n\nNext step\n\n");
chain.doFilter(request, response);
}
}
And the mapping in the web.xml:
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>mycontroller.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
What it is strange to me is that, if I ask a restricted resource via URL, the doFilter method is called several times before moving to the home (the server logs 'FILTERING... Cannot access' 4,5 times).
I'm using Tomcat 7.
Can someone help me to understand? Thanks a lot
You've mapped the filter on /*. It will thus intercept on every single HTTP request. Not only HTML/JSP pages, but also static resources like CSS, JS and image files. Apparently you've requested a HTML/JSP page which in turn references several CSS, JS and/or image files.
Your check in the filter is also pretty poor. You should rather map the filter on /restricted/*.
<url-pattern>/restricted/*</url-pattern>
Then remove that URI check from the filter's code. If you put those static resources outside that map, e.g. in /static or /resources, etc, then the filter won't be invoked for them.
To improve my java skills, I'm trying to build a simple j2ee framework (MVC).
I built it to handle every request in a FrontServlet. Here is the mapping that I used :
web.xml :
<servlet>
<servlet-name>Front</servlet-name>
<servlet-class>test.FrontServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Front</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
My problem is that when I forward the request from the FrontServlet to a JSP, obviously, the JSP request is handle by the FrontServlet and the view isn't rendered.
How can I resolve this problem by keeping the url-pattern "/*" ?
Is there a way to render a JSP in a Servlet without performance losses ?
Thanks in advance for your reply !
Solution 1 (#Bryan Kyle)
I'm trying to follow your advise. I created this filter :
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest req = (HttpServletRequest) request;
if(!req.getRequestURL().toString().endsWith("jsp"))
{
// I changed the servlet url-pattern to "/front.controller"
req.getRequestDispatcher("/front.controller").forward(req, response);
/*chain.doFilter(req, resp);*/
}
}
<filter>
<filter-name>Filter</filter-name>
<filter-class>test.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Is it right?
Thanks !
A Filter is an inappropriate solution for a front controller approach.
You want to refine the url-pattern of your servlet so that it matches e.g. /pages/* or *.do. You don't want your front controller to kick in on irrelevant requests like CSS/JS/images/etc. To take /pages/* as an example, assuming that you've a JSP in /WEB-INF/foo.jsp, then the following in a servlet
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF" + request.getPathInfo() + ".jsp").forward(request, response);
}
should display the JSP in question on http://localhost:8080/contextname/pages/foo.
See also:
Design patterns in Java web applications
Hidden features of JSP/Servlet
I think the problem here might be that you're using a Servlet instead of a ServletFilter.
A ServletFilter, as the name suggests filters requests by providing pre- and post-processing on the request. You'd probably want to use a Filter if you needed to do something like the following:
Provide security checks across an entire application
Set request properties that are picked up by a servlet or jsp
Compress a response
Log timing information
Etc.
Have a look at the documentation about Servlet Filters.
I am using
<url-pattern>/*</url-pattern>
to map all the requests to one sevlet,where i do all the authentication work.
but I want to skip some static content (like css files).so I tried fowrding them from
that sevlet to where the resource file is
if(isResourceFile){
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("static/" + fileName);
dispatcher.forward(request, response);
}
but this will start a infinite loop because this will again call the same sevlet
is there any way to work around this without mapping all the resource(css) files in web.xml?
The url-pattern of /* is better to be used exclusively by Filters, not Servlets. Put all your static files in a certain folder (maybe covered by the url-pattern of a more effective FileServlet?) and let the Filter check it.
E.g. (pseudo)
public void doFilter(request, response, chain) {
if (requestURI.startsWith("/static")) {
chain.doFilter(request, response); // Just continue. Do nothing.
} else {
request.getRequestDispatcher("/pages").forward(request, response); // Forward to page controller.
}
}
Hope this helps.
Assuming that you're looking to authenticate just JSP files, you could change the URL:
/*.jsp
I think it's a better idea to handle your authentication using a filter rather than a servlet. And in a production environment, you should use a front-end webserver for static content.
In case you cannot use a filter and you have to use a wildcard '*' in the mapping without a extension like '.jsp' then then this could work for you:
if(isResourceFile){
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/static/" + fileName);
dispatcher.forward(request, response);
return;
}
Adding the '/' in the beginning of the static directory will give it root context.