How to pass a reference when initializing a servlet - java

How would I go about passing a reference to the initialization of a servlet?
So, let's say I have something like this in my web.xml:
<servlet>
<servlet-name>RestTestServlet V3.1</servlet-name>
<servlet-class>com.xxx.servlet.RestTestServlet</servlet-class>
<init-param>
<param-name>serviceConsumerKey</param-name>
<param-value>com.xxx.oauth.ConsumerKey</param-value>
</init-param>
</servlet>
When I try to get the parameter, of course I just get the literal string value ("com.xxx... etc).
The com.xxx.oauth.ConsumerKey is a string bean I pull from JNDI, but I'm not sure how to get the servlet to be aware of it. I'm using Spring.
Is there a way to do this via the web.xml? If not, how would you go about doing what I'm trying to do?

The normal Spring approach would be to not write your own servlets, but rather use the Spring WebApplicationCOntext together with a DispatcherServlet. I.e., your servlet would be replaced by a spring bean, configured to handle certain requests and injected with the JNDI object.

Related

Servlet crashes jsp layout [duplicate]

The familiar code:
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
My understanding is that /* maps to http://host:port/context/*.
How about /? It sure doesn't map to http://host:port/context root only. In fact, it will accept http://host:port/context/hello, but reject http://host:port/context/hello.jsp.
Can anyone explain how is http://host:port/context/hello mapped?
<url-pattern>/*</url-pattern>
The /* on a servlet overrides all other servlets, including all servlets provided by the servletcontainer such as the default servlet and the JSP servlet. Whatever request you fire, it will end up in that servlet. This is thus a bad URL pattern for servlets. Usually, you'd like to use /* on a Filter only. It is able to let the request continue to any of the servlets listening on a more specific URL pattern by calling FilterChain#doFilter().
<url-pattern>/</url-pattern>
The / doesn't override any other servlet. It only replaces the servletcontainer's built in default servlet for all requests which doesn't match any other registered servlet. This is normally only invoked on static resources (CSS/JS/image/etc) and directory listings. The servletcontainer's built in default servlet is also capable of dealing with HTTP cache requests, media (audio/video) streaming and file download resumes. Usually, you don't want to override the default servlet as you would otherwise have to take care of all its tasks, which is not exactly trivial (JSF utility library OmniFaces has an open source example). This is thus also a bad URL pattern for servlets. As to why JSP pages doesn't hit this servlet, it's because the servletcontainer's built in JSP servlet will be invoked, which is already by default mapped on the more specific URL pattern *.jsp.
<url-pattern></url-pattern>
Then there's also the empty string URL pattern . This will be invoked when the context root is requested. This is different from the <welcome-file> approach that it isn't invoked when any subfolder is requested. This is most likely the URL pattern you're actually looking for in case you want a "home page servlet". I only have to admit that I'd intuitively expect the empty string URL pattern and the slash URL pattern / be defined exactly the other way round, so I can understand that a lot of starters got confused on this. But it is what it is.
Front Controller
In case you actually intend to have a front controller servlet, then you'd best map it on a more specific URL pattern like *.html, *.do, /pages/*, /app/*, etc. You can hide away the front controller URL pattern and cover static resources on a common URL pattern like /resources/*, /static/*, etc with help of a servlet filter. See also How to prevent static resources from being handled by front controller servlet which is mapped on /*. Noted should be that Spring MVC has a built in static resource servlet, so that's why you could map its front controller on / if you configure a common URL pattern for static resources in Spring. See also How to handle static content in Spring MVC?
I'd like to supplement BalusC's answer with the mapping rules and an example.
Mapping rules from Servlet 2.5 specification:
Map exact URL
Map wildcard paths
Map extensions
Map to the default servlet
In our example, there're three servlets. / is the default servlet installed by us. Tomcat installs two servlets to serve jsp and jspx. So to map http://host:port/context/hello
No exact URL servlets installed, next.
No wildcard paths servlets installed, next.
Doesn't match any extensions, next.
Map to the default servlet, return.
To map http://host:port/context/hello.jsp
No exact URL servlets installed, next.
No wildcard paths servlets installed, next.
Found extension servlet, return.
Perhaps you need to know how urls are mapped too, since I suffered 404 for hours. There are two kinds of handlers handling requests. BeanNameUrlHandlerMapping and SimpleUrlHandlerMapping. When we defined a servlet-mapping, we are using SimpleUrlHandlerMapping. One thing we need to know is these two handlers share a common property called alwaysUseFullPath which defaults to false.
false here means Spring will not use the full path to mapp a url to a controller. What does it mean? It means when you define a servlet-mapping:
<servlet-mapping>
<servlet-name>viewServlet</servlet-name>
<url-pattern>/perfix/*</url-pattern>
</servlet-mapping>
the handler will actually use the * part to find the controller. For example, the following controller will face a 404 error when you request it using /perfix/api/feature/doSomething
#Controller()
#RequestMapping("/perfix/api/feature")
public class MyController {
#RequestMapping(value = "/doSomething", method = RequestMethod.GET)
#ResponseBody
public String doSomething(HttpServletRequest request) {
....
}
}
It is a perfect match, right? But why 404. As mentioned before, default value of alwaysUseFullPath is false, which means in your request, only /api/feature/doSomething is used to find a corresponding Controller, but there is no Controller cares about that path. You need to either change your url to /perfix/perfix/api/feature/doSomething or remove perfix from MyController base #RequestingMapping.
I think Candy's answer is mostly correct. There is one small part I think otherwise.
To map host:port/context/hello.jsp
No exact URL servlets installed, next.
Found wildcard paths servlets, return.
I believe that why "/*" does not match host:port/context/hello because it treats "/hello" as a path instead of a file (since it does not have an extension).
The essential difference between /* and / is that a servlet with mapping /* will be selected before any servlet with an extension mapping (like *.html), while a servlet with mapping / will be selected only after extension mappings are considered (and will be used for any request which doesn't match anything else---it is the "default servlet").
In particular, a /* mapping will always be selected before a / mapping. Having either prevents any requests from reaching the container's own default servlet.
Either will be selected only after servlet mappings which are exact matches (like /foo/bar) and those which are path mappings longer than /* (like /foo/*). Note that the empty string mapping is an exact match for the context root (http://host:port/context/).
See Chapter 12 of the Java Servlet Specification, available in version 3.1 at http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html.

Servlet Filter - Dont apply filter to a specific one

I have a web-application with login screen backed up by an Authentication Filter.
I have the following in my web.xml
<filter>
<filter-name>AuthenticationFilter</filter-name>
<display-name>AuthenticationFilter</display-name>
<filter-class>com.mycompany.secutity.AuthenticationFilter</filter-class>
</filter>
And I have the following mapping -
<filter-mapping>
<filter-name>AuthenticationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
But now I want to add an exception where for a specific servlet /web/MyNewServlet, I want to bypass the authenctication filter. How can we do this?
There are two ways in which you could do this:
Remap the /* pattern to another pattern like /subdir/*, and thereby avoid the AuthenticationFilter from being applied against /web/MyNewServlet. This is a cumbersome process as you might have several URLs in your web-application that now need to be remapped. I would suggest doing this early in your development, or when you do not have too many URLs to remap.
Include an exclusion rule programatically inside your Filter implementation. You will need to use HttpServletRequest.getServletPath and similar methods to verify if the URL fragment contains /web/MyNewServlet, and then chain the filter to the next filter or the servlet, instead of executing the body of the filter.
Extending Vineet's idea slightly, you could add another filter, called something like DoesNotNeedAuthenticationFilter, which runs before the AuthenticationFilter, and just sets an attribute DOES_NOT_NEED_AUTHENTICATION on the request. The AuthenticationFilter can then check for that attribute, and pass any requests which have it. You can then use the normal filter mapping mechanism to apply the DoesNotNeedAuthenticationFilter to the appropriate URLs or servlets.

Using <mvc:resources .../> in spring 3 causes all other views to stop working

Simplest example:
I have a dispatcher servlet configured to catch everything:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
I have a simple test controller:
#RequestMapping("/index")
#ResponseBody
public String rootTest(){
return "Main page displayed from TestController";
}
In this test case I am adding (or removing) the following line to dispatcher-servlet.xml:
<mvc:resources mapping="/public/**" location="/public/"/>
My lofty goal: to serve static content (images, css, js) along with my dynamic content (generated via Velocity within a Jetty servlet container, tied together with the almighty Spring).
My Dilema: When I add <mvc:resources .../> I get a 404 for http://localhost/index, but I can serve an image from http://localhost/public/img/42.png. If I remove <mvc:resources .../> then http://localhost/index works fine, but of course, how do I serve static content?
Bonus question: Why can I never have my cake and eat it too?
There are 2 problems:
Never use /* in servlet mapping:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<mvc:resources> requires <mvc:annotation-driven> (or explicitly declared handler mappings, etc).
This happens because DispatcherServlet applies default configuration of handler mappings only when no custom handler mappings found in the context. Since <mvc:resources> adds its own handler mapping, defaults are broken, therefore other handler mappings should be decalred explicitly, either by <mvc:annotation-driven> or manually as beans.
Also note that <mvc:resources> declares only DefaultAnnotationHandlerMapping and doesn't declare other mappings such as BeanNameUrlHandlerMapping, though they are in defaults of DispatcherServlet. Declare them manually if you need them.
I also met this problem before. My situation was I didn't put all the 62 spring framework jars into the lib file (spring-framework-4.1.2.RELEASE edition), it did work. And then I also changed the 3.0.xsd into 2.5 or 3.1 for test, it all worked out. Of course, there are also other factors to affect your result.
add "mvc:annotation-driven" line into view resolvers SpringWeb.XML file. it is work for me

getServletContext().getAttribute() returning null?

When trying to set Context attributes like so:
void init()
{
String testing = new String();
testing = "This is a test";
getServletContext().setAttribute("test", testing);
}
In one servlet, and getting the attribute like so:
String testing = (String) getServletContext().getAttribute("test")
In a second servlet, testing is null.
Does this mean my servlets are in separate contexts? If so, how could I access the context attributes of the first servlet? Please provide a reference for this as I am relatively new to java/servlets.
I am using Netbeans with Glassfish 3.
EDIT: They are both in the same webapp and are both defined in the same WEB-INF/web.xml
If both servlets are in the same webapp, by default the order of initialization is undefined. So it may be, your "second" servlet is initialized before the "first" (according to the order in the web.xml). You may fix it by adding a load-on-startup tag to the servlet tag:
<servlet>
<servlet-name>first<servlet-name>
...
<load-on-startup>1<load-on-startup>
</servlet>
<servlet>
<servlet-name>second<servlet-name>
...
<load-on-startup>2<load-on-startup>
</servlet>
I believe the two servlets need to be in the web application, i.e. packaged in the same war file, for this to work.
Context == WAR == webapps
Both servlet has to live under the same webapp to share context. Check if both servlet classes are under same WEB-INF/classes.

How To Read Context Parameters From a Restlet?

When using Restlets, how can I read configuration parameters passed in through web.xml? With servlets, context-param can be used. How do I read context parameters from within a Restlet?
From the mailing list:
the init parameters are available in the application's context:
getApplication().get​Context().getParamet​ers().
In web.xml:
<context-param>
<param-name>my.context.param</param-name>
<param-value>Hello World</param-value>
</context-param>
In a Restlet's represent method, use:
// => "Hello World"
String result =
getApplication().getContext().getParameters().getFirstValue("my.context.param");
ServerServlet adds all the init parameters from both the servletConfig and from the servletContext to the application context.
So depending on your need, you could either examine the source code for ServerServlet, and read the configuration parameters in the same way, or simply obtain the values from your restlet, or your restlet's application's context.

Categories

Resources