You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2014/03/29 17:46:17 UTC
git commit: CXF-5576: Initital support for CDI integration. Added
more test cases and support for application singletons
Repository: cxf
Updated Branches:
refs/heads/master 9c920cd52 -> b0e7be04d
CXF-5576: Initital support for CDI integration. Added more test cases and support for application singletons
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/b0e7be04
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/b0e7be04
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/b0e7be04
Branch: refs/heads/master
Commit: b0e7be04d0d6ba8061831fcc26448e8e5c1c8a2e
Parents: 9c920cd
Author: reta <dr...@gmail.com>
Authored: Sat Mar 29 12:46:09 2014 -0400
Committer: reta <dr...@gmail.com>
Committed: Sat Mar 29 12:46:09 2014 -0400
----------------------------------------------------------------------
.../cxf/cdi/JAXRSCdiResourceExtension.java | 171 ++++++++++++++-----
.../org/apache/cxf/systest/jaxrs/BookStore.java | 16 +-
.../cxf/systest/jaxrs/BookStoreApplication.java | 4 +
.../jaxrs/BookStoreCustomApplication.java | 45 +++++
.../cxf/systest/jaxrs/cdi/AbstractCDITest.java | 24 ++-
5 files changed, 219 insertions(+), 41 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/b0e7be04/integration/cdi/src/main/java/org/apache/cxf/cdi/JAXRSCdiResourceExtension.java
----------------------------------------------------------------------
diff --git a/integration/cdi/src/main/java/org/apache/cxf/cdi/JAXRSCdiResourceExtension.java b/integration/cdi/src/main/java/org/apache/cxf/cdi/JAXRSCdiResourceExtension.java
index ffe5421..2218281 100644
--- a/integration/cdi/src/main/java/org/apache/cxf/cdi/JAXRSCdiResourceExtension.java
+++ b/integration/cdi/src/main/java/org/apache/cxf/cdi/JAXRSCdiResourceExtension.java
@@ -19,7 +19,10 @@
package org.apache.cxf.cdi;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.ServiceLoader;
import javax.enterprise.event.Observes;
@@ -40,11 +43,13 @@ import javax.ws.rs.ext.Provider;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.extension.ExtensionManagerBus;
+import org.apache.cxf.feature.Feature;
+import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.utils.ResourceUtils;
/**
- * Apache CXF portable CDI extension to support initialization of JAX-RS / JAX-WS resources.
+ * Apache CXF portable CDI extension to support initialization of JAX-RS resources.
*/
public class JAXRSCdiResourceExtension implements Extension {
private Bean< ? > busBean;
@@ -54,9 +59,6 @@ public class JAXRSCdiResourceExtension implements Extension {
private final List< Bean< ? > > serviceBeans = new ArrayList< Bean< ? > >();
private final List< Bean< ? > > providerBeans = new ArrayList< Bean< ? > >();
- private final List< Object > services = new ArrayList< Object >();
- private final List< Object > providers = new ArrayList< Object >();
-
public <T> void collect(@Observes final ProcessBean< T > event) {
if (event.getAnnotated().isAnnotationPresent(ApplicationPath.class)) {
applicationBeans.add(event.getBean());
@@ -71,26 +73,6 @@ public class JAXRSCdiResourceExtension implements Extension {
}
public void load(@Observes final AfterDeploymentValidation event, final BeanManager beanManager) {
- for (final Bean< ? > bean: serviceBeans) {
- services.add(
- beanManager.getReference(
- bean,
- bean.getBeanClass(),
- beanManager.createCreationalContext(bean)
- )
- );
- }
-
- for (final Bean< ? > bean: providerBeans) {
- providers.add(
- beanManager.getReference(
- bean,
- bean.getBeanClass(),
- beanManager.createCreationalContext(bean)
- )
- );
- }
-
bus = (Bus)beanManager.getReference(
busBean,
busBean.getBeanClass(),
@@ -104,13 +86,22 @@ public class JAXRSCdiResourceExtension implements Extension {
beanManager.createCreationalContext(application)
);
- // Create the JAXRSServerFactoryBean for each application we have discovered
- final JAXRSServerFactoryBean factory = createFactoryInstance(instance);
- factory.init();
+ // If there is an application without any singletons and classes defined, we will
+ // create a server factory bean with all services and providers discovered.
+ if (instance.getSingletons().isEmpty() && instance.getClasses().isEmpty()) {
+ final JAXRSServerFactoryBean factory = createFactoryInstance(instance,
+ loadServices(beanManager), loadProviders(beanManager));
+ factory.init();
+ } else {
+ // If there is an application with any singletons or classes defined, we will
+ // create a server factory bean with only application singletons and classes.
+ final JAXRSServerFactoryBean factory = createFactoryInstance(instance);
+ factory.init();
+ }
}
}
-
- public void injectFactories(@Observes final AfterBeanDiscovery event, final BeanManager beanManager) {
+
+ public void injectBus(@Observes final AfterBeanDiscovery event, final BeanManager beanManager) {
if (busBean == null) {
final AnnotatedType< ExtensionManagerBus > busAnnotatedType =
beanManager.createAnnotatedType(ExtensionManagerBus.class);
@@ -123,28 +114,130 @@ public class JAXRSCdiResourceExtension implements Extension {
}
}
- @SuppressWarnings("rawtypes")
- private JAXRSServerFactoryBean createFactoryInstance(final Application application) {
-
- JAXRSServerFactoryBean instance = ResourceUtils.createApplication(application, false, false);
+ /**
+ * Create the JAXRSServerFactoryBean from the application and all discovered service and provider instances.
+ * @param application application instance
+ * @param services all discovered services
+ * @param providers all discovered providers
+ * @return JAXRSServerFactoryBean instance
+ */
+ private JAXRSServerFactoryBean createFactoryInstance(final Application application, final List< ? > services,
+ final List< ? > providers) {
+
+ final JAXRSServerFactoryBean instance = ResourceUtils.createApplication(application, false, false);
instance.setServiceBeans(new ArrayList< Object >(services));
instance.setProviders(providers);
+ instance.setProviders(loadExternalProviders());
+ instance.setBus(bus);
+
+ return instance;
+ }
+
+ /**
+ * Create the JAXRSServerFactoryBean from the objects declared by application itself.
+ * @param application application instance
+ * @return JAXRSServerFactoryBean instance
+ */
+ private JAXRSServerFactoryBean createFactoryInstance(final Application application) {
+
+ final JAXRSServerFactoryBean instance = ResourceUtils.createApplication(application, false, false);
+ final Map< Class< ? >, List< Object > > classified = classifySingletons(application.getSingletons());
+ instance.setServiceBeans(classified.get(Path.class));
+ instance.setProviders(classified.get(Provider.class));
+ instance.setFeatures(CastUtils.cast(classified.get(Feature.class), Feature.class));
instance.setBus(bus);
-
+
+ return instance;
+ }
+
+ /**
+ * JAX-RS application has defined singletons as being instances of any providers, resources and features.
+ * In the JAXRSServerFactoryBean, those should be split around several method calls depending on instance
+ * type. At the moment, only the Feature is CXF-specific and should be replaced by JAX-RS Feature implementation.
+ * @param singletons application singletons
+ * @return classified singletons by instance types
+ */
+ private Map< Class< ? >, List< Object > > classifySingletons(final Collection< Object > singletons) {
+ final Map< Class< ? >, List< Object > > classified =
+ new HashMap< Class< ? >, List< Object > >();
+
+ classified.put(Feature.class, new ArrayList< Object >());
+ classified.put(Provider.class, new ArrayList< Object >());
+ classified.put(Path.class, new ArrayList< Object >());
+
+ for (final Object singleton: singletons) {
+ if (singleton instanceof Feature) {
+ classified.get(Feature.class).add(singleton);
+ } else if (singleton.getClass().isAnnotationPresent(Provider.class)) {
+ classified.get(Provider.class).add(singleton);
+ } else if (singleton.getClass().isAnnotationPresent(Path.class)) {
+ classified.get(Path.class).add(singleton);
+ }
+ }
+
+ return classified;
+ }
+
+ /**
+ * Load external providers from service loader
+ * @return loaded external providers
+ */
+ @SuppressWarnings("rawtypes")
+ private List< Object > loadExternalProviders() {
+ final List< Object > providers = new ArrayList< Object >();
+
final ServiceLoader< MessageBodyWriter > writers = ServiceLoader.load(MessageBodyWriter.class);
for (final MessageBodyWriter< ? > writer: writers) {
- instance.setProvider(writer);
+ providers.add(writer);
}
final ServiceLoader< MessageBodyReader > readers = ServiceLoader.load(MessageBodyReader.class);
for (final MessageBodyReader< ? > reader: readers) {
- instance.setProvider(reader);
+ providers.add(reader);
}
- return instance;
+ return providers;
}
- public Bus getBus() {
- return bus;
+ /**
+ * Gets the references for all discovered JAX-RS resources
+ * @param beanManager bean manager instance
+ * @return the references for all discovered JAX-RS resources
+ */
+ private List< Object > loadProviders(final BeanManager beanManager) {
+ final List< Object > providers = new ArrayList< Object >();
+
+ for (final Bean< ? > bean: providerBeans) {
+ providers.add(
+ beanManager.getReference(
+ bean,
+ bean.getBeanClass(),
+ beanManager.createCreationalContext(bean)
+ )
+ );
+ }
+
+ return providers;
+ }
+
+ /**
+ * Gets the references for all discovered JAX-RS providers
+ * @param beanManager bean manager instance
+ * @return the references for all discovered JAX-RS providers
+ */
+ private List< Object > loadServices(final BeanManager beanManager) {
+ final List< Object > services = new ArrayList< Object >();
+
+ for (final Bean< ? > bean: serviceBeans) {
+ services.add(
+ beanManager.getReference(
+ bean,
+ bean.getBeanClass(),
+ beanManager.createCreationalContext(bean)
+ )
+ );
+ }
+
+ return services;
}
}
http://git-wip-us.apache.org/repos/asf/cxf/blob/b0e7be04/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
----------------------------------------------------------------------
diff --git a/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java b/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
index c6182f1..755dbff 100644
--- a/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
+++ b/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
@@ -21,6 +21,7 @@ package org.apache.cxf.systest.jaxrs;
import java.util.Collection;
import javax.inject.Inject;
+import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.ws.rs.FormParam;
@@ -28,30 +29,43 @@ import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
@Path("/bookstore/")
public class BookStore {
@Inject private BookStoreService service;
+ @Inject private String version;
@GET
+ @Path("/version")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getVersion() {
+ return version;
+ }
+
+ @GET
@Path("/books/{bookId}")
@NotNull
+ @Produces(MediaType.APPLICATION_JSON)
public Book getBook(@PathParam("bookId") String id) {
return service.get(id);
}
@GET
@Path("/books")
- @NotNull
+ @NotNull @Valid
+ @Produces(MediaType.APPLICATION_JSON)
public Collection< Book > getBooks() {
return service.all();
}
@POST
@Path("/books")
+ @Produces(MediaType.APPLICATION_JSON)
public Response addBook(@Context final UriInfo uriInfo,
@NotNull @Size(min = 1, max = 50) @FormParam("id") String id,
@NotNull @FormParam("name") String name) {
http://git-wip-us.apache.org/repos/asf/cxf/blob/b0e7be04/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreApplication.java
----------------------------------------------------------------------
diff --git a/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreApplication.java b/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreApplication.java
index bf3fdcc..a3e7f84 100644
--- a/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreApplication.java
+++ b/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreApplication.java
@@ -18,9 +18,13 @@
*/
package org.apache.cxf.systest.jaxrs;
+import javax.enterprise.inject.Produces;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/api")
public class BookStoreApplication extends Application {
+ @Produces public String version() {
+ return "1.0";
+ }
}
http://git-wip-us.apache.org/repos/asf/cxf/blob/b0e7be04/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreCustomApplication.java
----------------------------------------------------------------------
diff --git a/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreCustomApplication.java b/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreCustomApplication.java
new file mode 100644
index 0000000..631470d
--- /dev/null
+++ b/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreCustomApplication.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.systest.jaxrs;
+
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+import com.google.common.collect.Sets;
+
+import org.apache.cxf.jaxrs.validation.JAXRSBeanValidationFeature;
+import org.apache.cxf.jaxrs.validation.ValidationExceptionMapper;
+
+@ApplicationPath("/custom")
+public class BookStoreCustomApplication extends Application {
+ @Inject private BookStore bookStore;
+
+ @Override
+ public Set< Object > getSingletons() {
+ return Sets.< Object >newHashSet(
+ bookStore,
+ new JacksonJsonProvider(),
+ new ValidationExceptionMapper(),
+ new JAXRSBeanValidationFeature());
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/b0e7be04/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/cdi/AbstractCDITest.java
----------------------------------------------------------------------
diff --git a/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/cdi/AbstractCDITest.java b/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/cdi/AbstractCDITest.java
index 0627d0a..e58924a 100644
--- a/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/cdi/AbstractCDITest.java
+++ b/systests/cdi/src/test/java/org/apache/cxf/systest/jaxrs/cdi/AbstractCDITest.java
@@ -37,6 +37,13 @@ import org.junit.Test;
public abstract class AbstractCDITest extends AbstractBusClientServerTestBase {
@Test
+ public void testInjectedVersionIsProperlyReturned() {
+ Response r = createWebClient("/rest/api/bookstore/version", MediaType.TEXT_PLAIN).get();
+ assertEquals(Status.OK.getStatusCode(), r.getStatus());
+ assertEquals("1.0", r.readEntity(String.class));
+ }
+
+ @Test
public void testResponseHasBeenReceivedWhenAddingNewBook() {
Response r = createWebClient("/rest/api/bookstore/books").post(
new Form()
@@ -68,12 +75,27 @@ public abstract class AbstractCDITest extends AbstractBusClientServerTestBase {
assertEquals(id, book.getId());
}
+ @Test
+ public void testAddOneBookWithValidation() {
+ final String id = UUID.randomUUID().toString();
+
+ Response r = createWebClient("/rest/custom/bookstore/books").post(
+ new Form()
+ .param("id", id));
+ assertEquals(Status.BAD_REQUEST.getStatusCode(), r.getStatus());
+ }
+
+
protected WebClient createWebClient(final String url) {
+ return createWebClient(url, MediaType.APPLICATION_JSON);
+ }
+
+ protected WebClient createWebClient(final String url, final String mediaType) {
final List< ? > providers = Arrays.asList(new JacksonJsonProvider());
final WebClient wc = WebClient
.create("http://localhost:" + getPort() + url, providers)
- .accept(MediaType.APPLICATION_JSON);
+ .accept(mediaType);
WebClient.getConfig(wc).getHttpConduit().getClient().setReceiveTimeout(10000000L);
return wc;