Get url-pattern from servlet-name - java

I have this configuration in web.xml fileof my Java EE Web application:
<servlet-mapping>
<servlet-name>ChangeLanguageServlet</servlet-name>
<url-pattern>/change</url-pattern>
</servlet-mapping>
What I want to do is get the String of "url-pattern" using the servlet-name, something like this (pseudocode):
// This would return "/change"
String pattern = getPatternByServletName("ChangeLanguageServlet");
I don't know how to do it.
Any help?
Thanks!

From the ServletContext you can get a Map keyed by servlet name with all servlets registered in the application:
Map<String, ? extends ServletRegistration> registrations =
servletContext.getServletRegistrations();
Then use the ServletRegistration API to extract the metadata you need, including:
Servlet name
Servlet class name
Servlet mappings
Servlet initialization parameters

Related

Why have 1 extra level for servlet config in web.xml?

The servlet config looks like this -
<servlet>
<servlet-name>smart</servlet-name>
<servlet-class>SuperSmart</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>smart</servlet-name>
<url-pattern>/dumb</url-pattern>
</servlet-mapping>
Its said that all these aliases are for security. I get that. But why do we have to map it to a servlet-name first and then to the servlet-class ? Why can't the server find the url pattern and directly map it to the servlet-class ?
The aim of this is that the servlet could be referenced by more than one mapping, so you can map one servlet to more than one url (or pattern) and not just one.
The name is sort of like and "ID" that tells the container which <servlet> part goes with which <servlet-mapping> part (as well as ties it to other parts of the XML config in container specific XML files)
You can have multiple url patterns tied to the same servlet name.
I agree it seems ugly, but it's an attempt to keep the servlet config DRY, as servlet-name can be used in filter-mappings as well as servlet-mappings.
In servlet spec 3.0 you can annotate the servlets themselves which is neater.
It was designed that way to allow other components, such as filters, can access it. Filters can either be associated with a Servlet by using the <servlet-name> style:
<filter-mapping>
<filter-name>Image Filter</filter-name>
<servlet-name>ImageServlet</servlet-name>
</filter-mapping>

Servlet Mapping: Is it possible to add servlet mappings at runtime?

