Init filter inside of servlet initializtion - java

I have a Servlet Filter and due to my business logic Filter uses some variables that are initializing in when servlet's method init() invoke. So the question is: is any possibility to init filter after servlet. My Web.xml is next:
...
<servlet>
<servlet-name>CommonsServlet</servlet-name>
<servlet-class>com.promptlink.dslib.gwt.common.server.rpc.CommonsServletImpl</servlet-class>
</servlet>
...
<filter>
<filter-name>CommonServletFilter</filter-name>
<filter-class>com.promptlink.dslib.gwt.common.server.httpListeners.CommonServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CommonServletFilter</filter-name>
<url-pattern>/*</url-pattern>
<servlet-name>CommonsServletImpl</servlet-name>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
...
Maybe is any way to configure filter not in xml? I've heart that it is possible to add filter to ServletContext, but i need to add a mapping to filter too

Filters are initialized before servlets, see here for the details.
But you can create a ServletContextListener which is loaded at application startup before any filter or servlet, initialize your variables in the listener, and let your serlvets and filters then use the already initialized variables.
The listener can also add your servlets and filters programmatically, see ServletContext.addFilter() and ServletContext.addServlet().

Related

Loading context in web.xml

What is the difference between loading context in context param and loading it in init-param of Dispatcher Servlet.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
vs
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value> /WEB-INF/mvc-config.xml </param-value>
</init-param>
What i understood is context-param is loaded by context listener and should only contain middle tier beans. Where as Dispatcher Servlet in its init method should load web tier beans. Is this understanding correct? Why do we load 2 things seperately?
<context-param>
Is written outside <Servlet> tag and is inside <webapp> tag.
The values decalred will be available to the whole application
Any servlet in the application (declared in the web.xml) can access the values
So we use this when we want to share the the same set of values across the servlet in the application such as Data base configuration details.
You can use public String getInitParameter(String name) method of ServletContext interface to get value.
getServletContext() method of ServletConfig interface returns the object of ServletContext.
getServletContext() method of GenericServlet class returns the object of ServletContext.
Example 1 : ServletContext application=getServletConfig().getServletContext();
Example 2 : ServletContext application=getServletContext();
<init-param> .
Is written inside <Servlet> tag.
The values declared will be available only to the servlet.
You can use public String getInitParameter(String name) method of ServletConfig interface to get value.
getServletConfig() method of Servlet interface returns the object of ServletConfig.
Example : ServletConfig config=getServletConfig();
In the context-param "contextConfigLocation" you should include your application contexts, as you have already said middle tier beans, like: services, datasource...
The Spring DispatcherServlet will look for config files in WEB-INF/servletName-servlet.xml. Using the init-param you can change this default behaviour. The servlets contexts (web contexts) are isolated but might hold the application contexts as parent. You can use both or one of them independently.

Filter only specific type of request

Recently I'm developing an app in which we need to filter just specific type of requests. For example only GET or POST. It is easy to check type in code and simply forward to the next filter in doFilter method, but I wonder if there is some way to define it in the web.xml file? For example something like:
<filter>
<filter-name>SomeFilter</filter-name>
<filter-class>org.src.SomeFilter</filter-class>
<filter-type>POST</filter-type> <<<<< this
</filter>
<filter-mapping>
<filter-name>SomeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
No there is no such configuration in deployment descriptor, you can use code to determine request type
httpRequest.getMethod();
I think there is no such thing to configure in web.xml.But you can use getMethod() method of ServletRequest object in Your filter class and design your logic there in doFilter() method.

Adding multiple servlets in single web.xml

I am trying to run two Servlet-class in a single web.xml but its not working, each servlet-class works fine independently.
web.xml:
<servlet>
<servlet-name>spring-ws</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>transformWsdlLocations</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-ws</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>240</session-timeout>
</session-config>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-ws-servlet.xml
/WEB-INF/health-page-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>health-page</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>health-page</servlet-name>
<url-pattern>/health.htm</url-pattern>
</servlet-mapping>
Do let me know if you can figure something wrong that i am doing.
I tried the below link but it doesnt work for me
Can I use Spring MVC and Spring WS in one single application?
This isn't going to work. The one which is mapped on /* overtakes all requests. You need to map it on / instead so that it will only intercept on requests which are not matched by all other existing servlets (including the JSP servlet which is implicitly mapped on *.jsp and all "normal" static resources like CSS/JS/image files!). See also Difference between / and /* in servlet mapping url pattern.
If being able to serve static resources is also required, then better map it on a more specific URL pattern like /ws/* and create a Filter which checks the request URI and then forwards accordingly. That filter can in turn safely be mapped on /*. See also this answer for a more concrete code example: How to access static resources when mapping a global front controller servlet on /*.
I am using Java configuration in my project and following code works fine for the same purpose:
public class Initializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(ApplicationConfiguration.class);
ctx.setServletContext(servletContext);
MessageDispatcherServlet messageDispatcherServlet = new MessageDispatcherServlet();
messageDispatcherServlet.setApplicationContext(ctx);
messageDispatcherServlet.setTransformWsdlLocations(true);
Dynamic dynamic = servletContext.addServlet("messageDispatcherServlet", messageDispatcherServlet);
dynamic.addMapping("/ws/*");
dynamic.setLoadOnStartup(1);
dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
dynamic.addMapping("/");
dynamic.setLoadOnStartup(1);
}
}
you have a mapping for /* in the spring-ws section which is getting the request. you need to
come up with a different strategy... Try putting the /health.htm before the /* mapping.

How to allow access to static content when having default servlet

I map all requests to /* to a specific servlet.
My static content is hidden by this configuration.
How can i allow access to specific files (such as crossdomain.xml)?
When you map /* to a specific servlet, all requests will be forwarded to that servlet, unless you provide a more explicit mapping to another servlet.
That is, if you have /* mapped to ServletA, and /static/* mapped to ServletB, then following Servlets will get called.
http://localhost:8080/abc.jpg -> ServletA
http://localhost:8080/static/abc.jpg -> ServletB
http://localhost:8080/xyz/abc.jpg -> ServletA
So one option you have is to write a Servlet to handle the static content, which will grab the file and return it as response. You can map that servlet to a prefixed by something like /static/*. This requires that all URL references to your static files to be updated to contain this '/static' part.
If that is not feasible for you, then probably you can use the same servlet, but mapped to multiple URL patterns (probably by extension) as follows.
<servlet>
<servlet-name>static-servlet</servlet-name>
<servlet-class>xxx.yyy.StaticServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>static-servlet</servlet-name>
<url-pattern>*.xml</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>static-servlet</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
If you want this to be fine-grained to the level of each file, you can map the servlet to your file URL as well.
Cookbook:
Map your controller Servlet on a more specific url-pattern like /app/*.
Put all the static content in a specific folder like /static.
Create a Filter which is mapped on /* which transparently continues the chain for any /static requests and dispatches other requests to /app.
So, in a nutshell:
<filter>
<filter-name>filter</filter-name>
<filter-class>com.example.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>controller</servlet-name>
<servlet-class>com.example.Controller</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>controller</servlet-name>
<url-pattern>/pages/*</url-pattern>
</servlet-mapping>
with the following in filter's doFilter():
String uri = ((HttpServletRequest) request).getRequestURI();
if (uri.startsWith("/static/")) {
chain.doFilter(request, response); // Goes to default servlet.
} else {
request.getRequestDispatcher("/app" + uri).forward(request, response);
}
No, you do not end up with extra /app path in the URL. It's fully transparent. Make if necessary "/static" and/or "/app" an <init-param> of the filter.
And one more(a direct) servlet mapping like this<servlet-mapping><servlet-name>StaticContentServlet</servlet-name><url-pattern>/crossdomain.xml</url-pattern></servlet-mapping>
probably you can put your static content under different URL like /static/* and then map this URL to a Servlet which responds with the static content.

Accessing context parameters within Servlet Filters

Thanks to everyone in advance,
I am trying to access any context parameters in the web.xml from within a servlet filter. Below is a portion from my web.xml file. I have verified that the context-param node is accessible via a jsp page using out.print(getServletContext().getInitParameter("error"));.
<filter>
<filter-name>prePost</filter-name>
<filter-class>MyFilter</filter-class>
<init_param>
<param_name>error</param_name>
<param_value>/test.jsp</param_value>
</init_param>
<filter-mapping>
<filter-name>prePost</filter-name>
<url-pattern>*.jsp</url-pattern>
<context-param>
<description>Error Handler</description>
<param-name>error</param-name>
<param-value>/test.jsp</param-value>
In my filters doFilter when I output this.filterConfig.getInitParameter("error"), I always get null. In my filters init() I am setting this.filterConfig with the passed in FilterConfig.
Thanks,
Sam
You're using underscores rather than hyphens for "param-name" and "param-value". Your config should look like this:
<init-param>
<param-name>error</param-name>
<param-value>/test.jsp</param-value>
</init-param>

Categories

Resources