Index: contribs/spring/src/test/java/com/sun/jersey/spring25/SpringScopedResource.java =================================================================== --- contribs/spring/src/test/java/com/sun/jersey/spring25/SpringScopedResource.java (revision 0) +++ contribs/spring/src/test/java/com/sun/jersey/spring25/SpringScopedResource.java (revision 0) @@ -0,0 +1,55 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of the Common Development + * and Distribution License("CDDL") (the "License"). You may not use this file + * except in compliance with the License. + * + * You can obtain a copy of the License at: + * https://jersey.dev.java.net/license.txt + * See the License for the specific language governing permissions and + * limitations under the License. + * + * When distributing the Covered Code, include this CDDL Header Notice in each + * file and include the License file at: + * https://jersey.dev.java.net/license.txt + * If applicable, add the following below this CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + */ +package com.sun.jersey.spring25; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import com.sun.jersey.spi.resource.Singleton; + +/** + * A resource class that is only annotated with spring's {@link Scope} annotation + * and no jersey lifecycle annotation. + * + * @author Martin Grotzke + * @version $Id$ + */ + @Path( "SpringScopedResource" ) + @Component + @Scope( "singleton" ) +public class SpringScopedResource { + + public SpringScopedResource() { + } + + @GET + @Path( "hello" ) + @Produces( "text/plain" ) + public String sayHello() { + return "hello"; + } + +} Property changes on: contribs/spring/src/test/java/com/sun/jersey/spring25/SpringScopedResource.java ___________________________________________________________________ Name: svn:keywords + Id Index: contribs/spring/src/test/java/com/sun/jersey/spring25/SpringScopedResourceTest.java =================================================================== --- contribs/spring/src/test/java/com/sun/jersey/spring25/SpringScopedResourceTest.java (revision 0) +++ contribs/spring/src/test/java/com/sun/jersey/spring25/SpringScopedResourceTest.java (revision 0) @@ -0,0 +1,55 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of the Common Development + * and Distribution License("CDDL") (the "License"). You may not use this file + * except in compliance with the License. + * + * You can obtain a copy of the License at: + * https://jersey.dev.java.net/license.txt + * See the License for the specific language governing permissions and + * limitations under the License. + * + * When distributing the Covered Code, include this CDDL Header Notice in each + * file and include the License file at: + * https://jersey.dev.java.net/license.txt + * If applicable, add the following below this CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + */ +package com.sun.jersey.spring25; + +import org.springframework.context.annotation.Scope; +import org.testng.Assert; +import org.testng.annotations.Test; + +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.spring.AbstractResourceTest; + +/** + * Test support for resource classes that are only annotated with a spring + * {@link Scope} and no jersey lifecycle annotation. + * + * @author Martin Grotzke + * @version $Id$ + */ +@Test +public class SpringScopedResourceTest extends AbstractResourceTest { + + private String _resourcePath; + + public SpringScopedResourceTest() { + _resourcePath = "SpringScopedResource"; + } + + @Test + public void testSayHello() { + final WebResource itemResource = resource( _resourcePath + "/hello" ); + final String hello = itemResource.get( String.class ); + Assert.assertNotNull( hello ); + + } + +} Property changes on: contribs/spring/src/test/java/com/sun/jersey/spring25/SpringScopedResourceTest.java ___________________________________________________________________ Name: svn:keywords + Id Index: contribs/spring/src/main/java/com/sun/jersey/spi/spring/container/servlet/SpringResourceProvider.java =================================================================== --- contribs/spring/src/main/java/com/sun/jersey/spi/spring/container/servlet/SpringResourceProvider.java (revision 0) +++ contribs/spring/src/main/java/com/sun/jersey/spi/spring/container/servlet/SpringResourceProvider.java (revision 0) @@ -0,0 +1,187 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of the Common Development + * and Distribution License("CDDL") (the "License"). You may not use this file + * except in compliance with the License. + * + * You can obtain a copy of the License at: + * https://jersey.dev.java.net/license.txt + * See the License for the specific language governing permissions and + * limitations under the License. + * + * When distributing the Covered Code, include this CDDL Header Notice in each + * file and include the License file at: + * https://jersey.dev.java.net/license.txt + * If applicable, add the following below this CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + */ +package com.sun.jersey.spi.spring.container.servlet; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import com.sun.jersey.api.core.HttpContext; +import com.sun.jersey.api.core.ResourceConfig; +import com.sun.jersey.api.model.AbstractResource; +import com.sun.jersey.impl.container.servlet.PerSessionProvider; +import com.sun.jersey.impl.resource.PerRequestProvider; +import com.sun.jersey.impl.resource.SingletonProvider; +import com.sun.jersey.spi.resource.ResourceProvider; +import com.sun.jersey.spi.service.ComponentProvider; + +/** + *
+ * This {@link ResourceProvider} is configured as the DefaultResourceProviderClass + * (see {@link ResourceConfig#PROPERTY_DEFAULT_RESOURCE_PROVIDER_CLASS}) by the + * {@link SpringServlet} if there's not already another DefaultResourceProviderClass is + * configured and if spring 2.5+ is used (determined by the availability of + * the {@link Component} annotation). + *
+ *+ * For resource classes annotated with {@link Component}, this {@link ResourceProvider} + * uses the value of the {@link Scope} annotation (provided by spring >= 2.5) on the + * resource class. According to the value of the {@link Scope} annotation it creates + * an appropriate {@link ResourceProvider} implementation and delegates all further work to this. + *
+ *+ * These spring scopes are supported: {@link SupportedSpringScopes}. + *
+ *+ * This {@link ResourceProvider} depends on spring 2.5 + *
+ * + * @author Martin Grotzke + * @version $Id$ + */ +public class SpringResourceProvider implements ResourceProvider { + + private static final Log LOG = LogFactory.getLog( SpringResourceProvider.class ); + + /** + * This enum defines the mapping of spring scopes to the jersey lifecycle/scopes + */ + public enum SupportedSpringScopes { + + /** + * Maps the spring scope "singleton" to the {@link SingletonProvider} + */ + SINGLETON ( "singleton", SingletonProvider.class ), + /** + * Maps the spring scope "prototype" to the {@link PerRequestProvider} + */ + PROTOTYPE( "prototype", PerRequestProvider.class ), + /** + * Maps the spring scope "request" to the {@link PerRequestProvider} + */ + REQUEST( "request", PerRequestProvider.class ), + /** + * Maps the spring scope "session" to the {@link PerSessionProvider} + */ + SESSION( "session", PerSessionProvider.class ); + + private final String _springScope; + private final Class extends ResourceProvider> _resourceProviderClass; + + private SupportedSpringScopes( String springScope, + Class extends ResourceProvider> resourceProviderClass ) { + _springScope = springScope; + _resourceProviderClass = resourceProviderClass; + } + + public Class extends ResourceProvider> createResourceProviderClass() { + return _resourceProviderClass; + } + + public String getSpringScope() { + return _springScope; + } + + /** + * Selects the matching SupportedSpringScopes item ornull
.
+ * @param springScope the spring scope
+ * @return the matching SupportedSpringScopes item or null
.
+ */
+ public static SupportedSpringScopes valueOfSpringScope( String springScope ) {
+ for( SupportedSpringScopes scope : values() ) {
+ if ( scope.getSpringScope().equals( springScope ) ) {
+ return scope;
+ }
+ }
+ return null;
+ }
+
+ public static String getSpringScopesAsCSV() {
+ final StringBuilder sb = new StringBuilder();
+ for ( int i = 0; i < values().length; i++ ) {
+ final SupportedSpringScopes item = values()[i];
+ sb.append( item.getSpringScope() );
+ if ( i < values().length - 1 ) {
+ sb.append( ", " );
+ }
+ }
+ return sb.toString();
+ }
+
+ }
+
+ private ResourceProvider _resourceProvider;
+
+ public void init( ComponentProvider provider, ComponentProvider resourceProvider, AbstractResource resource ) {
+ final Class> resourceClass = resource.getResourceClass();
+ final Class extends ResourceProvider> resourceProviderClass;
+ /* This resource provider is only responsible for spring beans
+ * annotated with @Component, for all other resource classes
+ * the default resource provider is used (see ResourceProviderFactory#createProvider)
+ */
+ if ( resourceClass.getAnnotation( Component.class ) == null ) {
+ resourceProviderClass = PerRequestProvider.class;
+ }
+ else {
+ /* This resource provider is only used if the resource class
+ * does not have any jersey lifecycle annotation
+ * -> we do not have to check this
+ * -> if no supported spring scope is used we cannot handle this
+ */
+ final Scope scope = resourceClass.getAnnotation( Scope.class );
+ if ( scope != null ) {
+ final SupportedSpringScopes springScope = SupportedSpringScopes.valueOfSpringScope( scope.value() );
+ if ( springScope != null ) {
+ resourceProviderClass = springScope.createResourceProviderClass();
+ }
+ else {
+ throw new RuntimeException( "No jersey lifecycle annotation specified on" +
+ " resource class " + resourceClass.getName() +
+ " and also no valid spring scope (valid scopes: "+ SupportedSpringScopes.getSpringScopesAsCSV() +")" );
+ }
+ }
+ else {
+ throw new RuntimeException( "No jersey lifecycle annotation specified on" +
+ " resource class " + resourceClass.getName() +
+ " and also no spring scope." );
+ }
+ }
+ try {
+ _resourceProvider = (ResourceProvider)provider.getInstance(
+ ComponentProvider.Scope.PerRequest, resourceProviderClass );
+ _resourceProvider.init( provider, resourceProvider, resource );
+ } catch( RuntimeException e ) {
+ LOG.error( "Could not initialize resource provider for resource class " + resourceClass.getName() );
+ throw e;
+ } catch ( Exception e ) {
+ LOG.error( "Could not initialize resource provider for resource class " + resourceClass.getName() );
+ e.printStackTrace();
+ throw new RuntimeException( "Could not initialize resource provider for resource class ", e );
+ }
+ }
+
+ public Object getInstance( ComponentProvider provider, HttpContext context ) {
+ return _resourceProvider.getInstance( provider, context );
+ }
+
+}
Index: contribs/spring/src/main/java/com/sun/jersey/spi/spring/container/servlet/SpringServlet.java
===================================================================
--- contribs/spring/src/main/java/com/sun/jersey/spi/spring/container/servlet/SpringServlet.java (revision 1359)
+++ contribs/spring/src/main/java/com/sun/jersey/spi/spring/container/servlet/SpringServlet.java (working copy)
@@ -161,6 +161,11 @@
final WebApplicationContext springContext = WebApplicationContextUtils.
getRequiredWebApplicationContext(getServletContext());
+ if ( rc.getProperty( ResourceConfig.PROPERTY_DEFAULT_RESOURCE_PROVIDER_CLASS ) == null
+ && springComponentAnnotationAvailable() ) {
+ rc.getProperties().put( ResourceConfig.PROPERTY_DEFAULT_RESOURCE_PROVIDER_CLASS, SpringResourceProvider.class );
+ }
+
wa.initiate(rc, new SpringComponentProvider((ConfigurableApplicationContext) springContext));
} catch( RuntimeException e ) {
LOG.error( "Got exception while trying to initialize", e );
@@ -168,6 +173,17 @@
}
}
+ private boolean springComponentAnnotationAvailable() {
+ try {
+ Class.forName( "org.springframework.stereotype.Component" );
+ LOG.info( "The spring Component annotation is present, we're using spring >= 2.5" );
+ return true;
+ } catch ( ClassNotFoundException e ) {
+ LOG.info( "The spring Component annotation is not present, we're using spring < 2.5" );
+ return false;
+ }
+ }
+
private static String getBeanName( ComponentContext cc, Class> c, ApplicationContext springContext ) {
boolean annotatedWithInject = false;
Index: jersey-server/src/main/java/com/sun/jersey/impl/container/servlet/PerSessionProvider.java
===================================================================
--- jersey-server/src/main/java/com/sun/jersey/impl/container/servlet/PerSessionProvider.java (revision 1359)
+++ jersey-server/src/main/java/com/sun/jersey/impl/container/servlet/PerSessionProvider.java (working copy)
@@ -70,7 +70,7 @@
public void init(ComponentProvider provider,
- AbstractResource abstractResource) {
+ ComponentProvider resourceProvider, AbstractResource abstractResource) {
this.c = abstractResource.getResourceClass();
this.rci = new ResourceClassInjector(ipc, Scope.PerRequest,
Index: jersey-server/src/main/java/com/sun/jersey/impl/resource/PerRequestProvider.java
===================================================================
--- jersey-server/src/main/java/com/sun/jersey/impl/resource/PerRequestProvider.java (revision 1359)
+++ jersey-server/src/main/java/com/sun/jersey/impl/resource/PerRequestProvider.java (working copy)
@@ -69,7 +69,7 @@
private List