users@jersey.java.net

Re: [Jersey] Integrating Jersey and Spring

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Wed, 20 Jan 2010 11:14:50 +0000

Hi Brad,

Thanks for sharing. I notice in a comment you state:

     //
=
=
========================================================================
     // SpringServlet methods are private instead of protected,
     // so I have to redo their servlet extension of
ServletContainer...
     //
=
=
========================================================================

If appropriate could you log an issue detailing what changes can be
made to Jersey's SpringServlet to make it easier for you?

Thanks,
Paul.

On Jan 19, 2010, at 8:28 PM, Brad Lee wrote:

> Hi Mahesh. Sorry I am late to reply here, this email never
> responded directly to me. Anyway, on this email you will find the
> JerseySpringController that very simply forwards Spring requests to
> Jersey.
>
> I don't have any examples of interceptors extending ContainerFilters
> and Jersey Resource filters, but I don't honestly think that it
> would be that hard to implement. If I ever have a need for one,
> then I will post back when I write it.
>
> Right now, I'm not bothering with annotations, although I would
> imagine you could configure it using annotations. The properties
> file above is what I use to inject the Properties instance variable
> on the JerseController class.
>
> Also, since Struts2 is YASF(yet another servlet framework), I would
> think it very easy to forward requests it receives into Jersey.
>
> package org.springframework.web.servlet.jersey;
>
> import java.util.Enumeration;
> import java.util.Map;
> import java.util.Properties;
>
> import javax.servlet.FilterConfig;
> import javax.servlet.ServletContext;
> import javax.servlet.ServletException;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpServletResponse;
>
> import org.slf4j.Logger;
> import org.slf4j.LoggerFactory;
> import org.springframework.beans.factory.InitializingBean;
> import org.springframework.context.ApplicationContext;
> import org.springframework.context.ApplicationContextAware;
> import org.springframework.context.ConfigurableApplicationContext;
> import org.springframework.web.context.ServletContextAware;
> import org.springframework.web.servlet.ModelAndView;
> import org.springframework.web.servlet.mvc.Controller;
>
> import com.sun.jersey.api.core.DefaultResourceConfig;
> import com.sun.jersey.api.core.ResourceConfig;
> import com.sun.jersey.spi.container.WebApplication;
> import com.sun.jersey.spi.container.servlet.ServletContainer;
> import com.sun.jersey.spi.container.servlet.WebConfig;
> import
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory;
>
> public class JerseyController
> extends ServletContainer
> implements Controller, ServletContextAware, InitializingBean,
> ApplicationContextAware {
> //
> =
> =
> =
> =
> ======================================================================
> // Private Static Variables
> //
> =
> =
> =
> =
> ======================================================================
> private static final Logger logger =
> LoggerFactory.getLogger(JerseyController.class);
> //
> =
> =
> =
> =
> ======================================================================
> // SpringServlet methods are private instead of protected,
> // so I have to redo their servlet extension of
> ServletContainer...
> //
> =
> =
> =
> =
> ======================================================================
> @Override
> protected void initiate(ResourceConfig rc, WebApplication wa) {
> try {
> wa.initiate(rc, new SpringComponentProviderFactory(rc,
> getContext()));
> } catch (RuntimeException e) {
> logger.error("Exception occurred during initializing
> "+SpringComponentProviderFactory.class.getName()+"!", e);
> throw e;
> }
> }
> protected ConfigurableApplicationContext getContext() {
> final ConfigurableApplicationContext springContext =
> (ConfigurableApplicationContext)
> this.getApplicationContext();
> return springContext;
> }
>
> //
> =
> =
> =
> =
> ======================================================================
> // Instance Variables
> //
> =
> =
> =
> =
> ======================================================================
> private ServletContext springServletContext;
> private Properties jerseyConfiguration;
> private ApplicationContext applicationContext;
> //
> =
> =
> =
> =
> ======================================================================
> // Getters
> //
> =
> =
> =
> =
> ======================================================================
> @Override
> public void setServletContext(ServletContext servletContext) {
> springServletContext = servletContext;
> }
> public Properties getJerseyConfiguration() {
> return jerseyConfiguration;
> }
> public ApplicationContext getApplicationContext() {
> return applicationContext;
> }
> //
> =
> =
> =
> =
> ======================================================================
> // Setters
> //
> =
> =
> =
> =
> ======================================================================
> public ServletContext getSpringServletContext(){
> return springServletContext;
> }
> @Override
> public ServletContext getServletContext(){
> return this.getSpringServletContext();
> }
> public void setJerseyConfiguration(Properties
> jerseyConfiguration) {
> if( logger.isDebugEnabled() ){
> StringBuffer buffer = new StringBuffer();
> buffer.append("Setting jersey configuration:\n");
> for( Object key : jerseyConfiguration.keySet() ){
>
> buffer
> .append
> ("\t
> ").append
> (key).append("=").append(jerseyConfiguration.get(key)).append("\n");
> }
> logger.debug(buffer.toString());
> }
> this.jerseyConfiguration = jerseyConfiguration;
> }
> @Override
> public void setApplicationContext(ApplicationContext
> applicationContext) {
> this.applicationContext = applicationContext;
> }
> //
> =
> =
> =
> =
> ======================================================================
> // Interfaces
> //
> =
> =
> =
> =
> ======================================================================
> @Override
> public ModelAndView handleRequest(
> HttpServletRequest request,
> HttpServletResponse response
> ) throws Exception {
> String uri = request.getRequestURI().substring(
> request.getContextPath().length(),
> request.getRequestURI().length());
> logger.info("Handling request {}, by passing it to parent
> jersey servlet...", uri);
> try{
> super.service(request, response);
> }catch(Throwable t){
> logger.error("An error occurred processing request:
> "+uri, t);
> throw new ServletException("The REST web service had an
> error. Please report this problem.", t);
> }
> logger.info("For path {}, returning DoNothingView...", uri);
> return new ModelAndView("DoNothingView");
> }
>
>
> @Override
> public void afterPropertiesSet() throws Exception {
> final String fName = getClass().getName();
> final Properties fJerseyConfig =
> this.getJerseyConfiguration();
> logger.info("Initializing Bean {}...", fName);
> FilterConfig config = new FilterConfig() {
> @Override
> public ServletContext getServletContext() {
> return getSpringServletContext();
> }
> @Override
> public String getFilterName() {
> return fName;
> }
> @Override
> public Enumeration getInitParameterNames() {
> return fJerseyConfig.keys();
> }
> @Override
> public String getInitParameter(String paramName) {
> return fJerseyConfig.getProperty(paramName);
> }
> };
>
> logger.debug("Initializing Jersey through
> super.init(FilterConfig)...");
> super.init(config);
> }//end afterPropertiesSet()
>
> }/* end JerseyIntegrationFilter */
>
>
> Where the injected properties file looks like this:
> # If true the request URI will be normalized as specified by
> # {_at_link java.net.URI#normalize}. If not true the request URI is not
> # modified.
> # The default value is false.
>
> com.sun.jersey.config.feature.NormalizeURI=true
>
>
> # If true the request URI path component will be canonicalized by
> removing
> # contiguous slashes (i.e. all /+ will be replaced by /). If not
> true the
> # request URI path component is mot modified.
> # The default value is false.
>
> com.sun.jersey.config.feature.CanonicalizeURIPath=true
>
>
> # If true, and either NORMALIZE_URI or CANONICALIZE_URI_PATH is true,
> # and the normalization and/or path canonicalization operations on the
> # request URI result in a new URI that is not equal to the request
> URI,
> # then the client is (temporarily) redirected to the new URI.
> Otherwise
> # the request URI is set to be the new URI.
> # <p>
> # If true, and the path value of a {_at_link javax.ws.rs.Path}
> annotation ends
> # in a slash, the request URI path does not end in a '/' and would
> otherwise
> # match the path value if it did, then the client is (temporarily)
> # redirected to a new URI that is the request URI with a '/'
> appended to the
> # the end of the path.
> # <p>
> # The default value is false.
>
> com.sun.jersey.config.feature.Redirect=true
>
>
> # If true matrix parameters (if present) in the request URI path
> component
> # will be ignored when matching the path to URI templates declared by
> # resource classes.
> # <p>
> # The default value is false.
>
> #com.sun.jersey.config.feature.IgnoreMatrixParams=true
>
>
> # If true then the matching algorithm will attempt to match and accept
> # any static content or templates associated with a resource that were
> # not explicitly decared by that resource.
> # <p>
> # If a template is matched then the model for the viewable will be the
> # resource instance associated with the template.
> # <p>
> # The default value is false.
>
> com.sun.jersey.config.feature.ImplicitViewables=true
>
>
> # If true then disable WADL generation.
> # <p>
> # By default WADL generation is automatically enabled, if JAXB is
> # present in the classpath.
> # <p>
> # The default value is false.
>
> #com.sun.jersey.config.feature.DisableWADL=true
>
>
>
> On Wed, Jan 13, 2010 at 4:02 PM, Mahesh Venkat <mhvenkat_at_gmail.com>
> wrote:
> Hi Brad,
>
> Is it possible to share this working code?
> Also if you have an example of adding Spring interceptors that
> extend the Jersey ContainerFilters and Jersey ResourceFilters it
> will be great!
>
> In fact, in Spring 3.0 they are attempting do to take a similar
> approach to integrate with Jersey.
>
> We also have to some thing similar for Struts2 too. The Apache
> community is attempting to define yet another REST mechanism rather
> than integrating Jersey with Struts2.
>