I need to include jersey into my web application. I use spring ioc and
spring mvc and already have some dispatcher servlet instances. Jersey
resources should be automatically injected with spring beans from the
child (non-root) application context associated with one of the
dispatcher servlet.
I tried mapping Jersey [i]SpringServlet[/i] as a servlet into
web.xml... but it works well only when you want to use the root
application context or create a child new one. That's not my case... I
was not able to configure a to workaround the problem I had to subclass
[i]SpringServlet[/i] in order to expose it as a controller from my
dispatcher servlet.
Here you are the controller I made
[code]
package com.acme.my.app;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.collections.iterators.IteratorEnumeration;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.ServletConfigAware;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.servlet.ModelAndView;
import com.sun.jersey.api.core.PackagesResourceConfig;
import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
/**
*
*
* @author Davide Cavestro
*
*/
@Controller
@RequestMapping ("/resources")
public class SuiteServlet extends SpringServlet implements
ApplicationContextAware, ServletContextAware, InitializingBean,
ServletConfigAware, ApplicationListener<ContextRefreshedEvent> {
/**
* serial version uid
*/
private static final long serialVersionUID = 1L;
private ApplicationContext applicationContext;
private ServletConfig servletConfig;
private Map<String, String> initParameters = new HashMap<String,
String> ();
/**
*
*/
public SuiteServlet () {//simulate servlet init params (we don't
have a web.xml mapping to se them)
initParameters.put (PackagesResourceConfig.PROPERTY_PACKAGES,
"com.acme.my.app");
initParameters.put
("com.sun.jersey.api.json.POJOMappingFeature", "true");
}
@Override
protected ConfigurableApplicationContext getContext () {
return (ConfigurableApplicationContext) applicationContext;
}
@Override
public void setApplicationContext (final ApplicationContext
applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void afterPropertiesSet () throws Exception {
}
@Override
public void setServletContext (final ServletContext servletContext)
{
// no-op
}
@RequestMapping ("/**")
public ModelAndView main (final HttpServletRequest request, final
HttpServletResponse response) throws ServletException, IOException {
service (request, response);
return null;
}
@Override
public void setServletConfig (final ServletConfig servletConfig) {
this.servletConfig = servletConfig;
}
@Override
public ServletConfig getServletConfig () {
// wrap the original servlet config in order to expose servlet
init params
final ServletConfig config = new ServletConfig () {
@Override
public String getServletName () {
return servletConfig.getServletName ();
}
@Override
public ServletContext getServletContext () {
return servletConfig.getServletContext ();
}
@Override
public String getInitParameter (String name) {
return initParameters.get (name);
}
@Override
public Enumeration getInitParameterNames () {
return new IteratorEnumeration (initParameters.keySet
().iterator ());
}};
return config;
}
@Override
public void onApplicationEvent (final ContextRefreshedEvent event)
{
try {
init (getServletConfig ());
} catch (final ServletException e) {
e.printStackTrace (System.err);
}
}
}
[/code]
This workaround has at least one drawback:
* if the SpringServlet is mapped to [i]"/resources"[/i], the REST
resources still have to declare [i]"resources"[/i] in their mapping
(i.e. @Path("/resources/myresource/"): the two mappings have to match,
otherwise the controller or the resource does not participate to the
request processing
Maybe starting from the SpringServlet a new application context having
my dispatcherservlet's existing application context as parent would
give better results.
[b]Is there any other (cleaner) way to achieve jersey-spring child
application context integration? [/b]