Skip to content

Commit

Permalink
Support automatic registration of type converter bean
Browse files Browse the repository at this point in the history
  • Loading branch information
astefanutti committed Aug 28, 2014
1 parent be400df commit db5caac
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import java.util.Set;

@Vetoed
class CdiBeanRegistry implements Registry {
final class CdiBeanRegistry implements Registry {

private final BeanManager beanManager;

Expand Down
26 changes: 23 additions & 3 deletions src/main/java/io/astefanutti/camel/cdi/CdiCamelExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,39 @@
package io.astefanutti.camel.cdi;

import org.apache.camel.CamelContext;
import org.apache.camel.Converter;
import org.apache.camel.RoutesBuilder;

import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import javax.enterprise.inject.spi.WithAnnotations;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class CdiCamelExtension implements Extension {

void configureCamelContext(@Observes AfterDeploymentValidation event, BeanManager beanManager) {
CamelContext context = BeanManagerUtil.getContextualReference(beanManager, CamelContext.class, false);
private final Set<Class<?>> typeConverters = Collections.newSetFromMap(new ConcurrentHashMap<Class<?>, Boolean>());

for (RoutesBuilder builder : BeanManagerUtil.getContextualReferences(beanManager, RoutesBuilder.class)) {
void processTypeConverters(@Observes @WithAnnotations(Converter.class) ProcessAnnotatedType<?> event) {
typeConverters.add(event.getAnnotatedType().getJavaClass());
}

void configureCamelContext(@Observes AfterDeploymentValidation event, BeanManager manager) {
CamelContext context = BeanManagerUtil.getContextualReference(manager, CamelContext.class, false);

// add type converter beans to the Camel context
if (!typeConverters.isEmpty()) {
CdiTypeConverterLoader loader = new CdiTypeConverterLoader();
for (Class<?> typeConverter : typeConverters)
loader.loadConverterMethods(context.getTypeConverterRegistry(), typeConverter);
}

// instantiate route builders and add them to the Camel context
for (RoutesBuilder builder : BeanManagerUtil.getContextualReferences(manager, RoutesBuilder.class)) {
try {
context.addRoutes(builder);
} catch (Exception exception) {
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/io/astefanutti/camel/cdi/CdiCamelFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@
*/
package io.astefanutti.camel.cdi;

import javax.enterprise.inject.Produces;
import javax.enterprise.inject.Typed;
import javax.enterprise.inject.spi.InjectionPoint;

import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.ProducerTemplate;
Expand All @@ -27,16 +23,20 @@
import org.apache.camel.util.CamelContextHelper;
import org.apache.camel.util.ObjectHelper;

import javax.enterprise.inject.Produces;
import javax.enterprise.inject.Typed;
import javax.enterprise.inject.spi.InjectionPoint;
import java.util.Collection;

class CdiCamelFactory {
final class CdiCamelFactory {

@Produces
private static TypeConverter typeConverter(CamelContext context) {
return context.getTypeConverter();
}

@Produces
@Typed(MockEndpoint.class)
private static MockEndpoint mockEndpointFromMember(InjectionPoint point, CamelContext context) {
String uri = "mock:" + point.getMember().getName();
return CamelContextHelper.getMandatoryEndpoint(context, uri, MockEndpoint.class);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/astefanutti/camel/cdi/CdiInjector.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import javax.enterprise.inject.spi.BeanManager;

class CdiInjector implements Injector {
final class CdiInjector implements Injector {

private final Injector injector;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import org.apache.camel.component.properties.DefaultPropertiesParser;

@Vetoed
class CdiPropertiesParser extends DefaultPropertiesParser {
final class CdiPropertiesParser extends DefaultPropertiesParser {

private final Properties properties;

Expand Down
35 changes: 35 additions & 0 deletions src/main/java/io/astefanutti/camel/cdi/CdiTypeConverterLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright (C) 2014 Antonin Stefanutti (antonin.stefanutti@gmail.com)
*
* Licensed 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 io.astefanutti.camel.cdi;


import org.apache.camel.impl.converter.AnnotationTypeConverterLoader;
import org.apache.camel.spi.TypeConverterRegistry;

import javax.enterprise.inject.Vetoed;

@Vetoed
final class CdiTypeConverterLoader extends AnnotationTypeConverterLoader {

CdiTypeConverterLoader() {
super(null);
}

@Override
protected void loadConverterMethods(TypeConverterRegistry registry, Class<?> type) {
super.loadConverterMethods(registry, type);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,33 @@
package io.astefanutti.camel.cdi;

import io.astefanutti.camel.cdi.bean.InjectedTypeConverterRoute;
import io.astefanutti.camel.cdi.bean.TypeConverterInput;

import io.astefanutti.camel.cdi.bean.TypeConverterOutput;
import io.astefanutti.camel.cdi.pojo.TypeConverterInput;
import io.astefanutti.camel.cdi.pojo.TypeConverterOutput;
import io.astefanutti.camel.cdi.converter.InjectedTypeConverter;
import org.apache.camel.CamelContext;
import org.apache.camel.NoTypeConversionAvailableException;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.TypeConverter;
import org.apache.camel.component.mock.MockEndpoint;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.junit.InSequence;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.Filters;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Test;
import org.junit.runner.RunWith;

import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

import static org.junit.Assert.assertThat;
import static org.hamcrest.Matchers.*;

import static org.apache.camel.component.mock.MockEndpoint.assertIsSatisfied;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

@RunWith(Arquillian.class)
public class InjectedTypeConverterTest {
Expand All @@ -58,8 +56,8 @@ public static Archive<?> deployment() {
.addClass(InjectedTypeConverterRoute.class)
// Type converter
.addClass(InjectedTypeConverter.class)
// TODO: use CDI to automatically register the converter
.addAsManifestResource(new StringAsset("io.astefanutti.camel.cdi.converter"), ArchivePaths.create("services/org/apache/camel/TypeConverter"))
// No need as Camel CDI automatically registers the type converter bean
//.addAsManifestResource(new StringAsset("io.astefanutti.camel.cdi.converter"), ArchivePaths.create("services/org/apache/camel/TypeConverter"))
// Bean archive deployment descriptor
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
Expand All @@ -68,18 +66,11 @@ public static Archive<?> deployment() {
@Produces
private static Properties configuration() {
Properties configuration = new Properties();
configuration.put("property", "value");
configuration.put("property1", "value 1");
configuration.put("property2", "value 2");
return configuration;
}

@Inject
@Uri("direct:inbound")
private ProducerTemplate inbound;

@Inject
@Uri("mock:outbound")
private MockEndpoint outbound;

@Test
@InSequence(1)
public void startCamelContext(CamelContext context) throws Exception {
Expand All @@ -88,21 +79,31 @@ public void startCamelContext(CamelContext context) throws Exception {

@Test
@InSequence(2)
public void sendMessageToInboundConsumer() throws InterruptedException {
public void sendMessageToInboundConsumer(@Uri("direct:inbound") ProducerTemplate inbound, @Uri("mock:outbound") MockEndpoint outbound) throws InterruptedException {
outbound.expectedMessageCount(1);

TypeConverterInput input = new TypeConverterInput();
input.setProperty("property value is [{{property}}]");
input.setProperty("property value is [{{property1}}]");

inbound.sendBody(input);

assertIsSatisfied(2L, TimeUnit.SECONDS, outbound);

assertThat(outbound.getExchanges().get(0).getIn().getBody(TypeConverterOutput.class).getProperty(), is(equalTo("property value is [value]")));
assertThat(outbound.getExchanges().get(0).getIn().getBody(TypeConverterOutput.class).getProperty(), is(equalTo("property value is [value 1]")));
}

@Test
@InSequence(3)
public void convertWithTypeConverter(TypeConverter converter) throws NoTypeConversionAvailableException {
TypeConverterInput input = new TypeConverterInput();
input.setProperty("property value is [{{property2}}]");

TypeConverterOutput output = converter.mandatoryConvertTo(TypeConverterOutput.class, input);

assertThat(output.getProperty(), is(equalTo("property value is [value 2]")));
}

@Test
@InSequence(4)
public void stopCamelContext(CamelContext context) throws Exception {
context.stop();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package io.astefanutti.camel.cdi.bean;


import io.astefanutti.camel.cdi.pojo.TypeConverterOutput;
import org.apache.camel.builder.RouteBuilder;

public class InjectedTypeConverterRoute extends RouteBuilder {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
*/
package io.astefanutti.camel.cdi.converter;

import io.astefanutti.camel.cdi.bean.TypeConverterInput;
import io.astefanutti.camel.cdi.bean.TypeConverterOutput;
import io.astefanutti.camel.cdi.pojo.TypeConverterInput;
import io.astefanutti.camel.cdi.pojo.TypeConverterOutput;
import org.apache.camel.CamelContext;
import org.apache.camel.Converter;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.astefanutti.camel.cdi.bean;
package io.astefanutti.camel.cdi.pojo;


public class TypeConverterInput {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.astefanutti.camel.cdi.bean;
package io.astefanutti.camel.cdi.pojo;


public class TypeConverterOutput {
Expand Down

0 comments on commit db5caac

Please sign in to comment.