How can i use a Filter just for servlets and not for jsp?
url-patterns :
/* - this makes the container to call the filter for servlets as well as jsp.
*.jsp - this makes the container to call the filter only for jsp.
Is there any way it calls the filter only for servlets..
Since filter is mapped to URL and the mapping is always "positive", i.e. you cannot say "call this filter unless url is *.jsp) the only solution is create special URLs for either servlets or JSPs.
For example you can map all your servlets to URLs that end with *.do, e.g. create.do, delete.do etc.
<servlet-mapping>
<servlet-name>Create Servlet</servlet-name>
<url-pattern>/create.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Delete Servlet</servlet-name>
<url-pattern>/delete.do</url-pattern>
</servlet-mapping>
Then you can create filter and map it to *.do:
<filter-mapping>
<filter-name>actionsFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
It will work for all servlets (because they are mapped to *.do) and will not work for JSPs (because they are not mapped to *.do).
You can do this by adding a Dummy Filter that doesn't propagate to the FilterChain, i.e. not calling FilterChain.doFilter() in the Dummy Filter, but including the requestdispatcher for jsp files.
public class NOPDummyFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
req.getRequestDispatcher(req.getServletContext().getContextPath()
.substring(req.getServletContext().getContextPath().lastIndexOf('/') + 1)).include(request, response);
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
and in the web.xml:
<filter>
<filter-name>NOPDummyFilter</filter-name>
<filter-class>NOPDummyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>NOPDummyFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>MyRealServletFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
see this discussion: http://www.coderanch.com/t/169859/java-Web-Component-SCWCD/certification/Filter-has-Exclude-url-pattern
hope this helped.
And code:
// Check if request goto a Servlet
private boolean needFilter(HttpServletRequest request) {
//
// Servlet Url-pattern: /path/*
//
// => /path
String servletPath = request.getServletPath();
// => /abc/mnp
String pathInfo = request.getPathInfo();
String urlPattern = servletPath;
if (pathInfo != null) {
// => /path/*
urlPattern = servletPath + "/*";
}
// Key: servletName.
// Value: ServletRegistration
Map<String, ? extends ServletRegistration> servletRegistrations = request.getServletContext()
.getServletRegistrations();
// collection of all servlets in your webapp.
// containing *.jsp & *.jspx
Collection<? extends ServletRegistration> values = servletRegistrations.values();
for (ServletRegistration sr : values) {
Collection<String> mappings = sr.getMappings();
if (mappings.contains(urlPattern)) {
return true;
}
}
return false;
}
Related
My requirement is to call the services from two different modules.But, Some urls can allow both modules,some urls allow for specific to that module.
Below is my current configuration for achieving that
<servlet>
<servlet-name>animals</servlet-name>
<servlet-class>
org.glassfish.jersey.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.lion,com.dog</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>animals</servlet-name>
<url-pattern>/lion/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>animals</servlet-name>
<url-pattern>/dogs/*</url-pattern>
</servlet-mapping>
For example if I have a service called as 'barking' this service is located in com.dog package.Now i can call this service using two urls like below
/lions/barking
/dogs/barking
As per my requirement /lions/barking should show 404 error.But it gives the response.
But some url both should work.Irrespective of where the service is located.
/lions/eat
/dogs/eat
How to do the configuration to achieve that functionality
Any help will be greatly appreciated!!!!
Use a "http Servlet Request Filter" to customise and configure/serve the requests as per your business requirements.
Please find the sample code below:
public class RequestUrlFilter implements Filter {
private static List<String> validUrls = new ArrayList<>();
public void init(FilterConfig filterConfig) throws ServletException {
//Load the valid list of urls here
validUrls.add("/lions/eat");
validUrls.add("/dogs/eat");
validUrls.add("/dogs/barking");
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain)
throws IOException, ServletException {
if(validUrls.contains(((HttpServletRequest)request).getRequestURI()) {
filterChain.doFilter(request,response);
} else {
//Error Response
RequestDispatcher rd = (HttpServletRequest)request.getRequestDispatcher("Error.jsp");
rd.forward(request, response);
}
}
public void destroy() {
}
}
I am serving an angular page in a Java WAR in Glassfish.
I need to serve everything under public as a static file and all other requests should serve index.html.
Because it's Angular, it needs to serve index.html but still keep the end. So if you go to example.com/stuff it should load the index page and keep /stuff on the end.
I have this glassfish-web.xml right now, but I'm still getting a 404 for everything outside public.
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD
GlassFish Application Server 3.1 Servlet 3.0//EN"
"http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>DefaultServlet</servlet-name>
<servlet-class>
org.apache.catalina.servlets.DefaultServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DefaultServlet</servlet-name>
<url-pattern>*</url-pattern>
</servlet-mapping>
</glassfish-web-app>
Use a Serlvet Filter:
#WebFilter("/*")
public class MainFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String requestUrl = request.getRequestURL().toString();
if (validUrl(requestUrl)) {
//allowed, continue navigation
chain.doFilter(req, res);
} else {
//invalid URL, send back to index.html
String invaludUrl = retrieveInvalidPart(requestUrl);
response.sendRedirect(request.getContextPath() + "/index.html" + invaludUrl);
}
}
private boolean validUrl(String url) {
//implement how to validate the URL
}
private String retrieveInvalidPart(String url) {
//implement how to recognize the invalid part of the URL
}
}
Note that this problem is completely unrelated to GlassFish or any other application server.
If you also want/need to add the query string associated to the url in case of invalid request, you may retrieve it by using HttpServletRequest#getQueryString:
//invalid URL, send back to index.html
String invaludUrl = retrieveInvalidPart(requestUrl);
String queryString = request.getQueryString();
queryString = (queryString == null) ? "" : queryString;
response.sendRedirect(request.getContextPath() + "/index.html" + "?invalidUrl=" + invaludUrl + queryString);
More info:
StackOVerflow Servlet Filter Wiki
How can I get the request URL from a Java Filter?
In my program any url in the form of /Controller/* is redirected by my servlet mapping to Controller class.
I tried to add a filter for authantication, if user is not logged in and path is not /Controller/RegForm it's redirecting to /Controller/RegForm.
Problem is because my servlet mapping redirects to /Controller, filter always gets the /Controller as path.
How can I use both filter and the servlet mapping ?
This is my web.xml:
<filter>
<filter-name>AuthFilter</filter-name>
<filter-class>AuthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthFilter</filter-name>
<url-pattern>/Controller/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>Controller</servlet-name>
<servlet-class>Controller</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Controller</servlet-name>
<url-pattern>/Controller/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
my filter:
#WebFilter("/Controller/*")
public class AuthFilter implements Filter {
#Override
public void init(FilterConfig config) throws ServletException {
// If you have any <init-param> in web.xml, then you could get them
// here by config.getInitParameter("name") and assign it as field.
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
String path = ((HttpServletRequest) request).getServletPath();
if ((session != null && session.getAttribute("student") != null )||(excludeFromFilter(path))) {
chain.doFilter(req, res); // Log
}
else {
response.sendRedirect("/registration-war/Controller/RegForm"); // No logged-in user found, so redirect to login page.
}
}
private boolean excludeFromFilter(String path) {
if (path.equals("/Controller/RegForm")) {
return true; // add more page to exclude here
} else {
return false;
}
}
You use HttpServletRequest.getServletPath() which returns the servlet URL which is (according to your servlet mapping) "/Controller".
You want the path info not the servlet path:
Returns any extra path information associated with the URL the client sent when it made this request. The extra path information follows the servlet path but precedes the query string and will start with a "/" character.
So for example this will return "/RegForm" if your user requests the /Controller/RegForm page.
String pathInfo = HttpServletRequest.getPathInfo();
Hi there, I have created a Filter class and configure the web.xml as below:
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>my.web.auth.LoginFilter</filter-class>
<init-param>
<param-name>test-param</param-name>
<param-value>This param is for testing</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/html/test/*</url-pattern>
</filter-mapping>
When I access the URL http://{myJBoss}/html/test/index.htm ,
LoginFilter's init() is called but not the doFilter()
Here is the excerpt of my Filter class:
public void init(FilterConfig config) throws ServletException {
log.debug("[201207bb] init"); //******This line can be seen in log file
this.config = config;
String testParam = config.getInitParameter("test-param");
log.debug("test-param="+testParam); //******* This is output correctly too
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
log.debug("[201207bb] doFilter"); //*****This line didn't appear in log file
HttpServletRequest request = (HttpServletRequest) req;
//Get the IP address of client machine.
String ipAddress = request.getRemoteAddr();
//Log the IP address and current timestamp.
log.debug("IP "+ipAddress + ", Time " + new Date().toString());
chain.doFilter(req, res);
}
Does anyone has any idea why is this so?
I have tried on a jsp too, same result.
Problem solved.
url-pattern is incorrectly set.
init() is being called doesn't mean the url-pattern is set up correctly.
I am developing inherited jsp/java ee application and I would like to introduce Guice IoC container to my application. However, I found some obstacles. I can't translate web.xml entries into guice registrations if there are more then one routing to single servlet using different urls. Problem is with init-parameters.
Here are some extracts from my web.xml:
This one is unrelated to problem, but it is good example how we are using init parameters. Basically it maps users with different roles in systems to appropriate pages.
<!-- LIST INTERNSHIPS SERVLET -->
<servlet>
<servlet-name>ListInternships</servlet-name>
<servlet-class>pl.poznan.put.ims.controllers.ListInternships</servlet-class>
<init-param>
<param-name>CoordinatorPage</param-name>
<param-value>WEB-INF/pages/coordinator/listinternships.jsp</param-value>
</init-param>
<init-param>
<param-name>MentorPage</param-name>
<param-value>WEB-INF/pages/mentor/listinternships.jsp</param-value>
</init-param>
<init-param>
<param-name>AdministratorPage</param-name>
<param-value>WEB-INF/pages/administrator/listinternships.jsp</param-value>
</init-param>
<init-param>
<param-name>AllowedRoles</param-name>
<param-value>Coordinator, Mentor, Administrator</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ListInternships</servlet-name>
<url-pattern>/internships</url-pattern>
</servlet-mapping>
Those two are the troublesome ones:
<!-- CHANGE PASSWORD SERVLET -->
<servlet>
<servlet-name>ChangePassword</servlet-name>
<servlet-class>myapp.controllers.ContextForwarder</servlet-class>
<init-param>
<param-name>SharedPage</param-name>
<param-value>WEB-INF/pages/shared/password.jsp</param-value>
</init-param>
<init-param>
<param-name>AllowedRoles</param-name>
<param-value>*</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ChangePassword</servlet-name>
<url-pattern>/changepassword</url-pattern>
</servlet-mapping>
<!-- HELP SERVLET -->
<servlet>
<servlet-name>Help</servlet-name>
<servlet-class>myapp.controllers.ContextForwarder</servlet-class>
<init-param>
<param-name>SharedPage</param-name>
<param-value>WEB-INF/pages/help/help.jsp</param-value>
</init-param>
<init-param>
<param-name>AllowedRoles</param-name>
<param-value>*</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Help</servlet-name>
<url-pattern>/help</url-pattern>
</servlet-mapping>
Here is my servlet:
#Singleton
public class ContextForwarder extends HttpServlet {
private static final long serialVersionUID = 1L;
private final IUserDao dao;
#Inject
public ContextForwarder(IUserDao dao) {
this.dao = dao;
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//trying to get rid of statics, using Ioc
Validator.checkUserLoggedIn (request);
Validator.checkUserAuthorized(this, request);
User currentUser = UserManager.getCurrentUser(request);
//pick matching page for user
String userViewPage = ServletUtils.getUserURL(this, currentUser, "Page");
try {
dao.openSession();
dao.beginTransaction();
currentUser = UserManager.reloadCurrentUser(request, dao);
ServletUtils.forward(request, response, userViewPage);
dao.commit();
}
catch(ServletException e) {
dao.rollback();
throw e;
}
catch(Exception e) {
dao.rollback();
throw new ServletException(e);
}
finally {
dao.closeSession();
}
}
}
public class ServletUtils {
public static void forward(HttpServletRequest request, HttpServletResponse response, String location)
throws ServletException, IOException {
RequestDispatcher view = request
.getRequestDispatcher( response.encodeRedirectURL(location) );
view.forward(request, response);
}
public static String getUserParameter(GenericServlet servlet, User user, String suffix) {
return servlet.getInitParameter( user.getRoles() + suffix );
}
public static String getUserURL(GenericServlet servlet, User user, String suffix)
throws ResourceNotFoundException {
String URL = getUserParameter(servlet, user, suffix);
if(URL == null) {
URL = servlet.getInitParameter("Shared" + suffix);
if(URL == null)
throw new ResourceNotFoundException(suffix);
}
return URL;
}
public static void redirect(HttpServletRequest request, HttpServletResponse response, String location)
throws ServletException, IOException {
response.sendRedirect( response.encodeRedirectURL(location) );
}
}
When i try to translate it into guice (and then register this module):
public class MyServletModule extends ServletModule
{
#Override
protected void configureServlets() {
configureHelp();
configurePassword();
}
private void configureHelp()
{
Map<String, String> params = new HashMap<String, String>();
params.put("SharedPage", "WEB-INF/pages/shared/help.jsp");
params.put("AllowedRoles", "*");
serve("/help").with(ContextForwarder.class, params);
}
private void configurePassword()
{
Map<String, String> params = new HashMap<String, String>();
params.put("SharedPage", "WEB-INF/pages/shared/password.jsp");
params.put("AllowedRoles", "*");
// it's routing correctly to servlet, but it uses params from first registration,
// so that routing to jsp page is incorrect
serve("/changepassword").with(ContextForwarder.class, params);
}
}
The problem is that guice creates ContextForwarder servlet as a singleton with init parameters from the first registered method and then regardless of the request url it has parameters from the first registration. Is there any other solution to route user to different sites considering current user role? Is it possible to configure the same servlet class with two different configurations?
I have found a solution, however I am not fully satisfied with it. I found out that, in solution without guice, web container (tomcat) creates two separate servlets using the same servlet class and injecting different init parameters. Guice by default restricts servlets to be singletons, so to copy default behaviour from web.xml solution I needed to find a way to create two instance of the same class and register it twice with different parameters. I solved this by creating two sub-classes to my servlet class, both with empty body, then I registered them with different parameters.
This solution works, but it involve creating empty-body sub-classes which I am not satisfied with. It's not a problem when I got two sub-classes, but with more of them code is becoming cumbersome.