Is it possible to add a servlet mapping at runtime? either through a ContextListener or within a Servlet's init() method?
Within the application I am using, all requests are handled through a single Servlet and their mappings are defined in the web.xml file. The number of mappings are increasing and adding a new mapping requires a new release.
Mapping the servlet to /* would not work since requests dispatched to JSPs and static content would also be routed to this Servlet.
Using a filter might be an option nevertheless, it will add a requirement for the filter to know what path to prefix to the RequestDispatcher.
For example:
Dispatcher Servlet Mapping
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/action/*</url-pattern>
</servlet-mapping>
Routing Filter Definition
<filter>
<filter-name>RoutingFilter</filter-name>
<filter-class>com.ssv.web.filter.RoutingFilter</filter-class>
<init-param>
<param-name>exclude</param-name>
<param-value>/static/**:/action/**:/**/*.jsp</param-value>
</init-param>
<init-param>
<param-name>dispatcher-prefix</param-name>
<param-value>/action/**</param-value>
</init-param>
</filter>
In the above example, I would like to skip creating the filter, the filter mapping, and the servlet mapping and instead dynamically define mappings in a ContextListener.
I'm using Tomcat.
In servlet 3.0 (tomcat 7) it is possible: ServletContext.addServlet(..)
But in your case it may be wiser not to do that. Spring's DispatcherServlet for example is mapped to /*. It forwards to JSPs internally, and handles requests in its own non-servlet components, so that it doesn't need to register them dynamically. Take a look at spring-mvc anyway, even if you don't end up using it.
To dynamically add your own servlet, you need a servletcontext Object. From the api docs, there exists a method to bind your Servlet to the servletContext.
Servletconfig.getServletContext().addServlet("YourServletname",yourServletname.class);

How to initialize Java EE 5 JAX-WS 2.0 Web Service with Parameters

Application configuration:
Web application using java first method of creating JAX-WS 2.0 Web Services with annotations.
WebLogic 10.3
My Requirements
The requirements I have are to deploy a single web service implementation class, but change logic based on the URL from which the service was accessed.
Question:
I'm assuming a good way to do this is to deploy different mappings in web.xml and initialize them with different parameters. Is there a better way?
What is the best way to switch logic off the URL from which the web service was accessed? Should I try to configure two servlet mappings in web.xml with initialization parameters (tried, but couldn't get it to work), or should I parse the URL in the service impl? Any other alternatives?
What I've Tried (but didn't work)
I have tried adding the <init-param> in the <servlet> element in web.xml. However, can't get to the ServletConfig object inside the web service to retrieve the param. The web service does not have all the functionality of a standard Servlet (even if I implement Servlet or ServletContextListener). I only have access to the WebServiceContext (it seems) and from there I can only get <context-param> elements--but I would need <init-param> elements instead.
In web.xml, I enter two <servlet> elements using the same Java class, but which map to two different URLs as follows. Notice how the "source" param is different in each Servlet mapping.
<servlet>
<servlet-name>Foo</servlet-name>
<servlet-class>com.Foo</servlet-class>
<init-param>
<param-name>source</param-name>
<param-value>1</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Foo</servlet-name>
<url-pattern>/Foo</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Bar</servlet-name>
<servlet-class>com.Foo</servlet-class>
<init-param>
<param-name>source</param-name>
<param-value>2</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Bar</servlet-name>
<url-pattern>/Bar</url-pattern>
</servlet-mapping>
You very well may have, but did you try using MessageContext at runtime to determine what the source is?
#WebService
public class CalculatorService implements Calculator
{
#Resource
private WebServiceContext context;
#WebMethod
public void getCounter()
{
MessageContext mc = wsContext.getMessageContext();
// you can grab the HttpSession
HttpSession session = (HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST)).getSession();
// ...or maybe the path info is enough
String path = mc.get(MessageContext.PATH_INFO);
// the query itself should almost definitely be enough
String query = (String) mc.get(MessageContext.QUERY_STRING);
}
}
I got the idea from http://sirinsevinc.wordpress.com/category/jaxws/. Haven't tried it, though.

URL Pattern for servlet mapping in web.xml

I need a workaround with this URL mapping in web.xml to create URLs with a letter, followed by a "_" followed by any combination of alphanumeric characters.
I want to map a servlet to something like this:
/something_*
Instead of:
/something/*
Using different "somethings" for different JSP's. Example:
/search_Something-I-searched-for
I tried using:
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/something_*</url-pattern>
</servlet-mapping>
But this doesn't seem to work.
This answer tells me I can't do this within web.xml, so maybe there's some workaround.
I don't know if this information is important, but I'm using JBoss and Struts2 in my project.
Map a servlet to the containing directory. Inside that servlet, take apart the URL path and forward to the appropriate named servlet.
Why not try Spring MVC Framework. Spring can offer that url mapping you want.
#RequestMapping(value="/something_{name}", method=RequestMethod.GET)
public String demo(#PathVariable(value="name") String name, ModelMap map) {
String something = name;
// Do manipulation
return "something"; // Forward to something.jsp
}
Watch this Spring MVC Framework Tutorial

Implementing a REST api which switches between XML and JSON in Servlets

Twitter's REST api allows you to append a JSON or XML at the end of the URI.
e.g.
http://twitter.com/statuses/public_timeline.json
http://twitter.com/statuses/public_timeline.xml
In the context of servlet, statuses will be the webapp context name & public_timeline.json is mapped to some servlet. I want to maintain one servlet to do the dispatch. Can this be done in servlets ?
The URL mapping in Servlet only supports extension matching, not prefix matching. So this doesn't work,
<url-pattern>/public_timeline.*</servlet-class>
Here is my suggestion,
<servlet-mapping>
<url-pattern>/*</servlet-class>
<servlet-name>YourServlet</servlet-class>
</servlet-mapping>
In the servlet, you can do this,
String path = request.getPathInfo();
if (path == null) return;
int index = path.indexOf('/');
String api;
if (index < 0)
api = path;
else
api = path.substring(index+1);
if (api.equals("public_timeline.json"))
// Process it as JSON
if (api.equals("public_timeline.xml"))
// Process it as XML
Most APIs use a format parameter to indicate response format. I think that's the better way.
In Java, if you are using JAXRS for your rest services, annotate your REST service method like:
#Path("/statuses/public_timeline{fileExt}")
Then add the following to you method argument:
#PathParam(value="fileExt") String fileExt
The the fileExt variable would be your extension. I think that would be a standard REST way to do it using JAXRS
Yes, it is possible.
Take a look at the web.xml file you may use a pattern like:
<servlet-mapping>
<url-pattern>public_timeline.*</servlet-class>
<servlet-name>myservlet</servlet-class>
</servlet-mapping>
I think you can even use public_timeline.[json|xml]
You can do simple glob-matching in url-pattern:
<servlet>
<servlet-name>public_timeline</servlet-name>
<servlet-class>your.package.PublicTimelineServlet</servlet-class>
</servlet>
<servlet-mapping>
<url-pattern>/public_timeline.*</servlet-class>
<servlet-name>public_timeline</servlet-class>
</servlet-mapping>

Categories