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.
Related
I have been trying to get parameters from my web.xml file from within my Jakarta JAX-RS resource. My web.xml is as follows:
<web-app>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>terrible.package.name</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/api/v1/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>max-customers-size</param-name>
<param-value>10</param-value>
</context-param>
</web-app>
In my test setup, I am running my web app with Jetty:
public static void main(String[] args) throws Exception {
Server server = new Server(8080);
WebAppContext ctx = new WebAppContext("target/the-finished-servlet.war", "/");
server.setHandler(ctx);
server.start();
}
And I have the following user resource defined using jakarta:
#Path("user")
public class UserResource {
ServletContext context;
#Context
public void setServletContext(ServletContext context) {
this.context = context;
System.out.println("setting to: " + context);
}
#GET
#Path("/list")
#Produces(MediaType.APPLICATION_JSON)
public Response getListOfAllUsers(final #Context HttpHeaders hdrs) throws SQLException {
System.out.println(context.getInitParameter("max-customers-size"));
return Response.ok("{}").build();
}
}
The context is always null, which makes absolutely no sense. The setServletContext method is called, and the parameter is null. I've tried using #Context on a constructor parameter, I've tried it on my context field, and I've tried it in the getListOfAllUsers method. None of them work.
I just want to configure my servlet (for MySQL database path and user, in this example I'm testing with max-customers-size, which doesn't matter though, because my context is null either way). Is there an easier way to get custom config data into my servlet? I want the user of my resulting war file to be able to supply things like the database port. Why isn't ServletContext working, and if there is an easier way to make my servlet configurable, how do I do that?
Typically a database (DataSource) for Servlet is configured via JNDI (the definition exists on the server JNDI context, and the webapp JNDI context contains a hardcoded reference to the server level location)
Your server level will typically have an XML that defines the DataSource as a org.eclipse.jetty.plus.jndi.Resource against the server level context.
And your webapp's WEB-INF/web.xml contains the <resource-ref> back to that server level location.
Your code then uses the InitialContext on JNDI to access this already defined DataSource.
This has the added bonus that the datasource can be any JDBC compatible implementation, and even include complex configurations like a Connection pool implementation (eg: c3p0) in front of your JDBC DataSource.
For unit testing, you'll set it up like this ...
JNDI Lookup Failing For Embedded Jetty Server
For standard webapp deployment in a standalone Jetty container, you'll set it up like this ...
Declaring JNDI Resources
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().
I've created a RestEASY Interceptor to allow me to set header values on the HTTP response after my webservice call has completed. My code looks like this...
#Provider
#ServerInterceptor
#Precedence("HEADER_DECORATORS")
public class MyHeaderInterceptor implements
MessageBodyWriterInterceptor {
#Override
public void write(MessageBodyWriterContext context) throws IOException,
WebApplicationException {
....do stuff here....
}
}
When I make a call to my service, however, the interceptor is never called. I see the webservice call complete successfully, but none of the code in my interceptor is ever executed. Is there anything beyond this that I need to do to register my interceptor? Does it have to be declared anywhere else? Are there any special web.xml parameters that need to be included?
You have to list the interceptor in the resteasy.providers context-param of your web.xml. Adding annotation to the Interceptor class is not enough.
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>org.resteasy.test.ejb.exception.FooExceptionMapper</param-value>
</context-param>
As for Resteasy 2.x you could also have it to automatically scan WEB-INF/lib jars and WEB-INF/classes directory for both #Provider and JAX-RS resource classes (#Path, #GET, #POST etc..) and register them:
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
Or can have Resteasy to Scan for #Provider classes and register them :
<context-param>
<param-name>resteasy.scan.providers</param-name>
<param-value>true</param-value>
</context-param>
In both cases you dont have to list the interceptors explicitly into web.xml.
Otherwise if both context-params 'resteasy.scan' and 'resteasy.scan.providers' are not enabled (and they are disabled by default) you may want to specify a comma delimited list of fully qualified #Provider class names you want to register inside the 'resteasy.providers' element:
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>com.test.Interceptor1,com.test.Interceptor2</param-value>
</context-param>
That's taken from the doc : http://docs.jboss.org/resteasy/docs/2.3.3.Final/userguide/html_single/index.html#d0e72
DD elements <context-param> and <init-param> both can be retrieved by the getInitParameter() method, in the servlet code.
Now the question is, how does it differentiate <context-param> and <init-param>?
Servlet init parameters are for a single servlet only. Nothing outside that servlet can access that. It is declared inside the <servlet> tag of Deployment Descriptor, on the other hand context init parameter is for the entire web application. Any servlet or JSP in that web application can access context init parameter. Context parameters are declared in a tag <context-param> directly inside the <web-app> tag.
The methods for accessing context init parameter is
getServletContext().getInitParameter("name");
whereas the method for accessing servlet init parameter is
getServletConfig().getInitParameter("name");
As explained by Adeel Ansari, here, it depends on what object are you invoking the method getInitParameter() in the servlet code.
All servlets extends from and hence are instance of GenericServlet.
.
DD elements <context-param> can be retrieved by:
ServletContext context = this.getServletContext();
String paramValue = context.getInitParamter("paramName");
.
DD elements <init-param> both can be retrieved by:
ServletConfig config = this.getServletConfig();
String paramValue = config.getInitParamter("paramName");
Also note that since GenericServlet class implements ServletConfig interface, your servlet class is also ServletConfig (implies this = this.getServletConfig() ). Hence you can also get DD elements <init-param> directly by:
String paramValue = this.getInitParamter("paramName");
.
You can try this by having same param-name in both DD elements with different values and then print it in your servlet.
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>