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.
Related
I have this configuration:
<servlet-mapping>
<servlet-name>RestletServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
I need to exclude "/xrebel" since Restlet is catching this path--and can't access XRebel. However I need to keep the url-pattern to be /*
What can be done to be able to access such /xrebel path
I had the same issue while developing Web Services last year. But after doing a lot of research I found that there was no easy to do solution for the problem.
Instead the best approach I found was to use prefix servlet URL.
So for all the mappings which you want to be handled by RestletServlet add a prefix to url something like /rest/*
Hope this helps.
One possible solution is to create a filter with the same url pattern to intercept the request.
In your filter you can check if the pattern is equal to /xrebel and then handle the request however you want to.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String requri = ((HttpServletRequest) request).getRequestURI().substring(((HttpServletRequest) request).getContextPath().length() + 1);
System.out.println(requri);
if(requri.equals("/xrebel")){
//do something else
}else{
chain.doFilter(request, response); //continue normally
}
}
As per the security of web application x-power-by should set to empty when it displays in response header..
In our application we did this by implementing a filter.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
// App specific logic...
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("X-Powered-By","");
chain.doFilter(request, response);
httpResponse.setHeader("X-Powered-By"," ");
}
It is showing blank value in response header for x-power-by when hitting the URL, That's well and good but in our application when we hit the URL with query string appended with the URL then for the first request it shows :
x-power-by= JSF1.2
We have also commented out the below portion of x-power-by in web.xml as our application use jboss 5.0.1.
<filter>
<filter-name>CommonHeadersFilter</filter-name>
<filter-class>
org.jboss.web.tomcat.filters.ReplyHeaderFilter</filter-class>
<!--
<init-param>
<param-name>X-Powered-By</param-name>
<param-value>Servlet 2.5; JBoss-5.0/JBossWeb-2.1</param-value>
</init-param>
-->
</filter>
But doing all the two things mention above I am getting x-power-by displayed in the response header when I hit the URL with query string appended for the 1st time.
URL like:
https://example.com?html="abcd",p_ab="shdhsgdhs"
Don't know how to resolve it,any help is highly appreciated.
1) Add following entry to your application web.xml.
<context-param>
<param-name>com.sun.faces.sendPoweredByHeader</param-name>
<param-value>false</param-value>
</context-param>
2) I don't think you need any filter to overwrite this header (based on jboss documentation).
I have a gateway sevlet that forward users to many servlets that processes tasks.
each users must go first through the gateway servlet then it forwards them to the proper servlet.
I create a RequestDispatcher and execute it's forward function to the proper servlet.
the problem is that all the servlets are publicly available so they user can actually go and execute any servlets they want.
I want to allow access only to the gateway servlet and to restrict access to all others. but of course to allow the gateway to forward to the servlets.
how can it be done?
thank you!
using apache tomcat 7
Using filter to check that the current user is logged in, you'll need to write the method userIsLoggedIn() yourself, by checking session attributes:
public class LoginFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
if (userIsLoggedIn()) {
//process request normally, pass up the filter chain to the servlet:
chain.doFilter(req, res);
} else {
//go to login screen instead
RequestDispatcher dispatcher = getRequestDispatcher("login");
dispatcher.forward( request, response );
}
}
}
In you web.xml, you'll need to declare your filter:
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>
com.foo.LoginFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
We have a Java EE 6 web application with JSF 2.0 running on Glassfish 3.1.
There we encountered a strange bug: the Mime type of the response header send by Glassfish to the client depends on the order of the allowed Mime types in the request header send by the Browser. So in some cases (depending on the browser), the Mime type of the response is wrong, resulting in a broken html page.
But it would take pretty long to explain that thing. So to workaround this problem we now want to do just one thing:
Force the response header type for the whole web-application to "text/html".
Currently, we do that with a Servlet Filter configured in the Web.xml:
#WebFilter("/BaseFilter")
public class BaseFilter implements Filter {
public BaseFilter() {
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
response.setContentType("text/html;charset=UTF-8");
chain.doFilter(request, response);
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
configuration in web.xml:
<filter>
<filter-name>BaseFilter</filter-name>
<filter-class>com.company.web.filter.BaseFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>BaseFilter</filter-name>
<url-pattern>/*</url-pattern>
<!-- these patterns should match cached resources -->
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
So my question is, is there a better way to enforce a specific response header, especially by just configuring it instead of implementing a ServletFilter?
Is there a Glassfish option to do that?
You can specify it in the default template by the contentType attribute of the <f:view>.
<f:view contentType="text/html">
I have an apache webserver that is used to serve php and static web files. In order to use active directory authentication i've written some code that can connect to AD through JNDI and authenticate usernames passwords and groups. What I would like is to map all requests to pages in apache through my servlet in order to make sure that a valid session is present and then if they have to login again that they have the correct AD group to visit a particular url. My issue is that when I map my servlet to every url with /* it cannot forward requests to the actual pages that I'm trying to get. It just keeps forwarding the request to my servlet and calling its doGet method till a servlet exception occurs. I want the functionality of a transparent proxy but I cannot seem to get that from this. Does anyone have any concrete examples of a transparent proxy servlet or know a way to do this with servlets. The forwarding functionality of a servlet seems to make this a perfect vehicle for doing it but I seem to be stuck.
Filter code
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse res = (HttpServletResponse)response;
boolean authenticated = false; //should be false when testing is done.
//skip if its the login page
if(req.getRequestURI().equals("/auth/login.jsp") || authenticated){
chain.doFilter(req, res);
}else{
req.setAttribute("protectedUrl", req.getRequestURI());
res.sendRedirect("/auth/login.jsp");
}
}
Web.xml
(snip)
<filter-mapping>
<filter-name>SessionFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
Because the servlet is mapped on /*, the RequestDispatcher#forward() will call it again, resulting in an infinite loop and finally a StackOverflowError (or some other exception depending on the servletcontainer in question which might have some recursion prevention builtin which kicks in after a certain amount of recursive calls).
After all, the Servlet is not entirely the right tool for the job, you'd rather like to use a Filter here. Implement javax.servlet.Filter and do the same job in doFilter() method. It won't call itself recursively when mapped on /* since it by default listens on requests only, not on forwards or includes.