Author: gertv
Date: Sun Jun 27 11:50:24 2010
New Revision: 958366
URL: http://svn.apache.org/viewvc?rev=958366&view=rev
Log:
SMXCOMP-770: Improve code to leverage async camel routing
Added:
servicemix/components/engines/servicemix-camel/trunk/src/test/java/org/apache/servicemix/camel/AsyncJbiMessagingTest.java
Modified:
servicemix/components/engines/servicemix-camel/trunk/pom.xml
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelConsumerEndpoint.java
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelJbiComponent.java
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelProviderEndpoint.java
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiBinding.java
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiComponent.java
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiEndpoint.java
servicemix/components/engines/servicemix-camel/trunk/src/test/java/org/apache/servicemix/camel/JbiTestSupport.java
Modified: servicemix/components/engines/servicemix-camel/trunk/pom.xml
URL:
http://svn.apache.org/viewvc/servicemix/components/engines/servicemix-camel/trunk/pom.xml?rev=958366&r1=958365&r2=958366&view=diff
==============================================================================
--- servicemix/components/engines/servicemix-camel/trunk/pom.xml (original)
+++ servicemix/components/engines/servicemix-camel/trunk/pom.xml Sun Jun 27
11:50:24 2010
@@ -37,7 +37,7 @@
</scm>
<properties>
- <camel-version>2.3.0</camel-version>
+ <camel-version>2.4-SNAPSHOT</camel-version>
<servicemix.osgi.import>
!org.apache.servicemix.camel*,
org.apache.camel.converter,
Modified:
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelConsumerEndpoint.java
URL:
http://svn.apache.org/viewvc/servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelConsumerEndpoint.java?rev=958366&r1=958365&r2=958366&view=diff
==============================================================================
---
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelConsumerEndpoint.java
(original)
+++
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelConsumerEndpoint.java
Sun Jun 27 11:50:24 2010
@@ -22,24 +22,34 @@ import javax.jbi.messaging.MessageExchan
import javax.jbi.messaging.MessagingException;
import javax.xml.namespace.QName;
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.AsyncProcessor;
import org.apache.camel.Exchange;
import org.apache.servicemix.common.endpoints.ConsumerEndpoint;
import org.apache.servicemix.common.util.URIResolver;
import org.apache.servicemix.id.IdGenerator;
import org.apache.servicemix.jbi.exception.FaultException;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+
/**
* A consumer endpoint that will be used to send JBI exchanges
* originating from camel.
*/
-public class CamelConsumerEndpoint extends ConsumerEndpoint {
+public class CamelConsumerEndpoint extends ConsumerEndpoint implements
AsyncProcessor {
public static final QName SERVICE_NAME = new
QName("http://camel.apache.org/schema/jbi", "provider");
private JbiBinding binding;
- private JbiEndpoint jbiEndpoint;
-
+ private JbiEndpoint jbiEndpoint;
+
+ private Map<String, ContinuationData> continuations = new
ConcurrentHashMap<String, ContinuationData>();
+
public CamelConsumerEndpoint(JbiBinding binding, JbiEndpoint jbiEndpoint) {
setService(SERVICE_NAME);
setEndpoint(new IdGenerator().generateId());
@@ -47,20 +57,32 @@ public class CamelConsumerEndpoint exten
this.jbiEndpoint = jbiEndpoint;
}
- public void process(MessageExchange exchange) throws Exception {
- // we don't expect any asynchronous MessageExchange callbacks because
we're using sendSync
- logger.error("Unexpected MessageExchange received: " + exchange);
+ /**
+ * Process the JBI MessageExchange that is being delivered asynchronously
as a response to what was sent by
+ * the {...@link #process(Exchange, AsyncCallback)} method
+ */
+ public void process(final MessageExchange messageExchange) throws
Exception {
+ final ContinuationData data =
continuations.remove(messageExchange.getExchangeId());
+
+ if (data == null) {
+ logger.error("Unexpected MessageExchange received: " +
messageExchange);
+ } else {
+ binding.runWithCamelContextClassLoader(new Callable<Object>() {
+ public Object call() throws Exception {
+ processReponse(messageExchange, data.exchange);
+ data.callback.done(false);
+ return null;
+ }
+ });
+ }
}
+ /**
+ * Process the Camel Exchange by sending/receiving a JBI MessageExchange
synchronously
+ */
public void process(Exchange exchange) throws Exception {
try {
- MessageExchange messageExchange =
binding.makeJbiMessageExchange(exchange, getExchangeFactory(),
jbiEndpoint.getMep());
-
- if (jbiEndpoint.getOperation() != null) {
- messageExchange.setOperation(jbiEndpoint.getOperation());
- }
-
- URIResolver.configureExchange(messageExchange, getContext(),
jbiEndpoint.getDestinationUri());
+ MessageExchange messageExchange = prepareMessageExchange(exchange);
sendSync(messageExchange);
@@ -69,9 +91,52 @@ public class CamelConsumerEndpoint exten
} catch (MessagingException e) {
exchange.setException(e);
throw new JbiException(e);
- }
+ }
}
-
+
+ /**
+ * Process the Camel Exchange by sending a JBI MessageExchange
asynchronously, where the response
+ * will be handled by the {...@link
#process(javax.jbi.messaging.MessageExchange)} method
+ */
+ public boolean process(Exchange exchange, AsyncCallback asyncCallback) {
+ MessageExchange messageExchange = null;
+ try {
+ messageExchange = prepareMessageExchange(exchange);
+
+ continuations.put(messageExchange.getExchangeId(),
+ new ContinuationData(exchange, asyncCallback));
+
+ send(messageExchange);
+
+ return false;
+ } catch (Exception e) {
+ if (messageExchange != null) {
+ continuations.remove(messageExchange.getExchangeId());
+ }
+
+ exchange.setException(e);
+ asyncCallback.done(true);
+ return true;
+ }
+ }
+
+ /*
+ * Create and configure a JBI MessageExchange for a given Camel Exchange
+ */
+ private MessageExchange prepareMessageExchange(Exchange exchange) throws
MessagingException, URISyntaxException {
+ MessageExchange messageExchange =
binding.makeJbiMessageExchange(exchange, getExchangeFactory(),
jbiEndpoint.getMep());
+
+ if (jbiEndpoint.getOperation() != null) {
+ messageExchange.setOperation(jbiEndpoint.getOperation());
+ }
+
+ URIResolver.configureExchange(messageExchange, getContext(),
jbiEndpoint.getDestinationUri());
+ return messageExchange;
+ }
+
+ /*
+ * Process a JBI response message by updating the corresponding Camel
exchange.
+ */
private void processReponse(MessageExchange messageExchange, Exchange
exchange) throws MessagingException {
if (messageExchange.getStatus() == ExchangeStatus.ERROR) {
exchange.setException(messageExchange.getError());
@@ -95,4 +160,33 @@ public class CamelConsumerEndpoint exten
public void validate() throws DeploymentException {
// No validation required
}
+
+ /**
+ * Provides read-only access to the underlying map of continuation data
+ */
+ protected Map<String, ContinuationData> getContinuationData() {
+ return Collections.unmodifiableMap(continuations);
+ }
+
+ /**
+ * Access the underlying Camel {...@link org.apache.camel.Endpoint}
+ */
+ protected JbiEndpoint getJbiEndpoint() {
+ return jbiEndpoint;
+ }
+
+ /**
+ * Encapsulates all the data necessary to continue processing the Camel
Exchange
+ */
+ private static final class ContinuationData {
+
+ private final Exchange exchange;
+ private final AsyncCallback callback;
+
+ private ContinuationData(Exchange exchange, AsyncCallback callback) {
+ super();
+ this.exchange = exchange;
+ this.callback = callback;
+ }
+ }
}
Modified:
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelJbiComponent.java
URL:
http://svn.apache.org/viewvc/servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelJbiComponent.java?rev=958366&r1=958365&r2=958366&view=diff
==============================================================================
---
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelJbiComponent.java
(original)
+++
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelJbiComponent.java
Sun Jun 27 11:50:24 2010
@@ -24,6 +24,7 @@ import java.util.Map;
import javax.jbi.servicedesc.ServiceEndpoint;
+import org.apache.camel.AsyncProcessor;
import org.apache.camel.Endpoint;
import org.apache.camel.Processor;
import org.apache.servicemix.common.BaseServiceUnitManager;
@@ -116,7 +117,7 @@ public class CamelJbiComponent extends D
Map map = URISupport.parseQuery(uri.getQuery());
String camelUri = uri.getSchemeSpecificPart();
Endpoint camelEndpoint =
jbiComponent.getCamelContext().getEndpoint(camelUri);
- Processor processor =
jbiComponent.createCamelProcessor(camelEndpoint);
+ AsyncProcessor processor =
jbiComponent.createCamelProcessor(camelEndpoint);
CamelProviderEndpoint endpoint =
new CamelProviderEndpoint(getServiceUnit(), camelEndpoint,
jbiComponent.createBinding(camelEndpoint), processor);
Modified:
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelProviderEndpoint.java
URL:
http://svn.apache.org/viewvc/servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelProviderEndpoint.java?rev=958366&r1=958365&r2=958366&view=diff
==============================================================================
---
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelProviderEndpoint.java
(original)
+++
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/CamelProviderEndpoint.java
Sun Jun 27 11:50:24 2010
@@ -26,9 +26,7 @@ import javax.jbi.messaging.MessagingExce
import javax.jbi.messaging.RobustInOnly;
import javax.xml.namespace.QName;
-import org.apache.camel.Endpoint;
-import org.apache.camel.Exchange;
-import org.apache.camel.Processor;
+import org.apache.camel.*;
import org.apache.camel.spi.Synchronization;
import org.apache.servicemix.common.JbiConstants;
@@ -49,15 +47,15 @@ public class CamelProviderEndpoint exten
private Endpoint camelEndpoint;
- private Processor camelProcessor;
+ private AsyncProcessor camelProcessor;
- public CamelProviderEndpoint(ServiceUnit serviceUnit, QName service,
String endpoint, JbiBinding binding, Processor camelProcessor) {
+ public CamelProviderEndpoint(ServiceUnit serviceUnit, QName service,
String endpoint, JbiBinding binding, AsyncProcessor camelProcessor) {
super(serviceUnit, service, endpoint);
this.camelProcessor = camelProcessor;
this.binding = binding;
}
- public CamelProviderEndpoint(ServiceUnit serviceUnit, Endpoint
camelEndpoint, JbiBinding binding, Processor camelProcessor) {
+ public CamelProviderEndpoint(ServiceUnit serviceUnit, Endpoint
camelEndpoint, JbiBinding binding, AsyncProcessor camelProcessor) {
this(serviceUnit, SERVICE_NAME, camelEndpoint.getEndpointUri(),
binding, camelProcessor);
}
@@ -105,13 +103,18 @@ public class CamelProviderEndpoint exten
final Exchange camelExchange = binding.createExchange(exchange);
camelExchange.setFromEndpoint(camelEndpoint);
camelExchange.addOnCompletion(this);
-
+
binding.runWithCamelContextClassLoader(new Callable<Object>() {
public Object call() throws Exception {
- camelProcessor.process(camelExchange);
+ camelProcessor.process(camelExchange, new AsyncCallback() {
+ public void done(boolean doneSync) {
+ // result processing done by onFailure/onSuccess
methods
+ }
+ });
return null;
}
});
+
} else {
// This is not complaint with the default MEPs
throw new IllegalStateException("Provider exchange is ACTIVE, but
no in or fault is provided");
Modified:
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiBinding.java
URL:
http://svn.apache.org/viewvc/servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiBinding.java?rev=958366&r1=958365&r2=958366&view=diff
==============================================================================
---
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiBinding.java
(original)
+++
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiBinding.java
Sun Jun 27 11:50:24 2010
@@ -103,7 +103,7 @@ public class JbiBinding {
* @param callable the block of code to be run
* @throws Exception exceptions being thrown while running the block of
code
*/
- public void runWithCamelContextClassLoader(Callable<Object> callable)
throws Exception {
+ public<T> T runWithCamelContextClassLoader(Callable<T> callable) throws
Exception {
ClassLoader original = Thread.currentThread().getContextClassLoader();
try {
ClassLoader loader = context.getApplicationContextClassLoader();
@@ -113,7 +113,7 @@ public class JbiBinding {
}
Thread.currentThread().setContextClassLoader(loader);
}
- callable.call();
+ return callable.call();
} finally {
// restore CL
Thread.currentThread().setContextClassLoader(original);
Modified:
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiComponent.java
URL:
http://svn.apache.org/viewvc/servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiComponent.java?rev=958366&r1=958365&r2=958366&view=diff
==============================================================================
---
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiComponent.java
(original)
+++
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiComponent.java
Sun Jun 27 11:50:24 2010
@@ -18,11 +18,7 @@ package org.apache.servicemix.camel;
import javax.xml.namespace.QName;
-import org.apache.camel.CamelContext;
-import org.apache.camel.Component;
-import org.apache.camel.Endpoint;
-import org.apache.camel.FailedToCreateProducerException;
-import org.apache.camel.Processor;
+import org.apache.camel.*;
import org.apache.camel.processor.UnitOfWorkProcessor;
import org.apache.servicemix.common.util.URIResolver;
import org.apache.servicemix.id.IdGenerator;
@@ -82,7 +78,7 @@ public class JbiComponent implements Com
protected CamelProviderEndpoint createJbiEndpointFromCamel(
- Endpoint camelEndpoint, Processor processor) {
+ Endpoint camelEndpoint, AsyncProcessor processor) {
CamelProviderEndpoint jbiEndpoint;
String endpointUri = camelEndpoint.getEndpointUri();
if (camelEndpoint instanceof JbiEndpoint) {
@@ -160,12 +156,12 @@ public class JbiComponent implements Com
*/
public CamelProviderEndpoint createJbiEndpointFromCamel(
Endpoint camelEndpoint) {
- Processor processor = createCamelProcessor(camelEndpoint);
+ AsyncProcessor processor = createCamelProcessor(camelEndpoint);
return createJbiEndpointFromCamel(camelEndpoint, processor);
}
- protected Processor createCamelProcessor(Endpoint camelEndpoint) {
- Processor processor = null;
+ protected AsyncProcessor createCamelProcessor(Endpoint camelEndpoint) {
+ AsyncProcessor processor = null;
try {
processor = new
UnitOfWorkProcessor(camelEndpoint.createProducer());
} catch (Exception e) {
Modified:
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiEndpoint.java
URL:
http://svn.apache.org/viewvc/servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiEndpoint.java?rev=958366&r1=958365&r2=958366&view=diff
==============================================================================
---
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiEndpoint.java
(original)
+++
servicemix/components/engines/servicemix-camel/trunk/src/main/java/org/apache/servicemix/camel/JbiEndpoint.java
Sun Jun 27 11:50:24 2010
@@ -22,17 +22,15 @@ import java.util.concurrent.Callable;
import javax.xml.namespace.QName;
-import org.apache.camel.Consumer;
-import org.apache.camel.Endpoint;
-import org.apache.camel.Exchange;
-import org.apache.camel.Processor;
-import org.apache.camel.Producer;
+import org.apache.camel.*;
import org.apache.camel.impl.DefaultConsumer;
import org.apache.camel.impl.DefaultEndpoint;
import org.apache.camel.impl.DefaultProducer;
+import org.apache.camel.impl.converter.AsyncProcessorTypeConverter;
import org.apache.camel.spi.HeaderFilterStrategy;
import org.apache.camel.spi.HeaderFilterStrategyAware;
import org.apache.camel.spi.Registry;
+import org.apache.camel.util.AsyncProcessorHelper;
import org.apache.camel.util.URISupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -81,7 +79,7 @@ public class JbiEndpoint extends Default
return new JbiProducer(this);
}
- protected class JbiProducer extends DefaultProducer {
+ protected class JbiProducer extends DefaultProducer implements
AsyncProcessor {
private final Log log = LogFactory.getLog(JbiProducer.class);
@@ -124,6 +122,20 @@ public class JbiEndpoint extends Default
protected CamelConsumerEndpoint getCamelConsumerEndpoint() {
return consumer;
}
+
+ public boolean process(final Exchange exchange, final AsyncCallback
asyncCallback) {
+ try {
+ return binding.runWithCamelContextClassLoader(new
Callable<Boolean>() {
+
+ public Boolean call() throws Exception {
+ return consumer.process(exchange, asyncCallback);
+ }
+ });
+ } catch (Exception e) {
+ exchange.setException(e);
+ return true;
+ }
+ }
}
@SuppressWarnings("unchecked")
@@ -206,7 +218,7 @@ public class JbiEndpoint extends Default
@Override
protected void doStart() throws Exception {
super.doStart();
- jbiEndpoint =
jbiComponent.createJbiEndpointFromCamel(JbiEndpoint.this, processor);
+ jbiEndpoint =
jbiComponent.createJbiEndpointFromCamel(JbiEndpoint.this,
AsyncProcessorTypeConverter.convert(processor));
jbiComponent.getCamelJbiComponent().activateJbiEndpoint(jbiEndpoint);
}
Added:
servicemix/components/engines/servicemix-camel/trunk/src/test/java/org/apache/servicemix/camel/AsyncJbiMessagingTest.java
URL:
http://svn.apache.org/viewvc/servicemix/components/engines/servicemix-camel/trunk/src/test/java/org/apache/servicemix/camel/AsyncJbiMessagingTest.java?rev=958366&view=auto
==============================================================================
---
servicemix/components/engines/servicemix-camel/trunk/src/test/java/org/apache/servicemix/camel/AsyncJbiMessagingTest.java
(added)
+++
servicemix/components/engines/servicemix-camel/trunk/src/test/java/org/apache/servicemix/camel/AsyncJbiMessagingTest.java
Sun Jun 27 11:50:24 2010
@@ -0,0 +1,100 @@
+/*
+ * 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.servicemix.camel;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.servicemix.client.DefaultServiceMixClient;
+import org.apache.servicemix.client.ServiceMixClient;
+import org.apache.servicemix.executors.impl.ExecutorFactoryImpl;
+import org.apache.servicemix.jbi.container.ActivationSpec;
+import org.apache.servicemix.jbi.container.JBIContainer;
+import org.apache.servicemix.jbi.jaxp.StringSource;
+
+import javax.jbi.messaging.ExchangeStatus;
+import javax.jbi.messaging.InOnly;
+import javax.xml.namespace.QName;
+import java.util.List;
+
+/**
+ * Tests to make sure that even a small thread pool can handle a lot of
servicemix-camel interactions
+ * by avoiding the use of sendSync internally.
+ */
+public class AsyncJbiMessagingTest extends JbiTestSupport {
+
+ private static final String MESSAGE = "<just><a>test</a></just>";
+
+ public void testNoSyncMessagingDeadlock() throws Exception {
+ ServiceMixClient client = new DefaultServiceMixClient(jbiContainer);
+ InOnly exchange = client.createInOnlyExchange();
+ exchange.setService(new QName("urn:test", "service"));
+ exchange.getInMessage().setContent(new StringSource(MESSAGE));
+ client.sendSync(exchange, 5000);
+ assertEquals("Should finish within the designated time-frame,
otherwise we probably caused a thread deadlock",
+ ExchangeStatus.DONE, exchange.getStatus());
+ }
+
+ public void testCallbackExchangesEmptyOnError() throws Exception {
+ // disable the exchange completed listener as it is unable to detect
failed exchanges
+ disableExchangeCompletedListener();
+
+ ServiceMixClient client = new DefaultServiceMixClient(jbiContainer);
+ InOnly exchange = client.createInOnlyExchange();
+ exchange.setService(new QName("urn:test", "error"));
+ exchange.getInMessage().setContent(new StringSource(MESSAGE));
+ client.sendSync(exchange);
+ assertEquals(ExchangeStatus.ERROR, exchange.getStatus());
+
+ // the tearDown method will now ensure that the ContinuationData map
on the endpoint is empty
+ // even though the send failed
+ }
+
+ @Override
+ protected void configureContainer(JBIContainer container) throws Exception
{
+ super.configureContainer(container);
+
+ // let's tune down the default thread pool size to make sure the test
fails with any JBI sync exchange
+ ExecutorFactoryImpl impl = new ExecutorFactoryImpl();
+ impl.getDefaultConfig().setCorePoolSize(1);
+
+ container.setExecutorFactory(impl);
+ }
+
+ @Override
+ protected void appendJbiActivationSpecs(List<ActivationSpec>
activationSpecList) {
+ // no additional activation specs required
+ }
+
+ @Override
+ protected RouteBuilder createRoutes() {
+ return new RouteBuilder() {
+
+ @Override
+ public void configure() throws Exception {
+ // this chain of endpoints is too long to be handled with all
sync calls
+
from("jbi:service:urn:test:service").to("jbi:service:urn:test:service1");
+
from("jbi:service:urn:test:service1").to("jbi:service:urn:test:service2");
+
from("jbi:service:urn:test:service2").to("jbi:service:urn:test:service3");
+
from("jbi:service:urn:test:service3").to("jbi:service:urn:test:service4");
+
from("jbi:service:urn:test:service4").to("jbi:service:urn:test:service5");
+ from("jbi:service:urn:test:service5").to("log:test");
+
+ // deliberately send to an non-existing endpoint
+
from("jbi:service:urn:test:error").to("jbi:service:urn:test:non-existing");
+ }
+ };
+ }
+}
Modified:
servicemix/components/engines/servicemix-camel/trunk/src/test/java/org/apache/servicemix/camel/JbiTestSupport.java
URL:
http://svn.apache.org/viewvc/servicemix/components/engines/servicemix-camel/trunk/src/test/java/org/apache/servicemix/camel/JbiTestSupport.java?rev=958366&r1=958365&r2=958366&view=diff
==============================================================================
---
servicemix/components/engines/servicemix-camel/trunk/src/test/java/org/apache/servicemix/camel/JbiTestSupport.java
(original)
+++
servicemix/components/engines/servicemix-camel/trunk/src/test/java/org/apache/servicemix/camel/JbiTestSupport.java
Sun Jun 27 11:50:24 2010
@@ -20,8 +20,11 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectOutputStream;
+import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -30,12 +33,7 @@ import javax.jbi.JBIException;
import javax.jbi.messaging.MessageExchange;
import javax.xml.namespace.QName;
-import org.apache.camel.CamelContext;
-import org.apache.camel.Endpoint;
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.Processor;
-import org.apache.camel.ProducerTemplate;
+import org.apache.camel.*;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.impl.DefaultCamelContext;
@@ -43,6 +41,7 @@ import org.apache.camel.spi.Synchronizat
import org.apache.camel.test.TestSupport;
import org.apache.servicemix.client.DefaultServiceMixClient;
import org.apache.servicemix.client.ServiceMixClient;
+import org.apache.servicemix.common.Registry;
import org.apache.servicemix.jbi.container.ActivationSpec;
import org.apache.servicemix.jbi.container.JBIContainer;
import org.apache.servicemix.jbi.container.SpringJBIContainer;
@@ -74,7 +73,7 @@ public abstract class JbiTestSupport ext
protected ProducerTemplate client;
protected ServiceMixClient servicemixClient;
-
+
/**
* Sends an exchange to the endpoint
*/
@@ -198,8 +197,12 @@ public abstract class JbiTestSupport ext
@Override
protected void tearDown() throws Exception {
exchangeCompletedListener.assertExchangeCompleted();
+
getServicemixClient().close();
client.stop();
+
+ assertCamelConsumerEndpointsDone();
+
camelContext.stop();
super.tearDown();
}
@@ -229,6 +232,44 @@ public abstract class JbiTestSupport ext
});
}
+ protected void disableExchangeCompletedListener() {
+ jbiContainer.removeListener(exchangeCompletedListener);
+ }
+
+ /*
+ * Assert that all CamelConsumerEndpoint are done:
+ * - there should be no more pending ContinuationData instances
+ */
+ private void assertCamelConsumerEndpointsDone() throws Exception {
+ List<CamelConsumerEndpoint> results =
findEndpoints(CamelConsumerEndpoint.class);
+
+ for (CamelConsumerEndpoint endpoint : results) {
+ assertEquals("Continuation data map should be empty on endpoint
for " + endpoint.getJbiEndpoint().getDestinationUri(),
+ 0, endpoint.getContinuationData().size());
+
+ }
+ }
+
+ /*
+ * Find endpoints in the component registry for the type provided
+ */
+ private<E> List<E> findEndpoints(Class<E> type) throws
NoSuchFieldException, IllegalAccessException {
+ List<E> results = new LinkedList<E>();
+
+ // little hack to access the endpoints map in the registry directly
+ Field field = Registry.class.getDeclaredField("endpoints");
+ field.setAccessible(true);
+ Map<String, org.apache.servicemix.common.Endpoint> endpoints = (Map)
field.get(component.getRegistry());
+
+ for (org.apache.servicemix.common.Endpoint endpoint :
endpoints.values()) {
+ if (type.isAssignableFrom(endpoint.getClass())) {
+ results.add((E) endpoint);
+ }
+ }
+
+ return results;
+ }
+
protected abstract void appendJbiActivationSpecs(
List<ActivationSpec> activationSpecList);