You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2013/12/13 14:03:03 UTC
svn commit: r1550718 - in /cxf/trunk:
core/src/main/java/org/apache/cxf/common/util/
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/
rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spring/
rt/rs/client/src/main/resources/schemas/ sy...
Author: sergeyb
Date: Fri Dec 13 13:03:03 2013
New Revision: 1550718
URL: http://svn.apache.org/r1550718
Log:
[CXF-4199] Auto-discovery support for Spring jaxrs:client, patch from Andriy Redko applied
Modified:
cxf/trunk/core/src/main/java/org/apache/cxf/common/util/ClasspathScanner.java
cxf/trunk/core/src/main/java/org/apache/cxf/common/util/SpringClasspathScanner.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/JAXRSServerFactoryBeanDefinitionParser.java
cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spring/JAXRSClientFactoryBeanDefinitionParser.java
cxf/trunk/rt/rs/client/src/main/resources/schemas/jaxrs-client.xsd
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/BookStore.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/JAXRSServerSpringDiscoveryTest.java
Modified: cxf/trunk/core/src/main/java/org/apache/cxf/common/util/ClasspathScanner.java
URL: http://svn.apache.org/viewvc/cxf/trunk/core/src/main/java/org/apache/cxf/common/util/ClasspathScanner.java?rev=1550718&r1=1550717&r2=1550718&view=diff
==============================================================================
--- cxf/trunk/core/src/main/java/org/apache/cxf/common/util/ClasspathScanner.java (original)
+++ cxf/trunk/core/src/main/java/org/apache/cxf/common/util/ClasspathScanner.java Fri Dec 13 13:03:03 2013
@@ -24,8 +24,10 @@ import java.net.URL;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
public class ClasspathScanner {
public static final String ALL_FILES = "**/*";
@@ -124,6 +126,24 @@ public class ClasspathScanner {
return HELPER.findResourcesInternal(basePackages, extension);
}
+
+ public static Set<String> parsePackages(final String packagesAsCsv) {
+ final String[] values = StringUtils.split(packagesAsCsv, ",");
+ final Set<String> basePackages = new HashSet<String>(values.length);
+ for (final String value : values) {
+ final String trimmed = value.trim();
+ if (trimmed.equals(ClasspathScanner.ALL_PACKAGES)) {
+ basePackages.clear();
+ basePackages.add(trimmed);
+ break;
+ } else if (trimmed.length() > 0) {
+ basePackages.add(trimmed);
+ }
+ }
+
+ return basePackages;
+ }
+
protected List<URL> findResourcesInternal(Collection<String> basePackages, String extension)
throws IOException {
return Collections.emptyList();
Modified: cxf/trunk/core/src/main/java/org/apache/cxf/common/util/SpringClasspathScanner.java
URL: http://svn.apache.org/viewvc/cxf/trunk/core/src/main/java/org/apache/cxf/common/util/SpringClasspathScanner.java?rev=1550718&r1=1550717&r2=1550718&view=diff
==============================================================================
--- cxf/trunk/core/src/main/java/org/apache/cxf/common/util/SpringClasspathScanner.java (original)
+++ cxf/trunk/core/src/main/java/org/apache/cxf/common/util/SpringClasspathScanner.java Fri Dec 13 13:03:03 2013
@@ -38,12 +38,18 @@ import org.springframework.core.type.cla
import org.springframework.util.ClassUtils;
class SpringClasspathScanner extends ClasspathScanner {
- private final ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
- private final MetadataReaderFactory factory = new CachingMetadataReaderFactory(resolver);
+ SpringClasspathScanner() throws Exception {
+ Class.forName("org.springframework.core.io.support.PathMatchingResourcePatternResolver");
+ Class.forName("org.springframework.core.type.classreading.CachingMetadataReaderFactory");
+ }
+
protected Map< Class< ? extends Annotation >, Collection< Class< ? > > > findClassesInternal(
Collection< String > basePackages, List<Class< ? extends Annotation > > annotations)
throws IOException, ClassNotFoundException {
+
+ ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
+ MetadataReaderFactory factory = new CachingMetadataReaderFactory(resolver);
final Map< Class< ? extends Annotation >, Collection< Class< ? > > > classes =
new HashMap< Class< ? extends Annotation >, Collection< Class< ? > > >();
@@ -90,6 +96,9 @@ class SpringClasspathScanner extends Cla
if (basePackages == null || basePackages.isEmpty()) {
return resourceURLs;
}
+ ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
+
+
for (final String basePackage: basePackages) {
final boolean scanAllPackages = basePackage.equals(ALL_PACKAGES);
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/JAXRSServerFactoryBeanDefinitionParser.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/JAXRSServerFactoryBeanDefinitionParser.java?rev=1550718&r1=1550717&r2=1550718&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/JAXRSServerFactoryBeanDefinitionParser.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/JAXRSServerFactoryBeanDefinitionParser.java Fri Dec 13 13:03:03 2013
@@ -22,10 +22,8 @@ import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import javax.ws.rs.Path;
import javax.ws.rs.ext.Provider;
@@ -76,20 +74,8 @@ public class JAXRSServerFactoryBeanDefin
} else if ("serviceName".equals(name)) {
QName q = parseQName(e, val);
bean.addPropertyValue(name, q);
- } else if ("base-packages".equals(name)) {
- final String[] values = StringUtils.split(val, ",");
- final Set<String> basePackages = new HashSet<String>(values.length);
- for (final String value : values) {
- final String trimmed = value.trim();
- if (trimmed.equals(ClasspathScanner.ALL_PACKAGES)) {
- basePackages.clear();
- basePackages.add(trimmed);
- break;
- } else if (trimmed.length() > 0) {
- basePackages.add(trimmed);
- }
- }
- bean.addPropertyValue("basePackages", basePackages);
+ } else if ("base-packages".equals(name)) {
+ bean.addPropertyValue("basePackages", ClasspathScanner.parsePackages(val));
} else {
mapToProperty(bean, name, val);
}
Modified: cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spring/JAXRSClientFactoryBeanDefinitionParser.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spring/JAXRSClientFactoryBeanDefinitionParser.java?rev=1550718&r1=1550717&r2=1550718&view=diff
==============================================================================
--- cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spring/JAXRSClientFactoryBeanDefinitionParser.java (original)
+++ cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spring/JAXRSClientFactoryBeanDefinitionParser.java Fri Dec 13 13:03:03 2013
@@ -18,19 +18,28 @@
*/
package org.apache.cxf.jaxrs.client.spring;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
+import javax.ws.rs.Path;
+import javax.ws.rs.ext.Provider;
import javax.xml.namespace.QName;
import org.w3c.dom.Element;
import org.apache.cxf.bus.spring.BusWiringBeanFactoryPostProcessor;
+import org.apache.cxf.common.util.ClasspathScanner;
import org.apache.cxf.configuration.spring.AbstractFactoryBeanDefinitionParser;
import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
import org.apache.cxf.jaxrs.model.UserResource;
import org.apache.cxf.jaxrs.utils.ResourceUtils;
import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.context.ApplicationContext;
@@ -39,6 +48,7 @@ import org.springframework.context.Appli
+
public class JAXRSClientFactoryBeanDefinitionParser extends AbstractFactoryBeanDefinitionParser {
public JAXRSClientFactoryBeanDefinitionParser() {
@@ -66,9 +76,11 @@ public class JAXRSClientFactoryBeanDefin
if ("serviceName".equals(name)) {
QName q = parseQName(e, val);
bean.addPropertyValue(name, q);
+ } else if ("base-packages".equals(name)) {
+ bean.addPropertyValue("basePackages", ClasspathScanner.parsePackages(val));
} else {
mapToProperty(bean, name, val);
- }
+ }
}
@Override
@@ -99,11 +111,42 @@ public class JAXRSClientFactoryBeanDefin
public static class JAXRSSpringClientFactoryBean extends JAXRSClientFactoryBean
implements ApplicationContextAware {
+ private List<String> basePackages;
+
public JAXRSSpringClientFactoryBean() {
super();
}
+
+ public void setBasePackages(List<String> basePackages) {
+ this.basePackages = basePackages;
+ }
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
+ try {
+ if (basePackages != null) {
+ @SuppressWarnings("unchecked")
+ final Map< Class< ? extends Annotation >, Collection< Class< ? > > > classes =
+ ClasspathScanner.findClasses(basePackages, Path.class, Provider.class);
+
+ if (classes.get(Path.class).size() > 1) {
+ throw new NoUniqueBeanDefinitionException(Path.class, classes.get(Path.class).size(),
+ "More than one service class (@Path) has been discovered");
+ } else {
+ for (final Class< ? > providerClass: classes.get(Provider.class)) {
+ setProvider(ctx.getAutowireCapableBeanFactory().createBean(providerClass));
+ }
+
+ for (final Class< ? > serviceClass: classes.get(Path.class)) {
+ setServiceClass(serviceClass);
+ }
+ }
+ }
+ } catch (IOException ex) {
+ throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
+ } catch (ClassNotFoundException ex) {
+ throw new BeanCreationException("Failed to create bean from classfile", ex);
+ }
+
if (bus == null) {
setBus(BusWiringBeanFactoryPostProcessor.addDefaultBus(ctx));
}
Modified: cxf/trunk/rt/rs/client/src/main/resources/schemas/jaxrs-client.xsd
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/client/src/main/resources/schemas/jaxrs-client.xsd?rev=1550718&r1=1550717&r2=1550718&view=diff
==============================================================================
--- cxf/trunk/rt/rs/client/src/main/resources/schemas/jaxrs-client.xsd (original)
+++ cxf/trunk/rt/rs/client/src/main/resources/schemas/jaxrs-client.xsd Fri Dec 13 13:03:03 2013
@@ -64,6 +64,7 @@
<xsd:attribute name="password" type="xsd:string"/>
<xsd:attribute name="serviceName" type="xsd:QName"/>
<xsd:attribute name="threadSafe" type="xsd:boolean"/>
+ <xsd:attribute name="base-packages" type="xsd:string"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/BookStore.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/BookStore.java?rev=1550718&r1=1550717&r2=1550718&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/BookStore.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/BookStore.java Fri Dec 13 13:03:03 2013
@@ -21,8 +21,10 @@ package org.apache.cxf.systest.jaxrs.dis
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
import org.apache.cxf.systest.jaxrs.validation.BookWithValidation;
@@ -35,4 +37,11 @@ public class BookStore {
@FormParam("name") String name) {
return new BookWithValidation(name, id);
}
+
+ @GET
+ @Path("/book/{id}")
+ @Valid
+ public BookWithValidation getBook(@NotNull @PathParam("id") String id) {
+ return new BookWithValidation("", id);
+ }
}
Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/JAXRSServerSpringDiscoveryTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/JAXRSServerSpringDiscoveryTest.java?rev=1550718&r1=1550717&r2=1550718&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/JAXRSServerSpringDiscoveryTest.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/JAXRSServerSpringDiscoveryTest.java Fri Dec 13 13:03:03 2013
@@ -22,16 +22,19 @@ import javax.ws.rs.core.Form;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
+import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
+import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
import org.apache.cxf.systest.jaxrs.AbstractSpringServer;
import org.apache.cxf.systest.jaxrs.validation.AbstractJAXRSValidationTest;
-
+import org.apache.cxf.systest.jaxrs.validation.BookWithValidation;
+import org.apache.cxf.testutil.common.TestUtil;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
public class JAXRSServerSpringDiscoveryTest extends AbstractJAXRSValidationTest {
- public static final String PORT = allocatePort(JAXRSServerSpringDiscoveryTest.class);
+ public static final String PORT = TestUtil.getPortNumber("jaxrs-http");
@Ignore
public static class Server extends AbstractSpringServer {
@@ -71,6 +74,16 @@ public class JAXRSServerSpringDiscoveryT
assertEquals(Status.BAD_REQUEST.getStatusCode(), r.getStatus());
}
+ @Test
+ public void testThatClientDiscoversServiceProperly() throws Exception {
+ BookStore bs = JAXRSClientFactory.create("http://localhost:" + PORT, BookStore.class,
+ "org/apache/cxf/systest/jaxrs/discovery/jaxrs-http-client.xml");
+ assertEquals("http://localhost:" + PORT, WebClient.client(bs).getBaseURI().toString());
+
+ BookWithValidation book = bs.getBook("123");
+ assertEquals(book.getId(), "123");
+ }
+
@Override
protected String getPort() {
return PORT;