Hi,
On a similar note,
I was wondering if JAX-RS Jersey is updated to use Spring Framework 3.0 now. If not, any clue as to when that support will be available?
Thanks!
Ronak Patel
________________________________
From: Brad Lee <s.brad.lee_at_gmail.com>
To: users_at_jersey.dev.java.net
Sent: Tue, January 19, 2010 12:28:20 PM
Subject: Re: [Jersey] Integrating Jersey and Spring
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.
>
>