diff --git a/akka-camel-typed/src/main/java/akka/camel/consume.java b/akka-camel-typed/src/main/java/akka/camel/consume.java deleted file mode 100644 index cac399b162..0000000000 --- a/akka-camel-typed/src/main/java/akka/camel/consume.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (C) 2009-2010 Typesafe Inc. - */ - -package akka.camel; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation used by implementations of {@link akka.actor.TypedActor} - * (on method-level) to define consumer endpoints. - * - * @author Martin Krasser - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -public @interface consume { - - /** - * Consumer endpoint URI - */ - public abstract String value(); - - /** - * Route definition handler class for customizing route to annotated method. - * The handler class must have a default constructor. - */ - public abstract Class routeDefinitionHandler() - default RouteDefinitionIdentity.class; - -} diff --git a/akka-camel-typed/src/main/resources/META-INF/services/org/apache/camel/component/typed-actor b/akka-camel-typed/src/main/resources/META-INF/services/org/apache/camel/component/typed-actor deleted file mode 100644 index 02efe457e6..0000000000 --- a/akka-camel-typed/src/main/resources/META-INF/services/org/apache/camel/component/typed-actor +++ /dev/null @@ -1 +0,0 @@ -class=akka.camel.component.TypedActorComponent \ No newline at end of file diff --git a/akka-camel-typed/src/main/scala/akka/camel/TypedCamel.scala b/akka-camel-typed/src/main/scala/akka/camel/TypedCamel.scala deleted file mode 100644 index e2a6c0b35a..0000000000 --- a/akka-camel-typed/src/main/scala/akka/camel/TypedCamel.scala +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (C) 2009-2012 Typesafe Inc. - */ - -package akka.camel - -import org.apache.camel.CamelContext - -import akka.actor.Actor._ -import akka.actor._ -import akka.camel.component.TypedActorComponent - -/** - * Module that adds typed consumer actor support to akka-camel. It is automatically - * detected by CamelService if added to the classpath. - * - * @author Martin Krasser - */ -private[camel] object TypedCamel { - private var consumerPublisher: ActorRef = _ - private var publishRequestor: ActorRef = _ - - /** - * Adds the TypedActorComponent to context. - */ - def onCamelContextInit(context: CamelContext) { - context.addComponent(TypedActorComponent.InternalSchema, new TypedActorComponent) - } - - /** - * Configures a TypedConsumerPublishRequestor and a TypedConsumerPublisher - * and re-uses the activationTracker of service. - */ - def onCamelServiceStart(service: CamelService) { - consumerPublisher = new LocalActorRef(Props(new TypedConsumerPublisher(service.activationTracker)), Props.randomName, true) - publishRequestor = new LocalActorRef(Props(new TypedConsumerPublishRequestor), Props.randomName, true) - - registerPublishRequestor - - for (event ← PublishRequestor.pastActorRegisteredEvents) publishRequestor ! event - publishRequestor ! InitPublishRequestor(consumerPublisher) - } - - /** - * Stops the configured Configures TypedConsumerPublishRequestor and - * TypedConsumerPublisher. - */ - def onCamelServiceStop(service: CamelService) { - unregisterPublishRequestor - consumerPublisher.stop - } - - private def registerPublishRequestor: Unit = registry.addListener(publishRequestor) - private def unregisterPublishRequestor: Unit = registry.removeListener(publishRequestor) -} diff --git a/akka-camel-typed/src/main/scala/akka/camel/TypedConsumer.scala b/akka-camel-typed/src/main/scala/akka/camel/TypedConsumer.scala deleted file mode 100644 index c7b8059153..0000000000 --- a/akka-camel-typed/src/main/scala/akka/camel/TypedConsumer.scala +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (C) 2009-2012 Typesafe Inc. - */ - -package akka.camel - -import java.lang.reflect.Method -import java.lang.reflect.Proxy._ - -import akka.actor.{ LocalActorRef, TypedActor, ActorRef } -import akka.actor.TypedActor._ - -/** - * @author Martin Krasser - */ -private[camel] object TypedConsumer { - - /** - * Applies a function f to actorRef if actorRef - * references a typed consumer actor. A valid reference to a typed consumer actor is a - * local actor reference with a target actor that implements TypedActor and - * has at least one of its methods annotated with @consume (on interface or - * implementation class). For each @consume-annotated method, f - * is called with the corresponding method instance and the return value is - * added to a list which is then returned by this method. - */ - def withTypedConsumer[T](actorRef: ActorRef, typedActor: Option[AnyRef])(f: (AnyRef, Method) ⇒ T): List[T] = { - typedActor match { - case None ⇒ Nil - case Some(tc) ⇒ { - withConsumeAnnotatedMethodsOnInterfaces(tc, f) ++ - withConsumeAnnotatedMethodsonImplClass(tc, actorRef, f) - } - } - } - - private implicit def class2ProxyClass(c: Class[_]) = new ProxyClass(c) - - private def withConsumeAnnotatedMethodsOnInterfaces[T](tc: AnyRef, f: (AnyRef, Method) ⇒ T): List[T] = for { - i ← tc.getClass.allInterfaces - m ← i.getDeclaredMethods.toList - if (m.isAnnotationPresent(classOf[consume])) - } yield f(tc, m) - - private def withConsumeAnnotatedMethodsonImplClass[T](tc: AnyRef, actorRef: ActorRef, f: (AnyRef, Method) ⇒ T): List[T] = actorRef match { - case l: LocalActorRef ⇒ - val implClass = l.underlyingActorInstance.asInstanceOf[TypedActor.TypedActor[AnyRef, AnyRef]].me.getClass - for (m ← implClass.getDeclaredMethods.toList; if (m.isAnnotationPresent(classOf[consume]))) yield f(tc, m) - case _ ⇒ Nil - } - - private class ProxyClass(c: Class[_]) { - def allInterfaces: List[Class[_]] = allInterfaces(c.getInterfaces.toList) - def allInterfaces(is: List[Class[_]]): List[Class[_]] = is match { - case Nil ⇒ Nil - case x :: xs ⇒ x :: allInterfaces(x.getInterfaces.toList) ::: allInterfaces(xs) - } - } -} diff --git a/akka-camel-typed/src/main/scala/akka/camel/TypedConsumerPublisher.scala b/akka-camel-typed/src/main/scala/akka/camel/TypedConsumerPublisher.scala deleted file mode 100644 index 6822665bb9..0000000000 --- a/akka-camel-typed/src/main/scala/akka/camel/TypedConsumerPublisher.scala +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Copyright (C) 2009-2012 Typesafe Inc. - */ - -package akka.camel - -import java.lang.reflect.Method - -import akka.actor._ -import akka.camel.component.TypedActorComponent -import akka.event.EventHandler - -/** - * Concrete publish requestor that requests publication of typed consumer actor methods on - * TypedActorRegistered events and unpublication of typed consumer actor methods on - * TypedActorUnregistered events. - * - * @author Martin Krasser - */ -private[camel] class TypedConsumerPublishRequestor extends PublishRequestor { - def receiveActorRegistryEvent = { - case TypedActorRegistered(_, actor, typedActor) ⇒ for (event ← ConsumerMethodRegistered.eventsFor(actor, Option(typedActor))) deliverCurrentEvent(event) - case TypedActorUnregistered(_, actor, typedActor) ⇒ for (event ← ConsumerMethodUnregistered.eventsFor(actor, Option(typedActor))) deliverCurrentEvent(event) - case _ ⇒ () - } -} - -/** - * Publishes a typed consumer actor method on ConsumerMethodRegistered events and - * unpublishes a typed consumer actor method on ConsumerMethodUnregistered events. - * Publications are tracked by sending an activationTracker an EndpointActivated - * event, unpublications are tracked by sending an EndpointActivated event. - * - * @author Martin Krasser - */ -private[camel] class TypedConsumerPublisher(activationTracker: ActorRef) extends Actor { - import TypedConsumerPublisher._ - - def receive = { - case mr: ConsumerMethodRegistered ⇒ { - handleConsumerMethodRegistered(mr) - activationTracker ! EndpointActivated - } - case mu: ConsumerMethodUnregistered ⇒ { - handleConsumerMethodUnregistered(mu) - activationTracker ! EndpointDeactivated - } - case _ ⇒ { /* ignore */ } - } -} - -/** - * @author Martin Krasser - */ -private[camel] object TypedConsumerPublisher { - /** - * Creates a route to a typed actor method. - */ - def handleConsumerMethodRegistered(event: ConsumerMethodRegistered) { - CamelContextManager.mandatoryContext.addRoutes(new ConsumerMethodRouteBuilder(event)) - EventHandler.info(this, "published method %s of %s at endpoint %s" format (event.methodName, event.typedActor, event.endpointUri)) - } - - /** - * Stops the route to the already un-registered typed consumer actor method. - */ - def handleConsumerMethodUnregistered(event: ConsumerMethodUnregistered) { - CamelContextManager.mandatoryContext.stopRoute(event.methodUuid) - EventHandler.info(this, "unpublished method %s of %s from endpoint %s" format (event.methodName, event.typedActor, event.endpointUri)) - } -} - -/** - * Builder of a route to a typed consumer actor method. - * - * @author Martin Krasser - */ -private[camel] class ConsumerMethodRouteBuilder(event: ConsumerMethodRegistered) extends ConsumerRouteBuilder(event.endpointUri, event.methodUuid) { - protected def routeDefinitionHandler: RouteDefinitionHandler = event.routeDefinitionHandler - protected def targetUri = "%s:%s?method=%s" format (TypedActorComponent.InternalSchema, event.methodUuid, event.methodName) -} - -/** - * A typed consumer method (un)registration event. - */ -private[camel] trait ConsumerMethodEvent extends ConsumerEvent { - val actorRef: ActorRef - val typedActor: AnyRef - val method: Method - - val methodName = method.getName - val methodUuid = "%s_%s" format (uuid, methodName) - - lazy val routeDefinitionHandler = consumeAnnotation.routeDefinitionHandler.newInstance - lazy val consumeAnnotation = method.getAnnotation(classOf[consume]) - lazy val endpointUri = consumeAnnotation.value -} - -/** - * Event indicating that a typed consumer actor has been registered at the actor registry. For - * each @consume annotated typed actor method a separate event is created. - */ -private[camel] case class ConsumerMethodRegistered(actorRef: ActorRef, typedActor: AnyRef, method: Method) extends ConsumerMethodEvent - -/** - * Event indicating that a typed consumer actor has been unregistered from the actor registry. For - * each @consume annotated typed actor method a separate event is created. - */ -private[camel] case class ConsumerMethodUnregistered(actorRef: ActorRef, typedActor: AnyRef, method: Method) extends ConsumerMethodEvent - -/** - * @author Martin Krasser - */ -private[camel] object ConsumerMethodRegistered { - /** - * Creates a list of ConsumerMethodRegistered event messages for a typed consumer actor or an empty - * list if actorRef doesn't reference a typed consumer actor. - */ - def eventsFor(actorRef: ActorRef, typedActor: Option[AnyRef]): List[ConsumerMethodRegistered] = { - TypedConsumer.withTypedConsumer(actorRef, typedActor) { (tc, m) ⇒ - ConsumerMethodRegistered(actorRef, tc, m) - } - } -} - -/** - * @author Martin Krasser - */ -private[camel] object ConsumerMethodUnregistered { - /** - * Creates a list of ConsumerMethodUnregistered event messages for a typed consumer actor or an empty - * list if actorRef doesn't reference a typed consumer actor. - */ - def eventsFor(actorRef: ActorRef, typedActor: Option[AnyRef]): List[ConsumerMethodUnregistered] = { - TypedConsumer.withTypedConsumer(actorRef, typedActor) { (tc, m) ⇒ - ConsumerMethodUnregistered(actorRef, tc, m) - } - } -} diff --git a/akka-camel-typed/src/main/scala/akka/camel/component/TypedActorComponent.scala b/akka-camel-typed/src/main/scala/akka/camel/component/TypedActorComponent.scala deleted file mode 100644 index b446a1fab1..0000000000 --- a/akka-camel-typed/src/main/scala/akka/camel/component/TypedActorComponent.scala +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (C) 2009-2010 Typesafe Inc. - */ - -package akka.camel.component - -import java.util.Map -import java.util.concurrent.ConcurrentHashMap - -import org.apache.camel.CamelContext -import org.apache.camel.component.bean._ - -import akka.actor._ - -/** - * @author Martin Krasser - */ -object TypedActorComponent { - /** - * Default schema name for typed actor endpoint URIs. - */ - val InternalSchema = "typed-actor-internal" -} - -/** - * Camel component for exchanging messages with typed actors. This component - * tries to obtain the typed actor from Actor.registry if the - * schema is TypedActorComponent.InternalSchema. If the schema - * name is typed-actor this component tries to obtain the typed - * actor from the CamelContext's registry. - * - * @see org.apache.camel.component.bean.BeanComponent - * - * @author Martin Krasser - */ -class TypedActorComponent extends BeanComponent { - val typedActorRegistry = new ConcurrentHashMap[String, AnyRef] - - /** - * Creates an org.apache.camel.component.bean.BeanEndpoint with a custom - * bean holder that uses Actor.registry for getting access to typed actors - * (beans). - * - * @see akka.camel.component.TypedActorHolder - */ - override def createEndpoint(uri: String, remaining: String, parameters: Map[String, AnyRef]) = { - val endpoint = new BeanEndpoint(uri, this) - endpoint.setBeanName(remaining) - endpoint.setBeanHolder(createBeanHolder(uri, remaining)) - setProperties(endpoint.getProcessor, parameters) - endpoint - } - - private def createBeanHolder(uri: String, beanName: String) = - new TypedActorHolder(uri, getCamelContext, beanName).createCacheHolder -} - -/** - * org.apache.camel.component.bean.BeanHolder implementation that uses - * Actor.registry for getting access to typed actors. - * - * @author Martin Krasser - */ -class TypedActorHolder(uri: String, context: CamelContext, name: String) - extends RegistryBean(context, name) { - - /** - * Returns an akka.camel.component.BeanInfo instance. - */ - override def getBeanInfo: BeanInfo = - new BeanInfo(getContext, getBean.getClass, getParameterMappingStrategy) - - /** - * Obtains a typed actor from Actor.registry if the schema is - * TypedActorComponent.InternalSchema. If the schema name is - * typed-actor this method obtains the typed actor from the - * CamelContext's registry. - * - * @return a typed actor or null. - */ - override def getBean: AnyRef = { - val internal = uri.startsWith(TypedActorComponent.InternalSchema) - if (internal) Actor.registry.local.typedActorFor(uuidFrom(getName)) getOrElse null else super.getBean - } -} diff --git a/akka-camel-typed/src/test/java/akka/camel/SampleErrorHandlingTypedConsumer.java b/akka-camel-typed/src/test/java/akka/camel/SampleErrorHandlingTypedConsumer.java deleted file mode 100644 index d8a8c79440..0000000000 --- a/akka-camel-typed/src/test/java/akka/camel/SampleErrorHandlingTypedConsumer.java +++ /dev/null @@ -1,11 +0,0 @@ -package akka.camel; - -/** - * @author Martin Krasser - */ -public interface SampleErrorHandlingTypedConsumer { - - @consume(value="direct:error-handler-test-java-typed", routeDefinitionHandler=SampleRouteDefinitionHandler.class) - String willFail(String s); - -} diff --git a/akka-camel-typed/src/test/java/akka/camel/SampleErrorHandlingTypedConsumerImpl.java b/akka-camel-typed/src/test/java/akka/camel/SampleErrorHandlingTypedConsumerImpl.java deleted file mode 100644 index 89b3948b00..0000000000 --- a/akka-camel-typed/src/test/java/akka/camel/SampleErrorHandlingTypedConsumerImpl.java +++ /dev/null @@ -1,12 +0,0 @@ -package akka.camel; - -/** - * @author Martin Krasser - */ -public class SampleErrorHandlingTypedConsumerImpl implements SampleErrorHandlingTypedConsumer { - - public String willFail(String s) { - throw new RuntimeException(String.format("error: %s", s)); - } - -} diff --git a/akka-camel-typed/src/test/java/akka/camel/SampleRemoteTypedConsumer.java b/akka-camel-typed/src/test/java/akka/camel/SampleRemoteTypedConsumer.java deleted file mode 100644 index 41a3c3f057..0000000000 --- a/akka-camel-typed/src/test/java/akka/camel/SampleRemoteTypedConsumer.java +++ /dev/null @@ -1,12 +0,0 @@ -package akka.camel; - -import akka.camel.consume; - -/** - * @author Martin Krasser - */ -public interface SampleRemoteTypedConsumer { - - @consume("direct:remote-typed-consumer") - public String foo(String s); -} diff --git a/akka-camel-typed/src/test/java/akka/camel/SampleRemoteTypedConsumerImpl.java b/akka-camel-typed/src/test/java/akka/camel/SampleRemoteTypedConsumerImpl.java deleted file mode 100644 index 067fb4eda6..0000000000 --- a/akka-camel-typed/src/test/java/akka/camel/SampleRemoteTypedConsumerImpl.java +++ /dev/null @@ -1,12 +0,0 @@ -package akka.camel; - -/** - * @author Martin Krasser - */ -public class SampleRemoteTypedConsumerImpl implements SampleRemoteTypedConsumer { - - public String foo(String s) { - return String.format("remote typed actor: %s", s); - } - -} diff --git a/akka-camel-typed/src/test/java/akka/camel/SampleRouteDefinitionHandler.java b/akka-camel-typed/src/test/java/akka/camel/SampleRouteDefinitionHandler.java deleted file mode 100644 index f1a99aa7d4..0000000000 --- a/akka-camel-typed/src/test/java/akka/camel/SampleRouteDefinitionHandler.java +++ /dev/null @@ -1,14 +0,0 @@ -package akka.camel; - -import org.apache.camel.builder.Builder; -import org.apache.camel.model.ProcessorDefinition; -import org.apache.camel.model.RouteDefinition; - -/** - * @author Martin Krasser - */ -public class SampleRouteDefinitionHandler implements RouteDefinitionHandler { - public ProcessorDefinition onRouteDefinition(RouteDefinition rd) { - return rd.onException(Exception.class).handled(true).transform(Builder.exceptionMessage()).end(); - } -} diff --git a/akka-camel-typed/src/test/java/akka/camel/SampleTypedActor.java b/akka-camel-typed/src/test/java/akka/camel/SampleTypedActor.java deleted file mode 100644 index 798d07a66c..0000000000 --- a/akka-camel-typed/src/test/java/akka/camel/SampleTypedActor.java +++ /dev/null @@ -1,9 +0,0 @@ -package akka.camel; - -/** - * @author Martin Krasser - */ -public interface SampleTypedActor { - - public String foo(String s); -} diff --git a/akka-camel-typed/src/test/java/akka/camel/SampleTypedActorImpl.java b/akka-camel-typed/src/test/java/akka/camel/SampleTypedActorImpl.java deleted file mode 100644 index 93d6cd9395..0000000000 --- a/akka-camel-typed/src/test/java/akka/camel/SampleTypedActorImpl.java +++ /dev/null @@ -1,14 +0,0 @@ -package akka.camel; - -import akka.actor.TypedActor; - -/** - * @author Martin Krasser - */ -public class SampleTypedActorImpl implements SampleTypedActor { - - public String foo(String s) { - return String.format("foo: %s", s); - } - -} diff --git a/akka-camel-typed/src/test/java/akka/camel/SampleTypedConsumer.java b/akka-camel-typed/src/test/java/akka/camel/SampleTypedConsumer.java deleted file mode 100644 index 26283d8e61..0000000000 --- a/akka-camel-typed/src/test/java/akka/camel/SampleTypedConsumer.java +++ /dev/null @@ -1,20 +0,0 @@ -package akka.camel; - -import org.apache.camel.Body; -import org.apache.camel.Header; - -import akka.camel.consume; - -/** - * @author Martin Krasser - */ -public interface SampleTypedConsumer { - - public String m1(String b, String h); - public String m2(@Body String b, @Header("test") String h); - public String m3(@Body String b, @Header("test") String h); - - @consume("direct:m4") - public String m4(@Body String b, @Header("test") String h); - public void m5(@Body String b, @Header("test") String h); -} diff --git a/akka-camel-typed/src/test/java/akka/camel/SampleTypedConsumerImpl.java b/akka-camel-typed/src/test/java/akka/camel/SampleTypedConsumerImpl.java deleted file mode 100644 index 8a402133f6..0000000000 --- a/akka-camel-typed/src/test/java/akka/camel/SampleTypedConsumerImpl.java +++ /dev/null @@ -1,28 +0,0 @@ -package akka.camel; - -/** - * @author Martin Krasser - */ -public class SampleTypedConsumerImpl implements SampleTypedConsumer { - - public String m1(String b, String h) { - return "m1: " + b + " " + h; - } - - @consume("direct:m2") - public String m2(String b, String h) { - return "m2: " + b + " " + h; - } - - @consume("direct:m3") - public String m3(String b, String h) { - return "m3: " + b + " " + h; - } - - public String m4(String b, String h) { - return "m4: " + b + " " + h; - } - - public void m5(String b, String h) { - } -} diff --git a/akka-camel-typed/src/test/java/akka/camel/SampleTypedSingleConsumer.java b/akka-camel-typed/src/test/java/akka/camel/SampleTypedSingleConsumer.java deleted file mode 100644 index ff0b7bc715..0000000000 --- a/akka-camel-typed/src/test/java/akka/camel/SampleTypedSingleConsumer.java +++ /dev/null @@ -1,13 +0,0 @@ -package akka.camel; - -import akka.camel.consume; - -/** - * @author Martin Krasser - */ -public interface SampleTypedSingleConsumer { - - @consume("direct:foo") - public void foo(String b); - -} diff --git a/akka-camel-typed/src/test/java/akka/camel/SampleTypedSingleConsumerImpl.java b/akka-camel-typed/src/test/java/akka/camel/SampleTypedSingleConsumerImpl.java deleted file mode 100644 index fa4807eec4..0000000000 --- a/akka-camel-typed/src/test/java/akka/camel/SampleTypedSingleConsumerImpl.java +++ /dev/null @@ -1,11 +0,0 @@ -package akka.camel; - -/** - * @author Martin Krasser - */ -public class SampleTypedSingleConsumerImpl implements SampleTypedSingleConsumer { - - public void foo(String b) { - } - -} diff --git a/akka-camel-typed/src/test/java/akka/camel/TypedConsumerJavaTestBase.java b/akka-camel-typed/src/test/java/akka/camel/TypedConsumerJavaTestBase.java deleted file mode 100644 index d6ea1da9f4..0000000000 --- a/akka-camel-typed/src/test/java/akka/camel/TypedConsumerJavaTestBase.java +++ /dev/null @@ -1,52 +0,0 @@ -package akka.camel; - -import akka.actor.Actor; -import akka.actor.TypedActor; -import akka.actor.Props; -import akka.util.Timeout; -import akka.dispatch.Dispatchers; -import akka.japi.SideEffect; -import akka.util.FiniteDuration; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import static akka.actor.Actors.*; -import static akka.camel.CamelContextManager.*; -import static akka.camel.CamelServiceManager.*; - -import static org.junit.Assert.*; - -/** - * @author Martin Krasser - */ -public class TypedConsumerJavaTestBase { - - private SampleErrorHandlingTypedConsumer consumer; - - @BeforeClass - public static void setUpBeforeClass() { - startCamelService(); - } - - @AfterClass - public static void tearDownAfterClass() { - stopCamelService(); - registry().local().shutdownAll(); - } - - @Test - public void shouldHandleExceptionThrownByTypedActorAndGenerateCustomResponse() { - getMandatoryService().awaitEndpointActivation(1, new SideEffect() { - public void apply() { - consumer = TypedActor.typedActorOf( - SampleErrorHandlingTypedConsumer.class, - SampleErrorHandlingTypedConsumerImpl.class, - (new Props()).withTimeout(new Timeout(new FiniteDuration(5000, "millis")))); - } - }); - String result = getMandatoryTemplate().requestBody("direct:error-handler-test-java-typed", "hello", String.class); - assertEquals("error: hello", result); - } -} diff --git a/akka-camel-typed/src/test/scala/akka/camel/TypedCamelTestSupport.scala b/akka-camel-typed/src/test/scala/akka/camel/TypedCamelTestSupport.scala deleted file mode 100644 index 42b38e5bb3..0000000000 --- a/akka-camel-typed/src/test/scala/akka/camel/TypedCamelTestSupport.scala +++ /dev/null @@ -1,66 +0,0 @@ -package akka.camel - -import java.util.concurrent.CountDownLatch - -import collection.mutable.Buffer - -import akka.actor.Actor - -object TypedCamelTestSupport { - type Handler = PartialFunction[Any, Any] - - trait TestActor extends Actor { - def receive = { - case msg ⇒ { - handler(msg) - } - } - - def handler: Handler - } - - trait Countdown { this: Actor ⇒ - var latch: CountDownLatch = new CountDownLatch(0) - def countdown: Handler = { - case SetExpectedMessageCount(num) ⇒ { - latch = new CountDownLatch(num) - sender ! latch - } - case msg ⇒ latch.countDown - } - } - - trait Respond { this: Actor ⇒ - def respond: Handler = { - case msg: Message ⇒ sender ! response(msg) - } - - def response(msg: Message): Any = "Hello %s" format msg.body - } - - trait Retain { this: Actor ⇒ - val messages = Buffer[Any]() - - def retain: Handler = { - case GetRetainedMessage ⇒ sender ! messages.last - case GetRetainedMessages(p) ⇒ sender ! messages.filter(p).toList - case msg ⇒ { - messages += msg - msg - } - } - } - - trait Noop { this: Actor ⇒ - def noop: Handler = { - case msg ⇒ msg - } - } - - case class SetExpectedMessageCount(num: Int) - case class GetRetainedMessage() - case class GetRetainedMessages(p: Any ⇒ Boolean) { - def this() = this(_ ⇒ true) - } -} - diff --git a/akka-camel-typed/src/test/scala/akka/camel/TypedConsumerJavaTest.scala b/akka-camel-typed/src/test/scala/akka/camel/TypedConsumerJavaTest.scala deleted file mode 100644 index d887a378ad..0000000000 --- a/akka-camel-typed/src/test/scala/akka/camel/TypedConsumerJavaTest.scala +++ /dev/null @@ -1,5 +0,0 @@ -package akka.camel - -import org.scalatest.junit.JUnitSuite - -class TypedConsumerJavaTest extends TypedConsumerJavaTestBase with JUnitSuite diff --git a/akka-camel-typed/src/test/scala/akka/camel/TypedConsumerPublishRequestorTest.scala b/akka-camel-typed/src/test/scala/akka/camel/TypedConsumerPublishRequestorTest.scala deleted file mode 100644 index 322a0412c5..0000000000 --- a/akka-camel-typed/src/test/scala/akka/camel/TypedConsumerPublishRequestorTest.scala +++ /dev/null @@ -1,104 +0,0 @@ -package akka.camel - -import java.util.concurrent.{ CountDownLatch, TimeUnit } - -import org.junit.{ Before, After, Test } -import org.scalatest.junit.JUnitSuite -import akka.util.duration._ -import akka.actor._ -import akka.actor.Actor._ -import akka.camel.TypedCamelTestSupport.{ SetExpectedMessageCount ⇒ SetExpectedTestMessageCount, _ } -import akka.dispatch.Await - -class TypedConsumerPublishRequestorTest extends JUnitSuite { - import TypedConsumerPublishRequestorTest._ - - var publisher: ActorRef = _ - var requestor: ActorRef = _ - var consumer: ActorRef = _ - - val ascendingMethodName = (r1: ConsumerMethodRegistered, r2: ConsumerMethodRegistered) ⇒ - r1.method.getName < r2.method.getName - - @Before - def setUp{ - publisher = actorOf(Props(new TypedConsumerPublisherMock) - requestor = actorOf(Props(new TypedConsumerPublishRequestor) - requestor ! InitPublishRequestor(publisher) - consumer = actorOf(Props(new Actor with Consumer { - def endpointUri = "mock:test" - protected def receive = null - }) - } - - @After - def tearDown = { - Actor.registry.removeListener(requestor); - Actor.registry.local.shutdownAll - } - - @Test - def shouldReceiveOneConsumerMethodRegisteredEvent = { - Actor.registry.addListener(requestor) - val latch = Await.result((publisher ? SetExpectedTestMessageCount(1)).mapTo[CountDownLatch], 3 seconds) - val obj = TypedActor.typedActorOf(classOf[SampleTypedSingleConsumer], classOf[SampleTypedSingleConsumerImpl], Props()) - assert(latch.await(5000, TimeUnit.MILLISECONDS)) - val event = Await.result((publisher ? GetRetainedMessage).mapTo[ConsumerMethodRegistered], 3 seconds) - assert(event.endpointUri === "direct:foo") - assert(event.typedActor === obj) - assert(event.methodName === "foo") - } - - @Test - def shouldReceiveOneConsumerMethodUnregisteredEvent = { - val latch = Await.result((publisher ? SetExpectedTestMessageCount(1)).mapTo[CountDownLatch], 3 seconds) - Actor.registry.addListener(requestor) - - val obj = TypedActor.typedActorOf(classOf[SampleTypedSingleConsumer], classOf[SampleTypedSingleConsumerImpl], Props()) - - assert(latch.await(5000, TimeUnit.MILLISECONDS)) - - val ignorableEvent = Await.result((publisher ? GetRetainedMessage).mapTo[ConsumerMethodRegistered], 3 seconds) - - val latch2 = Await.result((publisher ? SetExpectedTestMessageCount(1)).mapTo[CountDownLatch], 3 seconds) - TypedActor.stop(obj) - - assert(latch2.await(5000, TimeUnit.MILLISECONDS)) - - val event = Await.result((publisher ? GetRetainedMessage).mapTo[ConsumerMethodUnregistered], 3 seconds) - - assert(event.endpointUri === "direct:foo") - assert(event.typedActor === obj) - assert(event.methodName === "foo") - } - - @Test - def shouldReceiveThreeConsumerMethodRegisteredEvents = { - Actor.registry.addListener(requestor) - val latch = Await.result((publisher ? SetExpectedTestMessageCount(3)).mapTo[CountDownLatch], 3 seconds) - val obj = TypedActor.typedActorOf(classOf[SampleTypedConsumer], classOf[SampleTypedConsumerImpl], Props()) - assert(latch.await(5000, TimeUnit.MILLISECONDS)) - val request = GetRetainedMessages(_.isInstanceOf[ConsumerMethodRegistered]) - val events = Await.result((publisher ? request).mapTo[List[ConsumerMethodRegistered]], 3 seconds) - assert(events.map(_.method.getName).sortWith(_ < _) === List("m2", "m3", "m4")) - } - - @Test - def shouldReceiveThreeConsumerMethodUnregisteredEvents = { - val obj = TypedActor.typedActorOf(classOf[SampleTypedConsumer], classOf[SampleTypedConsumerImpl], Props()) - val latch = Await.result((publisher ? SetExpectedTestMessageCount(3)).mapTo[CountDownLatch], 3 seconds) - Actor.registry.addListener(requestor) - TypedActor.stop(obj) - assert(latch.await(5000, TimeUnit.MILLISECONDS)) - val request = GetRetainedMessages(_.isInstanceOf[ConsumerMethodUnregistered]) - val events = Await.result((publisher ? request).mapTo[List[ConsumerMethodUnregistered]], 3 seconds) - assert(events.map(_.method.getName).sortWith(_ < _) === List("m2", "m3", "m4")) - } -} - -object TypedConsumerPublishRequestorTest { - class TypedConsumerPublisherMock extends TestActor with Retain with Countdown { - def handler = retain andThen countdown - } -} - diff --git a/akka-camel-typed/src/test/scala/akka/camel/TypedConsumerScalaTest.scala b/akka-camel-typed/src/test/scala/akka/camel/TypedConsumerScalaTest.scala deleted file mode 100644 index 20703bdffe..0000000000 --- a/akka-camel-typed/src/test/scala/akka/camel/TypedConsumerScalaTest.scala +++ /dev/null @@ -1,99 +0,0 @@ -package akka.camel - -import org.apache.camel.CamelExecutionException - -import org.scalatest.{ BeforeAndAfterAll, WordSpec } -import org.scalatest.matchers.MustMatchers - -import akka.actor.Actor._ -import akka.actor._ - -/** - * @author Martin Krasser - */ -class TypedConsumerScalaTest extends WordSpec with BeforeAndAfterAll with MustMatchers { - import CamelContextManager.mandatoryTemplate - import TypedConsumerScalaTest._ - - var service: CamelService = _ - - override protected def beforeAll = { - registry.local.shutdownAll - service = CamelServiceManager.startCamelService - } - - override protected def afterAll = { - service.stop - registry.local.shutdownAll - } - - "A responding, typed consumer" when { - var actor: SampleTypedConsumer = null - "started" must { - "support in-out message exchanges via its endpoints" in { - service.awaitEndpointActivation(3) { - actor = TypedActor.typedActorOf(classOf[SampleTypedConsumer], classOf[SampleTypedConsumerImpl], Props()) - } must be(true) - mandatoryTemplate.requestBodyAndHeader("direct:m2", "x", "test", "y") must equal("m2: x y") - mandatoryTemplate.requestBodyAndHeader("direct:m3", "x", "test", "y") must equal("m3: x y") - mandatoryTemplate.requestBodyAndHeader("direct:m4", "x", "test", "y") must equal("m4: x y") - } - } - "stopped" must { - "not support in-out message exchanges via its endpoints" in { - service.awaitEndpointDeactivation(3) { - TypedActor.stop(actor) - } must be(true) - intercept[CamelExecutionException] { - mandatoryTemplate.requestBodyAndHeader("direct:m2", "x", "test", "y") - } - intercept[CamelExecutionException] { - mandatoryTemplate.requestBodyAndHeader("direct:m3", "x", "test", "y") - } - intercept[CamelExecutionException] { - mandatoryTemplate.requestBodyAndHeader("direct:m4", "x", "test", "y") - } - } - } - } - - "A responding, typed consumer (Scala)" when { - var actor: TestTypedConsumer = null - "started" must { - "support in-out message exchanges via its endpoints" in { - service.awaitEndpointActivation(2) { - actor = TypedActor.typedActorOf(classOf[TestTypedConsumer], classOf[TestTypedConsumerImpl], Props()) - } must be(true) - mandatoryTemplate.requestBody("direct:publish-test-3", "x") must equal("foo: x") - mandatoryTemplate.requestBody("direct:publish-test-4", "x") must equal("bar: x") - } - } - "stopped" must { - "not support in-out message exchanges via its endpoints" in { - service.awaitEndpointDeactivation(2) { - TypedActor.stop(actor) - } must be(true) - intercept[CamelExecutionException] { - mandatoryTemplate.requestBody("direct:publish-test-3", "x") - } - intercept[CamelExecutionException] { - mandatoryTemplate.requestBody("direct:publish-test-4", "x") - } - } - } - } -} - -object TypedConsumerScalaTest { - trait TestTypedConsumer { - @consume("direct:publish-test-3") - def foo(s: String): String - def bar(s: String): String - } - - class TestTypedConsumerImpl extends TestTypedConsumer { - def foo(s: String) = "foo: %s" format s - @consume("direct:publish-test-4") - def bar(s: String) = "bar: %s" format s - } -} diff --git a/akka-camel-typed/src/test/scala/akka/camel/component/TypedActorComponentFeatureTest.scala b/akka-camel-typed/src/test/scala/akka/camel/component/TypedActorComponentFeatureTest.scala deleted file mode 100644 index d1084f2719..0000000000 --- a/akka-camel-typed/src/test/scala/akka/camel/component/TypedActorComponentFeatureTest.scala +++ /dev/null @@ -1,113 +0,0 @@ -package akka.camel.component - -import org.apache.camel._ -import org.apache.camel.builder.RouteBuilder -import org.apache.camel.impl.{ DefaultCamelContext, SimpleRegistry } -import org.scalatest.{ BeforeAndAfterEach, BeforeAndAfterAll, FeatureSpec } - -import akka.actor.{ Actor, TypedActor, Props } -import akka.camel._ - -/** - * @author Martin Krasser - */ -class TypedActorComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll with BeforeAndAfterEach { - import TypedActorComponentFeatureTest._ - import CamelContextManager.mandatoryTemplate - - var typedConsumerUuid: String = _ - - override protected def beforeAll = { - val typedActor = TypedActor.typedActorOf( - classOf[SampleTypedActor], - classOf[SampleTypedActorImpl], Props()) // not a consumer - val typedConsumer = TypedActor.typedActorOf( - classOf[SampleTypedConsumer], - classOf[SampleTypedConsumerImpl], Props()) - - typedConsumerUuid = TypedActor.getActorRefFor(typedConsumer).uuid.toString - - val registry = new SimpleRegistry - // external registration - registry.put("ta", typedActor) - - CamelContextManager.init(new DefaultCamelContext(registry)) - CamelContextManager.mandatoryContext.addRoutes(new CustomRouteBuilder) - CamelContextManager.start - } - - override protected def afterAll = { - CamelContextManager.stop - Actor.registry.local.shutdownAll - } - - feature("Communicate with an internally-registered typed actor using typed-actor-internal endpoint URIs") { - import TypedActorComponent.InternalSchema - import ExchangePattern._ - - scenario("two-way communication with method returning String") { - val result1 = mandatoryTemplate.requestBodyAndHeader("%s:%s?method=m2" format (InternalSchema, typedConsumerUuid), "x", "test", "y") - val result2 = mandatoryTemplate.requestBodyAndHeader("%s:%s?method=m4" format (InternalSchema, typedConsumerUuid), "x", "test", "y") - assert(result1 === "m2: x y") - assert(result2 === "m4: x y") - } - - scenario("two-way communication with method returning void") { - val result = mandatoryTemplate.requestBodyAndHeader("%s:%s?method=m5" format (InternalSchema, typedConsumerUuid), "x", "test", "y") - assert(result === "x") // returns initial body - } - - scenario("one-way communication with method returning String") { - val result = mandatoryTemplate.send("%s:%s?method=m2" format (InternalSchema, typedConsumerUuid), InOnly, new Processor { - def process(exchange: Exchange) = { - exchange.getIn.setBody("x") - exchange.getIn.setHeader("test", "y") - } - }); - assert(result.getPattern === InOnly) - assert(result.getIn.getBody === "m2: x y") - assert(result.getOut.getBody === null) - } - - scenario("one-way communication with method returning void") { - val result = mandatoryTemplate.send("%s:%s?method=m5" format (InternalSchema, typedConsumerUuid), InOnly, new Processor { - def process(exchange: Exchange) = { - exchange.getIn.setBody("x") - exchange.getIn.setHeader("test", "y") - } - }); - assert(result.getPattern === InOnly) - assert(result.getIn.getBody === "x") - assert(result.getOut.getBody === null) - } - - } - - feature("Communicate with an internally-registered typed actor using typed-actor endpoint URIs") { - scenario("communication not possible") { - intercept[ResolveEndpointFailedException] { - mandatoryTemplate.requestBodyAndHeader("typed-actor:%s?method=m2" format typedConsumerUuid, "x", "test", "y") - } - } - } - - feature("Communicate with an externally-registered typed actor using typed-actor endpoint URIs") { - scenario("two-way communication with method returning String") { - val result = mandatoryTemplate.requestBody("typed-actor:ta?method=foo", "test") - assert(result === "foo: test") - } - - scenario("two-way communication with method returning String via custom route") { - val result = mandatoryTemplate.requestBody("direct:test", "test") - assert(result === "foo: test") - } - } -} - -object TypedActorComponentFeatureTest { - class CustomRouteBuilder extends RouteBuilder { - def configure = { - from("direct:test").to("typed-actor:ta?method=foo") - } - } -} diff --git a/akka-camel/src/main/scala/akka/camel/Activation.scala b/akka-camel/src/main/scala/akka/camel/Activation.scala index 83d928dd8b..cf07a19171 100644 --- a/akka-camel/src/main/scala/akka/camel/Activation.scala +++ b/akka-camel/src/main/scala/akka/camel/Activation.scala @@ -11,15 +11,21 @@ import java.util.concurrent.TimeoutException import akka.actor.{ ActorSystem, Props, ActorRef } import akka.pattern._ +/** + * Activation trait that can be used to wait on activation or de-activation of Camel endpoints. + * The Camel endpoints are activated asynchronously. This trait can signal when an endpoint is activated or de-activated. + */ trait Activation { import akka.dispatch.Await def system: ActorSystem - private[camel] val activationTracker = system.actorOf(Props[ActivationTracker]) + + private val activationTracker = system.actorOf(Props[ActivationTracker]) /** * Awaits for endpoint to be activated. It blocks until the endpoint is registered in camel context or timeout expires. - * + * @param endpoint the endpoint to wait for to be activated + * @param timeout the timeout for the wait * @throws akka.camel.ActivationTimeoutException if endpoint is not activated within timeout. */ def awaitActivation(endpoint: ActorRef, timeout: Duration): ActorRef = { @@ -32,7 +38,8 @@ trait Activation { /** * Awaits for endpoint to be de-activated. It is blocking until endpoint is unregistered in camel context or timeout expires. - * + * @param endpoint the endpoint to wait for to be de-activated + * @param timeout the timeout for the wait * @throws akka.camel.DeActivationTimeoutException if endpoint is not de-activated within timeout. */ def awaitDeactivation(endpoint: ActorRef, timeout: Duration) { @@ -44,7 +51,9 @@ trait Activation { } /** - * Similar to `awaitActivation` but returns future instead. + * Similar to `awaitActivation` but returns a future instead. + * @param endpoint the endpoint to be activated + * @param timeout the timeout for the Future */ def activationFutureFor(endpoint: ActorRef, timeout: Duration): Future[ActorRef] = { (activationTracker.ask(AwaitActivation(endpoint))(Timeout(timeout))).map[ActorRef] { @@ -54,20 +63,32 @@ trait Activation { } /** - * Similar to awaitDeactivation but returns future instead. + * Similar to awaitDeactivation but returns a future instead. + * @param endpoint the endpoint to be deactivated + * @param timeout the timeout of the Future */ def deactivationFutureFor(endpoint: ActorRef, timeout: Duration): Future[Unit] = { (activationTracker.ask(AwaitDeActivation(endpoint))(Timeout(timeout))).map[Unit] { - case EndpointDeActivated(_) ⇒ {} + case EndpointDeActivated(_) ⇒ () case EndpointFailedToDeActivate(_, cause) ⇒ throw cause } } } +/** + * An exception for when a timeout has occurred during deactivation of an endpoint + * @param endpoint the endpoint that could not be de-activated in time + * @param timeout the timeout + */ class DeActivationTimeoutException(endpoint: ActorRef, timeout: Duration) extends TimeoutException { override def getMessage = "Timed out after %s, while waiting for de-activation of %s" format (timeout, endpoint.path) } +/** + * An exception for when a timeout has occurred during the activation of an endpoint + * @param endpoint the endpoint that could not be activated in time + * @param timeout the timeout + */ class ActivationTimeoutException(endpoint: ActorRef, timeout: Duration) extends TimeoutException { override def getMessage = "Timed out after %s, while waiting for activation of %s" format (timeout, endpoint.path) } \ No newline at end of file diff --git a/akka-camel/src/main/scala/akka/camel/Camel.scala b/akka-camel/src/main/scala/akka/camel/Camel.scala index 7aed550978..085aad5316 100644 --- a/akka-camel/src/main/scala/akka/camel/Camel.scala +++ b/akka-camel/src/main/scala/akka/camel/Camel.scala @@ -11,6 +11,7 @@ import org.apache.camel.{ ProducerTemplate, CamelContext } //TODO complete this doc /** * Camel trait encapsulates the underlying camel machinery. + * '''Note:''' `CamelContext` and `ProducerTemplate` are stopped when the associated actor system is shut down. * */ trait Camel extends ConsumerRegistry with ProducerRegistry with Extension with Activation { @@ -30,30 +31,6 @@ trait Camel extends ConsumerRegistry with ProducerRegistry with Extension with A */ def template: ProducerTemplate - /** - * Associated `ActorSystem`. - * - *

It can be used to start producers, consumers or any other actors which need to interact with camel, - * for example: - * {{{ - * val system = ActorSystem("test") - * system.actorOf(Props[SysOutConsumer]) - * - * class SysOutConsumer extends Consumer { - * def endpointUri = "file://data/input/CamelConsumer" - * - * protected def receive = { - * case msg: Message ⇒ { - * printf("Received '%s'\\n", msg.bodyAs[String]) - * } - * } - * } - * }}} - * '''Note:''' This actor system is responsible for stopping the underlying camel instance. - * - * @see [[akka.camel.CamelExtension]] - */ - def system: ActorSystem } /** @@ -75,10 +52,12 @@ object CamelExtension extends ExtensionId[Camel] with ExtensionIdProvider { * Creates a new instance of Camel and makes sure it gets stopped when the actor system is shutdown. */ def createExtension(system: ExtendedActorSystem) = { - val camel = new DefaultCamel(system).start; + val camel = new DefaultCamel(system).start system.registerOnTermination(camel.shutdown()) camel } - def lookup() = CamelExtension + def lookup(): ExtensionId[Camel] = CamelExtension + + override def get(system: ActorSystem): Camel = super.get(system) } \ No newline at end of file diff --git a/akka-camel/src/main/scala/akka/camel/Message.scala b/akka-camel/src/main/scala/akka/camel/CamelMessage.scala similarity index 57% rename from akka-camel/src/main/scala/akka/camel/Message.scala rename to akka-camel/src/main/scala/akka/camel/CamelMessage.scala index e062b2f2a6..afc3d885d8 100644 --- a/akka-camel/src/main/scala/akka/camel/Message.scala +++ b/akka-camel/src/main/scala/akka/camel/CamelMessage.scala @@ -9,18 +9,18 @@ import java.util.{ Map ⇒ JMap, Set ⇒ JSet } import scala.collection.JavaConversions._ import akka.japi.{ Function ⇒ JFunction } -import org.apache.camel.{ CamelContext, Message ⇒ CamelMessage } +import org.apache.camel.{ CamelContext, Message ⇒ JCamelMessage } /** * An immutable representation of a Camel message. * * @author Martin Krasser */ -case class Message(body: Any, headers: Map[String, Any]) { +case class CamelMessage(body: Any, headers: Map[String, Any]) { def this(body: Any, headers: JMap[String, Any]) = this(body, headers.toMap) //for Java - override def toString = "Message(%s, %s)" format (body, headers) + override def toString = "CamelMessage(%s, %s)" format (body, headers) /** * Returns those headers from this message whose name is contained in names. @@ -60,73 +60,71 @@ case class Message(body: Any, headers: Map[String, Any]) { def getHeader(name: String): Any = headers(name) /** - * Creates a Message with a transformed body using a transformer function. + * Creates a CamelMessage with a transformed body using a transformer function. */ - def mapBody[A, B](transformer: A ⇒ B): Message = withBody(transformer(body.asInstanceOf[A])) + def mapBody[A, B](transformer: A ⇒ B): CamelMessage = withBody(transformer(body.asInstanceOf[A])) /** - * Creates a Message with a transformed body using a transformer function. + * Creates a CamelMessage with a transformed body using a transformer function. *

* Java API */ - def mapBody[A, B](transformer: JFunction[A, B]): Message = withBody(transformer(body.asInstanceOf[A])) + def mapBody[A, B](transformer: JFunction[A, B]): CamelMessage = withBody(transformer(body.asInstanceOf[A])) /** - * Creates a Message with a given body. + * Creates a CamelMessage with a given body. */ - def withBody(body: Any) = Message(body, this.headers) + def withBody(body: Any) = CamelMessage(body, this.headers) /** - * Creates a new Message with given headers. + * Creates a new CamelMessage with given headers. */ - def withHeaders[A](headers: Map[String, A]): Message = copy(this.body, headers) + def withHeaders[A](headers: Map[String, A]): CamelMessage = copy(this.body, headers) /** - * Creates a new Message with given headers. A copy of the headers map is made. + * Creates a new CamelMessage with given headers. A copy of the headers map is made. *

* Java API */ - def withHeaders[A](headers: JMap[String, A]): Message = withHeaders(headers.toMap) + def withHeaders[A](headers: JMap[String, A]): CamelMessage = withHeaders(headers.toMap) /** - * Creates a new Message with given headers added to the current headers. + * Creates a new CamelMessage with given headers added to the current headers. */ - def plusHeaders[A](headers: Map[String, A]): Message = copy(this.body, this.headers ++ headers) + def addHeaders[A](headers: Map[String, A]): CamelMessage = copy(this.body, this.headers ++ headers) /** - * Creates a new Message with given headers added to the current headers. + * Creates a new CamelMessage with given headers added to the current headers. * A copy of the headers map is made. *

* Java API */ - def plusHeaders[A](headers: JMap[String, A]): Message = plusHeaders(headers.toMap) + def addHeaders[A](headers: JMap[String, A]): CamelMessage = addHeaders(headers.toMap) /** - * Creates a new Message with the given header added to the current headers. + * Creates a new CamelMessage with the given header added to the current headers. */ - def plusHeader(header: (String, Any)): Message = copy(this.body, this.headers + header) + def addHeader(header: (String, Any)): CamelMessage = copy(this.body, this.headers + header) /** - * Creates a new Message with the given header, represented by name and + * Creates a new CamelMessage with the given header, represented by name and * value added to the existing headers. *

* Java API */ - def plusHeader(name: String, value: Any): Message = plusHeader((name, value)) + def addHeader(name: String, value: Any): CamelMessage = addHeader((name, value)) /** - * Creates a new Message where the header with given headerName is removed from + * Creates a new CamelMessage where the header with given headerName is removed from * the existing headers. */ def withoutHeader(headerName: String) = copy(this.body, this.headers - headerName) - def copyContentTo(to: CamelMessage) = { + def copyContentTo(to: JCamelMessage) = { to.setBody(this.body) for ((name, value) ← this.headers) to.getHeaders.put(name, value.asInstanceOf[AnyRef]) } -} -class RichMessage(message: Message, camelContext: CamelContext) { /** * Returns the body of the message converted to the type T. Conversion is done * using Camel's type converter. The type converter is obtained from the CamelContext managed @@ -136,7 +134,7 @@ class RichMessage(message: Message, camelContext: CamelContext) { * @see CamelContextManager. */ - def bodyAs[T](implicit m: Manifest[T]): T = getBodyAs(m.erasure.asInstanceOf[Class[T]]) + def bodyAs[T](implicit m: Manifest[T], camelContext: CamelContext): T = getBodyAs(m.erasure.asInstanceOf[Class[T]], camelContext) /** * Returns the body of the message converted to the type as given by the clazz @@ -148,26 +146,26 @@ class RichMessage(message: Message, camelContext: CamelContext) { * * @see CamelContextManager. */ - def getBodyAs[T](clazz: Class[T]): T = - camelContext.getTypeConverter.mandatoryConvertTo[T](clazz, message.body) + def getBodyAs[T](clazz: Class[T], camelContext: CamelContext): T = + camelContext.getTypeConverter.mandatoryConvertTo[T](clazz, body) /** - * Creates a Message with current body converted to type T. + * Creates a CamelMessage with current body converted to type T. */ - def withBodyAs[T](implicit m: Manifest[T]): Message = withBodyAs(m.erasure.asInstanceOf[Class[T]]) + def withBodyAs[T](implicit m: Manifest[T], camelContext: CamelContext): CamelMessage = withBodyAs(m.erasure.asInstanceOf[Class[T]]) /** - * Creates a Message with current body converted to type clazz. + * Creates a CamelMessage with current body converted to type clazz. *

* Java API */ - def withBodyAs[T](clazz: Class[T]): Message = message.withBody(getBodyAs(clazz)) + def withBodyAs[T](clazz: Class[T])(implicit camelContext: CamelContext): CamelMessage = withBody(getBodyAs(clazz, camelContext)) /** * Returns the header with given name converted to type T. Throws * NoSuchElementException if the header doesn't exist. */ - def headerAs[T](name: String)(implicit m: Manifest[T]): Option[T] = message.header(name).map(camelContext.getTypeConverter.mandatoryConvertTo[T](m.erasure.asInstanceOf[Class[T]], _)) + def headerAs[T](name: String)(implicit m: Manifest[T], camelContext: CamelContext): Option[T] = header(name).map(camelContext.getTypeConverter.mandatoryConvertTo[T](m.erasure.asInstanceOf[Class[T]], _)) /** * Returns the header with given name converted to type as given by the clazz @@ -175,19 +173,19 @@ class RichMessage(message: Message, camelContext: CamelContext) { *

* Java API */ - def getHeaderAs[T](name: String, clazz: Class[T]) = headerAs[T](name)(Manifest.classType(clazz)).get + def getHeaderAs[T](name: String, clazz: Class[T], camelContext: CamelContext) = headerAs[T](name)(Manifest.classType(clazz), camelContext).get } /** - * Companion object of Message class. + * Companion object of CamelMessage class. * * @author Martin Krasser */ -object Message { +object CamelMessage { /** - * Message header to correlate request with response messages. Applications that send + * CamelMessage header to correlate request with response messages. Applications that send * messages to a Producer actor may want to set this header on the request message * so that it can be correlated with an asynchronous response. Messages send to Consumer * actors have this header already set. @@ -196,26 +194,26 @@ object Message { /** * Creates a canonical form of the given message msg. If msg of type - * Message then msg is returned, otherwise msg is set as body of a - * newly created Message object. + * CamelMessage then msg is returned, otherwise msg is set as body of a + * newly created CamelMessage object. */ def canonicalize(msg: Any) = msg match { - case mobj: Message ⇒ mobj - case body ⇒ Message(body, Map.empty) + case mobj: CamelMessage ⇒ mobj + case body ⇒ CamelMessage(body, Map.empty) } /** - * Creates a new Message object from the Camel message. + * Creates a new CamelMessage object from the Camel message. */ - def from(camelMessage: CamelMessage): Message = from(camelMessage, Map.empty) + def from(camelMessage: JCamelMessage): CamelMessage = from(camelMessage, Map.empty) /** - * Creates a new Message object from the Camel message. + * Creates a new CamelMessage object from the Camel message. * - * @param headers additional headers to set on the created Message in addition to those + * @param headers additional headers to set on the created CamelMessage in addition to those * in the Camel message. */ - def from(camelMessage: CamelMessage, headers: Map[String, Any]): Message = Message(camelMessage.getBody, headers ++ camelMessage.getHeaders) + def from(camelMessage: JCamelMessage, headers: Map[String, Any]): CamelMessage = CamelMessage(camelMessage.getBody, headers ++ camelMessage.getHeaders) } diff --git a/akka-camel/src/main/scala/akka/camel/Consumer.scala b/akka-camel/src/main/scala/akka/camel/Consumer.scala index 3b2ebfd8c0..7c0119ef5e 100644 --- a/akka-camel/src/main/scala/akka/camel/Consumer.scala +++ b/akka-camel/src/main/scala/akka/camel/Consumer.scala @@ -19,16 +19,22 @@ import akka.util.duration._ trait Consumer extends Actor with ConsumerConfig { def endpointUri: String - protected[this] implicit lazy val camel = CamelExtension(context.system) + + protected[this] implicit def camel = CamelExtension(context.system) + protected[this] implicit def camelContext = camel.context camel.registerConsumer(endpointUri, this, activationTimeout) } +/** + * For internal use only. + */ +private[camel] object DefaultConsumerConfig extends ConsumerConfig + trait ConsumerConfig { - //TODO: Explain the parameters better with some examples! /** - * How long should the actor wait for activation before it fails. + * How long the actor should wait for activation before it fails. */ def activationTimeout: Duration = 10 seconds @@ -50,18 +56,12 @@ trait ConsumerConfig { /** * The route definition handler for creating a custom route to this consumer instance. */ - //TODO: write a test confirming onRouteDefinition gets called + //FIXME: write a test confirming onRouteDefinition gets called def onRouteDefinition(rd: RouteDefinition): ProcessorDefinition[_] = rd + /** + * For internal use only. Converts this ConsumerConfig to camel URI parameters + * @return + */ private[camel] def toCamelParameters: String = "autoack=%s&replyTimeout=%s" format (autoack, DurationTypeConverter.toString(replyTimeout)) } - -trait ManualAckConsumer extends Consumer { - override def autoack = false -} - -trait ErrorPassing { self: Actor ⇒ - final override def preRestart(reason: Throwable, message: Option[Any]) { - sender ! Failure(reason) - } -} \ No newline at end of file diff --git a/akka-camel/src/main/scala/akka/camel/Producer.scala b/akka-camel/src/main/scala/akka/camel/Producer.scala index 0be4d3bbbb..5a148bb6f9 100644 --- a/akka-camel/src/main/scala/akka/camel/Producer.scala +++ b/akka-camel/src/main/scala/akka/camel/Producer.scala @@ -14,14 +14,14 @@ import org.apache.camel.{ Exchange, ExchangePattern, AsyncCallback } * @author Martin Krasser */ trait ProducerSupport { this: Actor ⇒ - protected[this] implicit lazy val camel = CamelExtension(context.system) + protected[this] implicit def camel = CamelExtension(context.system) protected[this] lazy val (endpoint, processor) = camel.registerProducer(self, endpointUri) /** - * Message headers to copy by default from request message to response-message. + * CamelMessage headers to copy by default from request message to response-message. */ - private val headersToCopyDefault = Set(Message.MessageExchangeId) + private val headersToCopyDefault = Set(CamelMessage.MessageExchangeId) /** * If set to false (default), this producer expects a response message from the Camel endpoint. @@ -37,7 +37,7 @@ trait ProducerSupport { this: Actor ⇒ /** * Returns the names of message headers to copy from a request message to a response message. - * By default only the Message.MessageExchangeId is copied. Applications may override this to + * By default only the CamelMessage.MessageExchangeId is copied. Applications may override this to * define an application-specific set of message headers to copy. */ def headersToCopy: Set[String] = headersToCopyDefault @@ -52,7 +52,7 @@ trait ProducerSupport { this: Actor ⇒ * asynchronously. The original * sender and senderFuture are preserved. * - * @see Message#canonicalize(Any) + * @see CamelMessage#canonicalize(Any) * * @param msg message to produce * @param pattern exchange pattern @@ -60,7 +60,7 @@ trait ProducerSupport { this: Actor ⇒ protected def produce(msg: Any, pattern: ExchangePattern): Unit = { implicit def toExchangeAdapter(exchange: Exchange): CamelExchangeAdapter = new CamelExchangeAdapter(exchange) - val cmsg = Message.canonicalize(msg) + val cmsg = CamelMessage.canonicalize(msg) val exchange = endpoint.createExchange(pattern) exchange.setRequest(cmsg) processor.process(exchange, new AsyncCallback { @@ -68,15 +68,10 @@ trait ProducerSupport { this: Actor ⇒ // Need copies of sender reference here since the callback could be done // later by another thread. val originalSender = sender - - def done(doneSync: Boolean): Unit = { - if (exchange.isFailed) { - dispatch(FailureResult(exchange.toFailureMessage(cmsg.headers(headersToCopy)))) - } else { - dispatch(MessageResult(exchange.toResponseMessage(cmsg.headers(headersToCopy)))) - } - } - private def dispatch(result: Any) { producer.tell(result, originalSender) } + // Ignoring doneSync, sending back async uniformly. + def done(doneSync: Boolean): Unit = producer.tell( + if (exchange.isFailed) FailureResult(exchange.toFailureMessage(cmsg.headers(headersToCopy))) + else MessageResult(exchange.toResponseMessage(cmsg.headers(headersToCopy))), originalSender) }) } @@ -135,12 +130,12 @@ trait Producer extends ProducerSupport { this: Actor ⇒ /** * @author Martin Krasser */ -private[camel] case class MessageResult(message: Message) +private case class MessageResult(message: CamelMessage) /** * @author Martin Krasser */ -private[camel] case class FailureResult(failure: Failure) +private case class FailureResult(failure: Failure) /** * A one-way producer. diff --git a/akka-camel/src/main/scala/akka/camel/internal/ActivationTracker.scala b/akka-camel/src/main/scala/akka/camel/internal/ActivationTracker.scala index aa95189dcd..406cd48cbb 100644 --- a/akka-camel/src/main/scala/akka/camel/internal/ActivationTracker.scala +++ b/akka-camel/src/main/scala/akka/camel/internal/ActivationTracker.scala @@ -7,14 +7,24 @@ package akka.camel.internal import akka.actor._ import collection.mutable.WeakHashMap -class ActivationTracker extends Actor with ActorLogging { +/** + * For internal use only. Tracks activation and de-activation of endpoints. + */ +private[akka] final class ActivationTracker extends Actor with ActorLogging { val activations = new WeakHashMap[ActorRef, ActivationStateMachine] + /** + * A state machine that keeps track of the endpoint activation status of an actor. + */ class ActivationStateMachine { type State = PartialFunction[ActivationMessage, Unit] var receive: State = notActivated() + /** + * Not activated state + * @return a partial function that handles messages in the 'not activated' state + */ def notActivated(): State = { var awaitingActivation = List[ActorRef]() var awaitingDeActivation = List[ActorRef]() @@ -22,46 +32,59 @@ class ActivationTracker extends Actor with ActorLogging { { case AwaitActivation(ref) ⇒ awaitingActivation ::= sender case AwaitDeActivation(ref) ⇒ awaitingDeActivation ::= sender - - case msg @ EndpointActivated(ref) ⇒ { + case msg @ EndpointActivated(ref) ⇒ awaitingActivation.foreach(_ ! msg) receive = activated(awaitingDeActivation) - } - - case EndpointFailedToActivate(ref, cause) ⇒ { + case EndpointFailedToActivate(ref, cause) ⇒ awaitingActivation.foreach(_ ! EndpointFailedToActivate(ref, cause)) receive = failedToActivate(cause) - } } } + /** + * Activated state. + * @param currentAwaitingDeActivation the current ActorRefs awaiting de-activation + * @return a partial function that handles messages in the 'activated' state + */ def activated(currentAwaitingDeActivation: List[ActorRef]): State = { var awaitingDeActivation = currentAwaitingDeActivation { case AwaitActivation(ref) ⇒ sender ! EndpointActivated(ref) case AwaitDeActivation(ref) ⇒ awaitingDeActivation ::= sender - case msg @ EndpointDeActivated(ref) ⇒ { + case msg @ EndpointDeActivated(ref) ⇒ awaitingDeActivation foreach (_ ! msg) receive = deactivated - } - case msg @ EndpointFailedToDeActivate(ref, cause) ⇒ { + case msg @ EndpointFailedToDeActivate(ref, cause) ⇒ awaitingDeActivation foreach (_ ! msg) receive = failedToDeActivate(cause) - } } } + /** + * De-activated state + * @return a partial function that handles messages in the 'de-activated' state + */ def deactivated: State = { case AwaitActivation(ref) ⇒ sender ! EndpointActivated(ref) case AwaitDeActivation(ref) ⇒ sender ! EndpointDeActivated(ref) } + /** + * Failed to activate state + * @param cause the cause for the failure + * @return a partial function that handles messages in 'failed to activate' state + */ def failedToActivate(cause: Throwable): State = { case AwaitActivation(ref) ⇒ sender ! EndpointFailedToActivate(ref, cause) case AwaitDeActivation(ref) ⇒ sender ! EndpointFailedToActivate(ref, cause) } + /** + * Failed to de-activate state + * @param cause the cause for the failure + * @return a partial function that handles messages in 'failed to de-activate' state + */ def failedToDeActivate(cause: Throwable): State = { case AwaitActivation(ref) ⇒ sender ! EndpointActivated(ref) case AwaitDeActivation(ref) ⇒ sender ! EndpointFailedToDeActivate(ref, cause) @@ -69,15 +92,21 @@ class ActivationTracker extends Actor with ActorLogging { } + /** + * Subscribes self to messages of type ActivationMessage + */ override def preStart() { context.system.eventStream.subscribe(self, classOf[ActivationMessage]) } + /** + * + * @return + */ override def receive = { - case msg @ ActivationMessage(ref) ⇒ { + case msg @ ActivationMessage(ref) ⇒ val state = activations.getOrElseUpdate(ref, new ActivationStateMachine) (state.receive orElse logStateWarning(ref))(msg) - } } private[this] def logStateWarning(actorRef: ActorRef): Receive = { case msg ⇒ log.warning("Message [{}] not expected in current state of actor [{}]", msg, actorRef) } diff --git a/akka-camel/src/main/scala/akka/camel/internal/CamelExchangeAdapter.scala b/akka-camel/src/main/scala/akka/camel/internal/CamelExchangeAdapter.scala index cf137093aa..de54693950 100644 --- a/akka-camel/src/main/scala/akka/camel/internal/CamelExchangeAdapter.scala +++ b/akka-camel/src/main/scala/akka/camel/internal/CamelExchangeAdapter.scala @@ -7,31 +7,31 @@ import scala.collection.JavaConversions._ import org.apache.camel.util.ExchangeHelper import akka.japi.{ Function ⇒ JFunction } -import org.apache.camel.{ Exchange, Message ⇒ CamelMessage } -import akka.camel.{ Failure, Message } +import org.apache.camel.{ Exchange, Message ⇒ JCamelMessage } +import akka.camel.{ Failure, CamelMessage } /** - * Adapter for converting an org.apache.camel.Exchange to and from Message and Failure objects. + * For internal use only. + * Adapter for converting an org.apache.camel.Exchange to and from CamelMessage and Failure objects. * * @author Martin Krasser */ -//TODO: rething/rewrite this private[camel] class CamelExchangeAdapter(exchange: Exchange) { def getExchangeId = exchange.getExchangeId def isOutCapable = exchange.getPattern.isOutCapable /** - * Sets Exchange.getIn from the given Message object. + * Sets Exchange.getIn from the given CamelMessage object. */ - def setRequest(msg: Message) { msg.copyContentTo(request) } + def setRequest(msg: CamelMessage) { msg.copyContentTo(request) } /** * Depending on the exchange pattern, sets Exchange.getIn or Exchange.getOut from the given - * Message object. If the exchange is out-capable then the Exchange.getOut is set, otherwise + * CamelMessage object. If the exchange is out-capable then the Exchange.getOut is set, otherwise * Exchange.getIn. */ - def setResponse(msg: Message) { msg.copyContentTo(response) } + def setResponse(msg: CamelMessage) { msg.copyContentTo(response) } /** * Sets Exchange.getException from the given Failure message. Headers of the Failure message @@ -40,15 +40,15 @@ private[camel] class CamelExchangeAdapter(exchange: Exchange) { def setFailure(msg: Failure) { exchange.setException(msg.cause) } /** - * Creates a Message object from Exchange.getIn. + * Creates a CamelMessage object from Exchange.getIn. */ - def toRequestMessage: Message = toRequestMessage(Map.empty) + def toRequestMessage: CamelMessage = toRequestMessage(Map.empty) /** - * Depending on the exchange pattern, creates a Message object from Exchange.getIn or Exchange.getOut. + * Depending on the exchange pattern, creates a CamelMessage object from Exchange.getIn or Exchange.getOut. * If the exchange is out-capable then the Exchange.getOut is set, otherwise Exchange.getIn. */ - def toResponseMessage: Message = toResponseMessage(Map.empty) + def toResponseMessage: CamelMessage = toResponseMessage(Map.empty) /** * Creates a Failure object from the adapted Exchange. @@ -58,26 +58,26 @@ private[camel] class CamelExchangeAdapter(exchange: Exchange) { def toFailureMessage: Failure = toFailureMessage(Map.empty) /** - * Creates a Message object from Exchange.getIn. + * Creates a CamelMessage object from Exchange.getIn. * - * @param headers additional headers to set on the created Message in addition to those + * @param headers additional headers to set on the created CamelMessage in addition to those * in the Camel message. */ - def toRequestMessage(headers: Map[String, Any]): Message = Message.from(request, headers) + def toRequestMessage(headers: Map[String, Any]): CamelMessage = CamelMessage.from(request, headers) /** - * Depending on the exchange pattern, creates a Message object from Exchange.getIn or Exchange.getOut. + * Depending on the exchange pattern, creates a CamelMessage object from Exchange.getIn or Exchange.getOut. * If the exchange is out-capable then the Exchange.getOut is set, otherwise Exchange.getIn. * - * @param headers additional headers to set on the created Message in addition to those + * @param headers additional headers to set on the created CamelMessage in addition to those * in the Camel message. */ - def toResponseMessage(headers: Map[String, Any]): Message = Message.from(response, headers) + def toResponseMessage(headers: Map[String, Any]): CamelMessage = CamelMessage.from(response, headers) /** * Creates a Failure object from the adapted Exchange. * - * @param headers additional headers to set on the created Message in addition to those + * @param headers additional headers to set on the created CamelMessage in addition to those * in the Camel message. * * @see Failure @@ -87,6 +87,6 @@ private[camel] class CamelExchangeAdapter(exchange: Exchange) { private def request = exchange.getIn - private def response: CamelMessage = ExchangeHelper.getResultMessage(exchange) + private def response: JCamelMessage = ExchangeHelper.getResultMessage(exchange) } \ No newline at end of file diff --git a/akka-camel/src/main/scala/akka/camel/internal/ConsumerRegistry.scala b/akka-camel/src/main/scala/akka/camel/internal/ConsumerRegistry.scala index 74e5c16460..bb72e978ae 100644 --- a/akka-camel/src/main/scala/akka/camel/internal/ConsumerRegistry.scala +++ b/akka-camel/src/main/scala/akka/camel/internal/ConsumerRegistry.scala @@ -17,6 +17,7 @@ import org.apache.camel.CamelContext import akka.util.Duration /** + * For internal use only. * Manages consumer registration. Consumers call registerConsumer method to register themselves when they get created. * ActorEndpoint uses it to lookup an actor by its path. */ @@ -24,8 +25,17 @@ private[camel] trait ConsumerRegistry { this: Activation ⇒ def system: ActorSystem def context: CamelContext + /** + * For internal use only. + */ private[this] lazy val idempotentRegistry = system.actorOf(Props(new IdempotentCamelConsumerRegistry(context))) - + /** + * For internal use only. + * @param endpointUri the URI to register the consumer on + * @param consumer the consumer + * @param activationTimeout the timeout for activation + * @return the actorRef to the consumer + */ private[camel] def registerConsumer(endpointUri: String, consumer: Consumer, activationTimeout: Duration) = { idempotentRegistry ! RegisterConsumer(endpointUri, consumer.self, consumer) awaitActivation(consumer.self, activationTimeout) @@ -33,6 +43,7 @@ private[camel] trait ConsumerRegistry { this: Activation ⇒ } /** + * For internal use only. * Guarantees idempotent registration of camel consumer endpoints. * * Once registered the consumer is watched and unregistered upon termination. @@ -48,46 +59,42 @@ private[camel] class IdempotentCamelConsumerRegistry(camelContext: CamelContext) val registrator = context.actorOf(Props(new CamelConsumerRegistrator)) def receive = { - case msg @ RegisterConsumer(_, consumer, _) ⇒ unless(isAlreadyActivated(consumer)) { - activated.add(consumer) - registrator ! msg - } - case msg @ EndpointActivated(consumer) ⇒ { + case msg @ RegisterConsumer(_, consumer, _) ⇒ + if (!isAlreadyActivated(consumer)) { + activated.add(consumer) + registrator ! msg + } + case msg @ EndpointActivated(consumer) ⇒ context.watch(consumer) context.system.eventStream.publish(msg) - } - case msg @ EndpointFailedToActivate(consumer, _) ⇒ { + case msg @ EndpointFailedToActivate(consumer, _) ⇒ activated.remove(consumer) context.system.eventStream.publish(msg) - } - case Terminated(ref) ⇒ { + case Terminated(ref) ⇒ activated.remove(ref) registrator ! UnregisterConsumer(ref) - } - case msg @ EndpointDeActivated(ref) ⇒ { context.system.eventStream.publish(msg) } - case msg @ EndpointFailedToDeActivate(ref, cause) ⇒ { context.system.eventStream.publish(msg) } + case msg @ EndpointFailedToDeActivate(ref, cause) ⇒ context.system.eventStream.publish(msg) + case msg: EndpointDeActivated ⇒ context.system.eventStream.publish(msg) } - def unless[A](condition: Boolean)(block: ⇒ A) = if (!condition) block def isAlreadyActivated(ref: ActorRef): Boolean = activated.contains(ref) class CamelConsumerRegistrator extends Actor with ActorLogging { def receive = { - case RegisterConsumer(endpointUri, consumer, consumerConfig) ⇒ { + case RegisterConsumer(endpointUri, consumer, consumerConfig) ⇒ camelContext.addRoutes(new ConsumerActorRouteBuilder(endpointUri, consumer, consumerConfig)) context.sender ! EndpointActivated(consumer) log.debug("Published actor [{}] at endpoint [{}]", consumerConfig, endpointUri) - } - - case UnregisterConsumer(consumer) ⇒ { + case UnregisterConsumer(consumer) ⇒ camelContext.stopRoute(consumer.path.toString) context.sender ! EndpointDeActivated(consumer) log.debug("Unpublished actor [{}] from endpoint [{}]", consumer, consumer.path) - } } override def preRestart(reason: Throwable, message: Option[Any]) { + //FIXME check logic + super.preStart() message match { case Some(RegisterConsumer(_, consumer, _)) ⇒ sender ! EndpointFailedToActivate(consumer, reason) case Some(UnregisterConsumer(consumer)) ⇒ sender ! EndpointFailedToDeActivate(consumer, reason) @@ -97,9 +104,16 @@ private[camel] class IdempotentCamelConsumerRegistry(camelContext: CamelContext) } } +/** + * For internal use only. A message to register a consumer. + * @param endpointUri the endpointUri to register to + * @param actorRef the actorRef to register as a consumer + * @param config the configuration for the consumer + */ private[camel] case class RegisterConsumer(endpointUri: String, actorRef: ActorRef, config: ConsumerConfig) /** + * For internal use only. * Abstract builder of a route to a target which can be either an actor or an typed actor method. * * @param endpointUri endpoint URI of the consumer actor or typed actor method. @@ -115,7 +129,7 @@ private[camel] class ConsumerActorRouteBuilder(endpointUri: String, consumer: Ac val scheme = endpointUri take endpointUri.indexOf(":") // e.g. "http" from "http://whatever/..." val route = from(endpointUri).routeId(consumer.path.toString) - val converted = Conversions.apply(scheme, route) + val converted = Conversions(scheme, route) val userCustomized = applyUserRouteCustomization(converted) userCustomized.to(targetActorUri) } @@ -138,18 +152,39 @@ private[camel] class ConsumerActorRouteBuilder(endpointUri: String, consumer: Ac /** * Super class of all activation messages. */ -private[camel] abstract class ActivationMessage(val actor: ActorRef) +abstract class ActivationMessage(val actor: ActorRef) + +/** + * For internal use only. companion object of ActivationMessage + * + */ private[camel] object ActivationMessage { def unapply(msg: ActivationMessage): Option[ActorRef] = Some(msg.actor) } /** + * For internal use only. * Event message indicating that a single endpoint has been activated. */ -private[camel] case class EndpointActivated(actorRef: ActorRef) extends ActivationMessage(actorRef) +sealed case class EndpointActivated(actorRef: ActorRef) extends ActivationMessage(actorRef) -private[camel] case class EndpointFailedToActivate(actorRef: ActorRef, cause: Throwable) extends ActivationMessage(actorRef) +/** + * For internal use only. + * Event message indicating that a single endpoint failed tp activate + * @param actorRef the endpoint that failed to activate + * @param cause the cause for failure + */ +sealed case class EndpointFailedToActivate(actorRef: ActorRef, cause: Throwable) extends ActivationMessage(actorRef) -private[camel] case class EndpointDeActivated(actorRef: ActorRef) extends ActivationMessage(actorRef) +/** + * For internal use only. + * @param actorRef the endpoint that was de-activated + */ +sealed case class EndpointDeActivated(actorRef: ActorRef) extends ActivationMessage(actorRef) -private[camel] case class EndpointFailedToDeActivate(actorRef: ActorRef, cause: Throwable) extends ActivationMessage(actorRef) +/** + * For internal use only. + * @param actorRef the endpoint that failed to de-activate + * @param cause the cause for failure + */ +sealed case class EndpointFailedToDeActivate(actorRef: ActorRef, cause: Throwable) extends ActivationMessage(actorRef) diff --git a/akka-camel/src/main/scala/akka/camel/internal/DefaultCamel.scala b/akka-camel/src/main/scala/akka/camel/internal/DefaultCamel.scala index 04046a4bf0..1754bb0073 100644 --- a/akka-camel/src/main/scala/akka/camel/internal/DefaultCamel.scala +++ b/akka-camel/src/main/scala/akka/camel/internal/DefaultCamel.scala @@ -4,12 +4,13 @@ import akka.actor.ActorSystem import component.{ DurationTypeConverter, ActorComponent } import org.apache.camel.CamelContext import org.apache.camel.impl.DefaultCamelContext -import akka.util.Duration import scala.Predef._ import akka.event.Logging import akka.camel.Camel +import akka.util.{ NonFatal, Duration } /** + * For internal use only. * Creates an instance of the Camel subsystem. * * @param system is used to create internal actors needed by camel instance. @@ -18,6 +19,9 @@ import akka.camel.Camel * Also by not creating extra internal actor system we are conserving resources. */ private[camel] class DefaultCamel(val system: ActorSystem) extends Camel { + /** + * For internal use only. + */ private[camel] implicit val log = Logging(system, "Camel") lazy val context: CamelContext = { @@ -38,7 +42,7 @@ private[camel] class DefaultCamel(val system: ActorSystem) extends Camel { */ def start = { context.start() - Try(template.start()) otherwise context.stop() + try template.start() catch { case NonFatal(e) ⇒ context.stop(); throw e } log.debug("Started CamelContext[{}] for ActorSystem[{}]", context.getName, system.name) this } @@ -51,7 +55,9 @@ private[camel] class DefaultCamel(val system: ActorSystem) extends Camel { * @see akka.camel.DefaultCamel#start() */ def shutdown() { - try context.stop() finally Try.safe(template.stop()) + try context.stop() finally { + try { template.stop() } catch { case NonFatal(e) ⇒ log.debug("Swallowing non-fatal exception [{}] on stopping Camel producer template", e) } + } log.debug("Stopped CamelContext[{}] for ActorSystem[{}]", context.getName, system.name) } } diff --git a/akka-camel/src/main/scala/akka/camel/internal/ProducerRegistry.scala b/akka-camel/src/main/scala/akka/camel/internal/ProducerRegistry.scala index 9f7f268159..ad0650c980 100644 --- a/akka-camel/src/main/scala/akka/camel/internal/ProducerRegistry.scala +++ b/akka-camel/src/main/scala/akka/camel/internal/ProducerRegistry.scala @@ -5,26 +5,24 @@ import org.apache.camel.processor.SendProcessor import akka.actor.{ Props, ActorRef, Terminated, Actor } import org.apache.camel.Endpoint import akka.camel.Camel +import akka.util.NonFatal /** * Watches the end of life of Producers. * Removes a Producer from the ProducerRegistry when it is Terminated, * which in turn stops the SendProcessor. */ -private[camel] class ProducerWatcher(registry: ProducerRegistry) extends Actor { +private class ProducerWatcher(registry: ProducerRegistry) extends Actor { override def receive = { - case RegisterProducer(actorRef) ⇒ { - context.watch(actorRef) - } - case Terminated(actorRef) ⇒ { - registry.unregisterProducer(actorRef) - } + case RegisterProducer(actorRef) ⇒ context.watch(actorRef) + case Terminated(actorRef) ⇒ registry.unregisterProducer(actorRef) } } -private[camel] case class RegisterProducer(actorRef: ActorRef) +private case class RegisterProducer(actorRef: ActorRef) /** + * For internal use only. * Manages the Camel objects for Producers. * Every Producer needs an Endpoint and a SendProcessor * to produce messages over an Exchange. @@ -39,6 +37,7 @@ private[camel] trait ProducerRegistry { } /** + * For internal use only. * Unregisters Endpoint and SendProcessor and stops the SendProcessor */ private[camel] def unregisterProducer(actorRef: ActorRef): Unit = { @@ -49,12 +48,13 @@ private[camel] trait ProducerRegistry { processor.stop() system.eventStream.publish(EndpointDeActivated(actorRef)) } catch { - case e ⇒ system.eventStream.publish(EndpointFailedToDeActivate(actorRef, e)) + case NonFatal(e) ⇒ system.eventStream.publish(EndpointFailedToDeActivate(actorRef, e)) } } } /** + * For internal use only. * Creates Endpoint and SendProcessor and associates the actorRef to these. * @param actorRef the actorRef of the Producer actor. * @param endpointUri the endpoint Uri of the producer @@ -65,17 +65,16 @@ private[camel] trait ProducerRegistry { val endpoint = context.getEndpoint(endpointUri) val processor = new SendProcessor(endpoint) - val prev = camelObjects.putIfAbsent(actorRef, (endpoint, processor)) - if (prev != null) { - prev - } else { - processor.start() - system.eventStream.publish(EndpointActivated(actorRef)) - registerWatch(actorRef) - (endpoint, processor) + camelObjects.putIfAbsent(actorRef, (endpoint, processor)) match { + case null ⇒ + processor.start() + registerWatch(actorRef) + system.eventStream.publish(EndpointActivated(actorRef)) + (endpoint, processor) + case prev ⇒ prev } } catch { - case e ⇒ { + case NonFatal(e) ⇒ { system.eventStream.publish(EndpointFailedToActivate(actorRef, e)) // can't return null to the producer actor, so blow up actor in initialization. throw e diff --git a/akka-camel/src/main/scala/akka/camel/internal/Try.scala b/akka-camel/src/main/scala/akka/camel/internal/Try.scala deleted file mode 100644 index d7d47fe5cc..0000000000 --- a/akka-camel/src/main/scala/akka/camel/internal/Try.scala +++ /dev/null @@ -1,53 +0,0 @@ -package akka.camel.internal - -/** - * Copyright (C) 2009-2012 Typesafe Inc. - */ - -import akka.event.LoggingAdapter - -private[camel] object Try { - - /** - * Tries to execute body. - * - * Example below tries to start template and if it's unsuccessful it stops context in a safe way, by logging exceptions and then it rethrows exception thrown by template.start() - *

 Try(template.start()) otherwise context.stop() 
- * - * @param body block of code to execute. - * @return Ok, if no exception is thrown by body. - * @return Failed, if exception was thrown by body. - * - */ - def apply(body: ⇒ Unit): Result = - try { - body; Ok - } catch { - case e ⇒ Failed(e) - } - - sealed trait Result { - def otherwise(onError: ⇒ Unit)(implicit log: LoggingAdapter): Unit = () - } - - private[this] case object Ok extends Result - - private[this] case class Failed(e: Throwable) extends Result { - override def otherwise(onError: ⇒ Unit)(implicit log: LoggingAdapter) = { - safe(onError) - throw e - } - } - - /** - * Executes the block and logs the exception, if it's thrown by the block, and swallows the exception. - */ - @inline def safe(block: ⇒ Unit)(implicit log: LoggingAdapter) { - try { - block - } catch { - case e ⇒ log.warning("Safe operation failed. Swallowing exception [{}]", e) - } - } - -} diff --git a/akka-camel/src/main/scala/akka/camel/internal/component/ActorComponent.scala b/akka-camel/src/main/scala/akka/camel/internal/component/ActorComponent.scala index 440a6fe1c6..6374dddcac 100644 --- a/akka-camel/src/main/scala/akka/camel/internal/component/ActorComponent.scala +++ b/akka-camel/src/main/scala/akka/camel/internal/component/ActorComponent.scala @@ -13,13 +13,14 @@ import akka.actor._ import akka.pattern._ import scala.reflect.BeanProperty -import akka.util.{ Duration, Timeout } import akka.util.duration._ import java.util.concurrent.{ TimeoutException, CountDownLatch } -import akka.camel.{ ConsumerConfig, Camel, Ack, Failure ⇒ CamelFailure, Message } import akka.camel.internal.CamelExchangeAdapter +import akka.util.{ NonFatal, Duration, Timeout } +import akka.camel.{ DefaultConsumerConfig, ConsumerConfig, Camel, Ack, Failure ⇒ CamelFailure, CamelMessage } /** + * For internal use only. * Camel component for sending messages to and receiving replies from (untyped) actors. * * @see akka.camel.component.ActorEndpoint @@ -27,7 +28,7 @@ import akka.camel.internal.CamelExchangeAdapter * * @author Martin Krasser */ -class ActorComponent(camel: Camel) extends DefaultComponent { +private[camel] class ActorComponent(camel: Camel) extends DefaultComponent { def createEndpoint(uri: String, remaining: String, parameters: JMap[String, Object]): ActorEndpoint = { val path = ActorEndpointPath.fromCamelPath(remaining) new ActorEndpoint(uri, this, path, camel) @@ -35,32 +36,31 @@ class ActorComponent(camel: Camel) extends DefaultComponent { } /** - * TODO fix the doc to be consistent with implementation - * Camel endpoint for sending messages to and receiving replies from (untyped) actors. Actors - * are referenced using actor endpoint URIs of the following format: - * actor:, - * actor:id:[] and - * actor:uuid:[], - * where refers to ActorRef.id and - * refers to the String-representation od ActorRef.uuid. In URIs that contain - * id: or uuid:, an actor identifier (id or uuid) is optional. In this - * case, the in-message of an exchange produced to this endpoint must contain a message header - * with name CamelActorIdentifier and a value that is the target actor's identifier. - * If the URI contains an actor identifier, a message with a CamelActorIdentifier - * header overrides the identifier in the endpoint URI. + * For internal use only. + * The ActorEndpoint is a Camel Endpoint that is used to receive messages from Camel through the ActorComponent + * Actors are referenced using actor endpoint URIs of the following format: + * actor://path:[actorPath]?[options]%s, + * where [actorPath] refers to the Actor Path to the Actor. * * @see akka.camel.component.ActorComponent * @see akka.camel.component.ActorProducer * * @author Martin Krasser */ -class ActorEndpoint(uri: String, - comp: ActorComponent, - val path: ActorEndpointPath, - camel: Camel) extends DefaultEndpoint(uri, comp) with ActorEndpointConfig { +private[camel] class ActorEndpoint(uri: String, + comp: ActorComponent, + val path: ActorEndpointPath, + camel: Camel) extends DefaultEndpoint(uri, comp) with ActorEndpointConfig { /** - * @throws UnsupportedOperationException + * + * The ActorEndpoint right now only supports receiving messages from Camel. + * The createProducer method (not to be confused with a producer actor) is used to send messages into the endpoint. + * The ActorComponent is only there to send to actors registered through an actor endpoint URI. + * You can use an actor as an endpoint to send to in a camel route (as in, a Camel Consumer Actor). so from(someuri) to (actoruri), but not 'the other way around'. + * Supporting createConsumer would mean that messages are consumed from an Actor endpoint in a route, and an Actor is not necessarily a producer of messages + * [[akka.camel.Producer]] Actors can be used for sending messages to some other uri/ component type registered in Camel. + * @throws UnsupportedOperationException this method is not supported */ def createConsumer(processor: Processor): org.apache.camel.Consumer = throw new UnsupportedOperationException("actor consumer not supported yet") @@ -76,7 +76,7 @@ class ActorEndpoint(uri: String, def isSingleton: Boolean = true } -trait ActorEndpointConfig { +private[camel] trait ActorEndpointConfig { def path: ActorEndpointPath @BeanProperty var replyTimeout: Duration = 1 minute @@ -91,43 +91,54 @@ trait ActorEndpointConfig { @BeanProperty var autoack: Boolean = true } -//FIXME: rewrite this doc /** - * Sends the in-message of an exchange to an (untyped) actor, identified by an - * actor endpoint URI or by a CamelActorIdentifier message header. - *
    - *
  • If the exchange pattern is out-capable and blocking is set to - * true then the producer waits for a reply, using the !! operator.
  • - *
  • If the exchange pattern is out-capable and blocking is set to - * false then the producer sends the message using the ! operator, together - * with a callback handler. The callback handler is an ActorRef that can be - * used by the receiving actor to asynchronously reply to the route that is sending the - * message.
  • - *
  • If the exchange pattern is in-only then the producer sends the message using the - * ! operator.
  • - *
+ * Sends the in-message of an exchange to an untyped actor, identified by an [[akka.camel.internal.component.ActorEndPoint]] * * @see akka.camel.component.ActorComponent * @see akka.camel.component.ActorEndpoint * * @author Martin Krasser */ -class ActorProducer(val ep: ActorEndpoint, camel: Camel) extends DefaultProducer(ep) with AsyncProcessor { - def process(exchange: Exchange) { new ConsumerAsyncProcessor(ep, camel).process(new CamelExchangeAdapter(exchange)) } - def process(exchange: Exchange, callback: AsyncCallback) = new ConsumerAsyncProcessor(ep, camel).process(new CamelExchangeAdapter(exchange), callback) -} +private[camel] class ActorProducer(val endpoint: ActorEndpoint, camel: Camel) extends DefaultProducer(endpoint) with AsyncProcessor { + /** + * Processes the exchange. + * Calls the asynchronous version of the method and waits for the result (blocking) + * @param exchange the exchange to process + */ + def process(exchange: Exchange) { processExchangeAdapter(new CamelExchangeAdapter(exchange)) } -class ConsumerAsyncProcessor(config: ActorEndpointConfig, camel: Camel) { + /** + * Processes the message exchange. the caller supports having the exchange asynchronously processed. + * If there was a failure processing then the caused Exception would be set on the Exchange. + * + * @param exchange the message exchange + * @param callback the AsyncCallback will be invoked when the processing of the exchange is completed. + * If the exchange is completed synchronously, then the callback is also invoked synchronously. + * The callback should therefore be careful of starting recursive loop. + * @return (doneSync) true to continue execute synchronously, false to continue being executed asynchronously + */ + def process(exchange: Exchange, callback: AsyncCallback): Boolean = { processExchangeAdapter(new CamelExchangeAdapter(exchange), callback) } - def process(exchange: CamelExchangeAdapter) { + /** + * For internal use only. Processes the [[akka.camel.internal.CamelExchangeAdapter]] + * @param exchange the [[akka.camel.internal.CamelExchangeAdapter]] + */ + private[camel] def processExchangeAdapter(exchange: CamelExchangeAdapter) { val isDone = new CountDownLatch(1) - process(exchange, new AsyncCallback { def done(doneSync: Boolean) { isDone.countDown() } }) + processExchangeAdapter(exchange, new AsyncCallback { def done(doneSync: Boolean) { isDone.countDown() } }) isDone.await() // this should never wait forever as the process(exchange, callback) method guarantees that. } - def process(exchange: CamelExchangeAdapter, callback: AsyncCallback): Boolean = { + /** + * For internal use only. Processes the [[akka.camel.internal.CamelExchangeAdapter]]. + * This method is blocking when the exchange is inOnly. The method returns true if it executed synchronously/blocking. + * @param exchange the [[akka.camel.internal.CamelExchangeAdapter]] + * @param callback the callback + * @return (doneSync) true to continue execute synchronously, false to continue being executed asynchronously + */ + private[camel] def processExchangeAdapter(exchange: CamelExchangeAdapter, callback: AsyncCallback): Boolean = { - // this notify methods are just a syntax sugar + // these notify methods are just a syntax sugar def notifyDoneSynchronously[A](a: A = null) = callback.done(true) def notifyDoneAsynchronously[A](a: A = null) = callback.done(false) @@ -136,7 +147,7 @@ class ConsumerAsyncProcessor(config: ActorEndpointConfig, camel: Camel) { if (exchange.isOutCapable) { //InOut sendAsync(message, onComplete = forwardResponseTo(exchange) andThen notifyDoneAsynchronously) } else { // inOnly - if (config.autoack) { //autoAck + if (endpoint.autoack) { //autoAck fireAndForget(message, exchange) notifyDoneSynchronously() true // done sync @@ -146,46 +157,45 @@ class ConsumerAsyncProcessor(config: ActorEndpointConfig, camel: Camel) { } } + private def forwardResponseTo(exchange: CamelExchangeAdapter): PartialFunction[Either[Throwable, Any], Unit] = { + case Right(failure: CamelFailure) ⇒ exchange.setFailure(failure); + case Right(msg) ⇒ exchange.setResponse(CamelMessage.canonicalize(msg)) + case Left(e: TimeoutException) ⇒ exchange.setFailure(CamelFailure(new TimeoutException("Failed to get response from the actor [%s] within timeout [%s]. Check replyTimeout and blocking settings [%s]" format (endpoint.path, endpoint.replyTimeout, endpoint)))) + case Left(throwable) ⇒ exchange.setFailure(CamelFailure(throwable)) + } - private def sendAsync(message: Message, onComplete: PartialFunction[Either[Throwable, Any], Unit]): Boolean = { + private def forwardAckTo(exchange: CamelExchangeAdapter): PartialFunction[Either[Throwable, Any], Unit] = { + case Right(Ack) ⇒ { /* no response message to set */ } + case Right(failure: CamelFailure) ⇒ exchange.setFailure(failure) + case Right(msg) ⇒ exchange.setFailure(CamelFailure(new IllegalArgumentException("Expected Ack or Failure message, but got: [%s] from actor [%s]" format (msg, endpoint.path)))) + case Left(e: TimeoutException) ⇒ exchange.setFailure(CamelFailure(new TimeoutException("Failed to get Ack or Failure response from the actor [%s] within timeout [%s]. Check replyTimeout and blocking settings [%s]" format (endpoint.path, endpoint.replyTimeout, endpoint)))) + case Left(throwable) ⇒ exchange.setFailure(CamelFailure(throwable)) + } + + private def sendAsync(message: CamelMessage, onComplete: PartialFunction[Either[Throwable, Any], Unit]): Boolean = { try { - val actor = actorFor(config.path) - val future = actor.ask(message)(new Timeout(config.replyTimeout)) + val actor = actorFor(endpoint.path) + val future = actor.ask(message)(new Timeout(endpoint.replyTimeout)) future.onComplete(onComplete) } catch { - case e ⇒ onComplete(Left(e)) + case NonFatal(e) ⇒ onComplete(Left(e)) } false // Done async } - private def fireAndForget(message: Message, exchange: CamelExchangeAdapter) { + private def fireAndForget(message: CamelMessage, exchange: CamelExchangeAdapter) { try { - actorFor(config.path) ! message + actorFor(endpoint.path) ! message } catch { case e ⇒ exchange.setFailure(new CamelFailure(e)) } } - private[this] def forwardResponseTo(exchange: CamelExchangeAdapter): PartialFunction[Either[Throwable, Any], Unit] = { - case Right(failure: CamelFailure) ⇒ exchange.setFailure(failure); - case Right(msg) ⇒ exchange.setResponse(Message.canonicalize(msg)) - case Left(e: TimeoutException) ⇒ exchange.setFailure(CamelFailure(new TimeoutException("Failed to get response from the actor [%s] within timeout [%s]. Check replyTimeout and blocking settings [%s]" format (config.path, config.replyTimeout, config)))) - case Left(throwable) ⇒ exchange.setFailure(CamelFailure(throwable)) - } - - def forwardAckTo(exchange: CamelExchangeAdapter): PartialFunction[Either[Throwable, Any], Unit] = { - case Right(Ack) ⇒ { /* no response message to set */ } - case Right(failure: CamelFailure) ⇒ exchange.setFailure(failure) - case Right(msg) ⇒ exchange.setFailure(CamelFailure(new IllegalArgumentException("Expected Ack or Failure message, but got: [%s] from actor [%s]" format (msg, config.path)))) - case Left(e: TimeoutException) ⇒ exchange.setFailure(CamelFailure(new TimeoutException("Failed to get Ack or Failure response from the actor [%s] within timeout [%s]. Check replyTimeout and blocking settings [%s]" format (config.path, config.replyTimeout, config)))) - case Left(throwable) ⇒ exchange.setFailure(CamelFailure(throwable)) - } - private[this] def actorFor(path: ActorEndpointPath): ActorRef = path.findActorIn(camel.system) getOrElse (throw new ActorNotRegisteredException(path.actorPath)) private[this] def messageFor(exchange: CamelExchangeAdapter) = - exchange.toRequestMessage(Map(Message.MessageExchangeId -> exchange.getExchangeId)) + exchange.toRequestMessage(Map(CamelMessage.MessageExchangeId -> exchange.getExchangeId)) } @@ -199,25 +209,34 @@ class ActorNotRegisteredException(uri: String) extends RuntimeException { override def getMessage = "Actor [%s] doesn't exist" format uri } +/** + * For internal use only. + */ private[camel] object DurationTypeConverter extends CamelTypeConverter { def convertTo[T](`type`: Class[T], value: AnyRef) = { - require(value.toString.endsWith(" nanos")) - Duration.fromNanos(value.toString.dropRight(6).toLong).asInstanceOf[T] + Duration(value.toString).asInstanceOf[T] } def toString(duration: Duration) = duration.toNanos + " nanos" } +/** + * For internal use only. + */ private[camel] abstract class CamelTypeConverter extends TypeConverter { def convertTo[T](`type`: Class[T], exchange: Exchange, value: AnyRef) = convertTo(`type`, value) def mandatoryConvertTo[T](`type`: Class[T], value: AnyRef) = convertTo(`type`, value) def mandatoryConvertTo[T](`type`: Class[T], exchange: Exchange, value: AnyRef) = convertTo(`type`, value) } +/** + * For internal use only. An endpoint to an ActorRef + * @param actorPath the path to the actor + */ private[camel] case class ActorEndpointPath private (actorPath: String) { require(actorPath != null) require(actorPath.length() > 0) - def toCamelPath(config: ConsumerConfig = new ConsumerConfig {}): String = "actor://path:%s?%s" format (actorPath, config.toCamelParameters) + def toCamelPath(config: ConsumerConfig = DefaultConsumerConfig): String = "actor://path:%s?%s" format (actorPath, config.toCamelParameters) def findActorIn(system: ActorSystem): Option[ActorRef] = { val ref = system.actorFor(actorPath) @@ -226,6 +245,9 @@ private[camel] case class ActorEndpointPath private (actorPath: String) { } +/** + * For internal use only. Companion of ActorEndpointPath + */ private[camel] object ActorEndpointPath { def apply(actorRef: ActorRef) = new ActorEndpointPath(actorRef.path.toString) diff --git a/akka-camel/src/main/scala/akka/camel/javaapi/UntypedConsumer.scala b/akka-camel/src/main/scala/akka/camel/javaapi/UntypedConsumer.scala index eebb4ec7a1..9c21333348 100644 --- a/akka-camel/src/main/scala/akka/camel/javaapi/UntypedConsumer.scala +++ b/akka-camel/src/main/scala/akka/camel/javaapi/UntypedConsumer.scala @@ -6,6 +6,7 @@ package akka.camel.javaapi import akka.actor.UntypedActor import akka.camel._ +import org.apache.camel.{ ProducerTemplate, CamelContext } /** * Java-friendly Consumer. @@ -23,11 +24,22 @@ trait UntypedConsumer extends Consumer { self: UntypedActor ⇒ */ def getEndpointUri(): String - def rich(message: Message): RichMessage = message } /** * Subclass this abstract class to create an MDB-style untyped consumer actor. This * class is meant to be used from Java. */ -abstract class UntypedConsumerActor extends UntypedActor with UntypedConsumer +abstract class UntypedConsumerActor extends UntypedActor with UntypedConsumer { + /** + * Returns the [[org.apache.camel.CamelContext]] + * @return the CamelContext + */ + protected def getCamelContext: CamelContext = camelContext + + /** + * Returns the [[org.apache.camel.ProducerTemplate]] + * @return the ProducerTemplate + */ + protected def getProducerTemplate: ProducerTemplate = camel.template +} diff --git a/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala b/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala index 0865c5e02a..b947e43d64 100644 --- a/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala +++ b/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala @@ -19,7 +19,7 @@ abstract class UntypedProducerActor extends UntypedActor with ProducerSupport { * message is passed as argument. By default, this method simply returns the argument but may be overridden * by subclasses. */ - def onReceiveBeforeProduce(message: Any): Any = super.receiveBeforeProduce(message) + def onReceiveBeforeProduce(message: AnyRef): AnyRef = message /** * Called after a response was received from the endpoint specified by endpointUri. The @@ -27,14 +27,14 @@ abstract class UntypedProducerActor extends UntypedActor with ProducerSupport { * if oneway is false. If oneway is true, nothing is * done. This method may be overridden by subclasses (e.g. to forward responses to another actor). */ - def onReceiveAfterProduce(message: Any): Unit = super.receiveAfterProduce(message) + def onReceiveAfterProduce(message: AnyRef): Unit = super.receiveAfterProduce(message) final override def receiveBeforeProduce = { - case msg ⇒ onReceiveBeforeProduce(msg) + case msg: AnyRef ⇒ onReceiveBeforeProduce(msg) } final override def receiveAfterProduce = { - case msg ⇒ onReceiveAfterProduce(msg) + case msg: AnyRef ⇒ onReceiveAfterProduce(msg) } final override def endpointUri = getEndpointUri @@ -60,13 +60,6 @@ abstract class UntypedProducerActor extends UntypedActor with ProducerSupport { */ def isOneway() = super.oneway - /** - * Creates a RichMessage out of a message. The RichMessage has convenience methods for accessing body and headers - * @param message the message - * @return the RichMessage - */ - def rich(message: Message): RichMessage = message - /** * Returns the CamelContext. */ diff --git a/akka-camel/src/main/scala/akka/camelexamples/ExamplesSupport.scala b/akka-camel/src/main/scala/akka/camelexamples/ExamplesSupport.scala index f795f217a7..6140075823 100644 --- a/akka-camel/src/main/scala/akka/camelexamples/ExamplesSupport.scala +++ b/akka-camel/src/main/scala/akka/camelexamples/ExamplesSupport.scala @@ -20,7 +20,7 @@ class SysOutConsumer extends Consumer { def endpointUri = "file://data/input/CamelConsumer" protected def receive = { - case msg: Message ⇒ { + case msg: CamelMessage ⇒ { printf("Received '%s'\n", msg.bodyAs[String]) } } @@ -34,8 +34,9 @@ class TroubleMaker extends Consumer { } class SysOutActor(implicit camel: Camel) extends Actor { + implicit val camelContext = camel.context protected def receive = { - case msg: Message ⇒ { + case msg: CamelMessage ⇒ { printf("Received '%s'\n", msg.bodyAs[String]) } } diff --git a/akka-camel/src/main/scala/akka/package.scala b/akka-camel/src/main/scala/akka/package.scala index b2632b4d2f..436d2fc1b3 100644 --- a/akka-camel/src/main/scala/akka/package.scala +++ b/akka-camel/src/main/scala/akka/package.scala @@ -8,5 +8,4 @@ import org.apache.camel.model.ProcessorDefinition package object camel { implicit def toActorRouteDefinition(definition: ProcessorDefinition[_]) = new ActorRouteDefinition(definition) - implicit def messageToRichMessage(m: Message)(implicit camel: Camel): RichMessage = new RichMessage(m, camel.context) } \ No newline at end of file diff --git a/akka-camel/src/on-hold/test/scala/akka/camel/CamelTestSupport.scala b/akka-camel/src/on-hold/test/scala/akka/camel/CamelTestSupport.scala deleted file mode 100644 index ea37c03a9c..0000000000 --- a/akka-camel/src/on-hold/test/scala/akka/camel/CamelTestSupport.scala +++ /dev/null @@ -1,79 +0,0 @@ -package akka.camel - -import java.util.concurrent.CountDownLatch - -import collection.mutable.Buffer - -import akka.actor.Actor - -object CamelTestSupport { - type Handler = PartialFunction[Any, Any] - - trait TestActor extends Actor { - def receive = { - case msg => { - handler(msg) - } - } - - def handler: Handler - } - - class Tester1 extends TestActor with Retain with Countdown { - def handler = retain andThen countdown - } - - class Tester2 extends TestActor with Respond { - def handler = respond - } - - class Tester3 extends TestActor with Noop { - self.timeout = 1 - def handler = noop - } - - trait Countdown { this: Actor => - var latch: CountDownLatch = new CountDownLatch(0) - def countdown: Handler = { - case SetExpectedMessageCount(num) => { - latch = new CountDownLatch(num) - self.reply(latch) - } - case msg => latch.countDown - } - } - - trait Respond { this: Actor => - def respond: Handler = { - case msg: Message => self.reply(response(msg)) - } - - def response(msg: Message): Any = "Hello %s" format msg.body - } - - trait Retain { this: Actor => - val messages = Buffer[Any]() - - def retain: Handler = { - case GetRetainedMessage => self.reply(messages.last) - case GetRetainedMessages(p) => self.reply(messages.toList.filter(p)) - case msg => { - messages += msg - msg - } - } - } - - trait Noop { this: Actor => - def noop: Handler = { - case msg => msg - } - } - - case class SetExpectedMessageCount(num: Int) - case class GetRetainedMessage() - case class GetRetainedMessages(p: Any => Boolean) { - def this() = this(_ => true) - } -} - diff --git a/akka-camel/src/on-hold/test/scala/akka/camel/component/ActorComponentFeatureTest.scala b/akka-camel/src/on-hold/test/scala/akka/camel/component/ActorComponentFeatureTest.scala deleted file mode 100644 index 4795aab378..0000000000 --- a/akka-camel/src/on-hold/test/scala/akka/camel/component/ActorComponentFeatureTest.scala +++ /dev/null @@ -1,130 +0,0 @@ -package akka.camel.component - -import java.util.concurrent.{TimeUnit, CountDownLatch} - -import org.apache.camel.RuntimeCamelException -import org.apache.camel.builder.RouteBuilder -import org.apache.camel.component.mock.MockEndpoint -import org.scalatest.{BeforeAndAfterEach, BeforeAndAfterAll, FeatureSpec} - -import akka.actor.Actor -import akka.actor.Actor._ -import akka.camel.{Failure, Message, CamelContextManager} -import akka.camel.CamelTestSupport._ - -class ActorComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll with BeforeAndAfterEach { - import ActorComponentFeatureTest._ - - override protected def beforeAll = { - Actor.registry.shutdownAll - CamelContextManager.init - CamelContextManager.mandatoryContext.addRoutes(new TestRoute) - CamelContextManager.start - } - - override protected def afterAll = CamelContextManager.stop - - override protected def afterEach = { - Actor.registry.shutdownAll - mockEndpoint.reset - } - - feature("Communicate with an actor via an actor:uuid endpoint") { - import CamelContextManager.mandatoryTemplate - - scenario("one-way communication") { - val actor = actorOf[Tester1].start - val latch = (actor !! SetExpectedMessageCount(1)).as[CountDownLatch].get - mandatoryTemplate.sendBody("actor:uuid:%s" format actor.uuid, "Martin") - assert(latch.await(5000, TimeUnit.MILLISECONDS)) - val reply = (actor !! GetRetainedMessage).get.asInstanceOf[Message] - assert(reply.body === "Martin") - } - - scenario("two-way communication") { - val actor = actorOf[Tester2].start - assert(mandatoryTemplate.requestBody("actor:uuid:%s" format actor.uuid, "Martin") === "Hello Martin") - } - - scenario("two-way communication with timeout") { - val actor = actorOf[Tester3].start - intercept[RuntimeCamelException] { - mandatoryTemplate.requestBody("actor:uuid:%s?blocking=true" format actor.uuid, "Martin") - } - } - - scenario("two-way communication via a custom route with failure response") { - mockEndpoint.expectedBodiesReceived("whatever") - mandatoryTemplate.requestBody("direct:failure-test-1", "whatever") - mockEndpoint.assertIsSatisfied - } - - scenario("two-way communication via a custom route with exception") { - mockEndpoint.expectedBodiesReceived("whatever") - mandatoryTemplate.requestBody("direct:failure-test-2", "whatever") - mockEndpoint.assertIsSatisfied - } - } - - feature("Communicate with an actor via an actor:id endpoint") { - import CamelContextManager.mandatoryTemplate - - scenario("one-way communication") { - val actor = actorOf[Tester1].start - val latch = (actor !! SetExpectedMessageCount(1)).as[CountDownLatch].get - mandatoryTemplate.sendBody("actor:%s" format actor.id, "Martin") - assert(latch.await(5000, TimeUnit.MILLISECONDS)) - val reply = (actor !! GetRetainedMessage).get.asInstanceOf[Message] - assert(reply.body === "Martin") - } - - scenario("two-way communication") { - val actor = actorOf[Tester2].start - assert(mandatoryTemplate.requestBody("actor:%s" format actor.id, "Martin") === "Hello Martin") - } - - scenario("two-way communication via a custom route") { - val actor = actorOf[CustomIdActor].start - assert(mandatoryTemplate.requestBody("direct:custom-id-test-1", "Martin") === "Received Martin") - assert(mandatoryTemplate.requestBody("direct:custom-id-test-2", "Martin") === "Received Martin") - } - } - - private def mockEndpoint = CamelContextManager.mandatoryContext.getEndpoint("mock:mock", classOf[MockEndpoint]) -} - -object ActorComponentFeatureTest { - class CustomIdActor extends Actor { - self.id = "custom-id" - protected def receive = { - case msg: Message => self.reply("Received %s" format msg.body) - } - } - - class FailWithMessage extends Actor { - protected def receive = { - case msg: Message => self.reply(Failure(new Exception("test"))) - } - } - - class FailWithException extends Actor { - protected def receive = { - case msg: Message => throw new Exception("test") - } - } - - class TestRoute extends RouteBuilder { - val failWithMessage = actorOf[FailWithMessage].start - val failWithException = actorOf[FailWithException].start - def configure { - from("direct:custom-id-test-1").to("actor:custom-id") - from("direct:custom-id-test-2").to("actor:id:custom-id") - from("direct:failure-test-1") - .onException(classOf[Exception]).to("mock:mock").handled(true).end - .to("actor:uuid:%s" format failWithMessage.uuid) - from("direct:failure-test-2") - .onException(classOf[Exception]).to("mock:mock").handled(true).end - .to("actor:uuid:%s?blocking=true" format failWithException.uuid) - } - } -} diff --git a/akka-camel/src/on-hold/test/scala/akka/camel/component/ActorProducerTest.scala b/akka-camel/src/on-hold/test/scala/akka/camel/component/ActorProducerTest.scala deleted file mode 100644 index e9a407189d..0000000000 --- a/akka-camel/src/on-hold/test/scala/akka/camel/component/ActorProducerTest.scala +++ /dev/null @@ -1,243 +0,0 @@ -package akka.camel.component - -import ActorComponentTest._ - -import java.util.concurrent.{CountDownLatch, TimeoutException, TimeUnit} - -import org.apache.camel.{AsyncCallback, ExchangePattern} - -import org.junit.{After, Test} -import org.scalatest.junit.JUnitSuite -import org.scalatest.BeforeAndAfterAll - -import akka.actor.Actor._ -import akka.camel.{Failure, Message} -import akka.camel.CamelTestSupport._ - -class ActorProducerTest extends JUnitSuite with BeforeAndAfterAll { - import ActorProducerTest._ - - @After def tearDown = registry.shutdownAll - - @Test def shouldSendMessageToActorWithSyncProcessor = { - val actor = actorOf[Tester1].start - val latch = (actor !! SetExpectedMessageCount(1)).as[CountDownLatch].get - val endpoint = actorEndpoint("actor:uuid:%s" format actor.uuid) - val exchange = endpoint.createExchange(ExchangePattern.InOnly) - exchange.getIn.setBody("Martin") - exchange.getIn.setHeader("k1", "v1") - actorProducer(endpoint).process(exchange) - assert(latch.await(5000, TimeUnit.MILLISECONDS)) - val reply = (actor !! GetRetainedMessage).get.asInstanceOf[Message] - assert(reply.body === "Martin") - assert(reply.headers === Map(Message.MessageExchangeId -> exchange.getExchangeId, "k1" -> "v1")) - } - - @Test def shouldSendMessageToActorWithAsyncProcessor = { - val actor = actorOf[Tester1].start - val latch = (actor !! SetExpectedMessageCount(1)).as[CountDownLatch].get - val endpoint = actorEndpoint("actor:uuid:%s" format actor.uuid) - val exchange = endpoint.createExchange(ExchangePattern.InOnly) - exchange.getIn.setBody("Martin") - exchange.getIn.setHeader("k1", "v1") - actorAsyncProducer(endpoint).process(exchange, expectSyncCompletion) - assert(latch.await(5000, TimeUnit.MILLISECONDS)) - val reply = (actor !! GetRetainedMessage).get.asInstanceOf[Message] - assert(reply.body === "Martin") - assert(reply.headers === Map(Message.MessageExchangeId -> exchange.getExchangeId, "k1" -> "v1")) - } - - @Test def shouldSendMessageToActorAndReceiveResponseWithSyncProcessor = { - val actor = actorOf(new Tester2 { - override def response(msg: Message) = Message(super.response(msg), Map("k2" -> "v2")) - }).start - val endpoint = actorEndpoint("actor:uuid:%s" format actor.uuid) - val exchange = endpoint.createExchange(ExchangePattern.InOut) - exchange.getIn.setBody("Martin") - exchange.getIn.setHeader("k1", "v1") - actorProducer(endpoint).process(exchange) - assert(exchange.getOut.getBody === "Hello Martin") - assert(exchange.getOut.getHeader("k2") === "v2") - } - - @Test def shouldSendMessageToActorAndReceiveResponseWithAsyncProcessor = { - val actor = actorOf(new Tester2 { - override def response(msg: Message) = Message(super.response(msg), Map("k2" -> "v2")) - }).start - val completion = expectAsyncCompletion - val endpoint = actorEndpoint("actor:uuid:%s" format actor.uuid) - val exchange = endpoint.createExchange(ExchangePattern.InOut) - exchange.getIn.setBody("Martin") - exchange.getIn.setHeader("k1", "v1") - actorAsyncProducer(endpoint).process(exchange, completion) - assert(completion.latch.await(5000, TimeUnit.MILLISECONDS)) - assert(exchange.getOut.getBody === "Hello Martin") - assert(exchange.getOut.getHeader("k2") === "v2") - } - - @Test def shouldSendMessageToActorAndReceiveFailureWithAsyncProcessor = { - val actor = actorOf(new Tester2 { - override def response(msg: Message) = Failure(new Exception("testmsg"), Map("k3" -> "v3")) - }).start - val completion = expectAsyncCompletion - val endpoint = actorEndpoint("actor:uuid:%s" format actor.uuid) - val exchange = endpoint.createExchange(ExchangePattern.InOut) - exchange.getIn.setBody("Martin") - exchange.getIn.setHeader("k1", "v1") - actorAsyncProducer(endpoint).process(exchange, completion) - assert(completion.latch.await(5000, TimeUnit.MILLISECONDS)) - assert(exchange.getException.getMessage === "testmsg") - assert(exchange.getOut.getBody === null) - assert(exchange.getOut.getHeader("k3") === null) // headers from failure message are currently ignored - } - - @Test def shouldSendMessageToActorAndReceiveAckWithAsyncProcessor = { - val actor = actorOf(new Tester2 { - override def response(msg: Message) = akka.camel.Ack - }).start - val completion = expectAsyncCompletion - val endpoint = actorEndpoint("actor:uuid:%s?autoack=false" format actor.uuid) - val exchange = endpoint.createExchange(ExchangePattern.InOnly) - exchange.getIn.setBody("Martin") - actorAsyncProducer(endpoint).process(exchange, completion) - assert(completion.latch.await(5000, TimeUnit.MILLISECONDS)) - assert(exchange.getIn.getBody === "Martin") - assert(exchange.getOut.getBody === null) - } - - @Test def shouldDynamicallyRouteMessageToActorWithDefaultId = { - val actor1 = actorOf[Tester1] - val actor2 = actorOf[Tester1] - actor1.id = "x" - actor2.id = "y" - actor1.start - actor2.start - val latch1 = (actor1 !! SetExpectedMessageCount(1)).as[CountDownLatch].get - val latch2 = (actor2 !! SetExpectedMessageCount(1)).as[CountDownLatch].get - val endpoint = actorEndpoint("actor:id:%s" format actor1.id) - val exchange1 = endpoint.createExchange(ExchangePattern.InOnly) - val exchange2 = endpoint.createExchange(ExchangePattern.InOnly) - exchange1.getIn.setBody("Test1") - exchange2.getIn.setBody("Test2") - exchange2.getIn.setHeader(ActorComponent.ActorIdentifier, actor2.id) - actorProducer(endpoint).process(exchange1) - actorProducer(endpoint).process(exchange2) - assert(latch1.await(5, TimeUnit.SECONDS)) - assert(latch2.await(5, TimeUnit.SECONDS)) - val reply1 = (actor1 !! GetRetainedMessage).get.asInstanceOf[Message] - val reply2 = (actor2 !! GetRetainedMessage).get.asInstanceOf[Message] - assert(reply1.body === "Test1") - assert(reply2.body === "Test2") - } - - @Test def shouldDynamicallyRouteMessageToActorWithoutDefaultId = { - val actor1 = actorOf[Tester1] - val actor2 = actorOf[Tester1] - actor1.id = "x" - actor2.id = "y" - actor1.start - actor2.start - val latch1 = (actor1 !! SetExpectedMessageCount(1)).as[CountDownLatch].get - val latch2 = (actor2 !! SetExpectedMessageCount(1)).as[CountDownLatch].get - val endpoint = actorEndpoint("actor:id:") - val exchange1 = endpoint.createExchange(ExchangePattern.InOnly) - val exchange2 = endpoint.createExchange(ExchangePattern.InOnly) - exchange1.getIn.setBody("Test1") - exchange2.getIn.setBody("Test2") - exchange1.getIn.setHeader(ActorComponent.ActorIdentifier, actor1.id) - exchange2.getIn.setHeader(ActorComponent.ActorIdentifier, actor2.id) - actorProducer(endpoint).process(exchange1) - actorProducer(endpoint).process(exchange2) - assert(latch1.await(5, TimeUnit.SECONDS)) - assert(latch2.await(5, TimeUnit.SECONDS)) - val reply1 = (actor1 !! GetRetainedMessage).get.asInstanceOf[Message] - val reply2 = (actor2 !! GetRetainedMessage).get.asInstanceOf[Message] - assert(reply1.body === "Test1") - assert(reply2.body === "Test2") - } - - @Test def shouldDynamicallyRouteMessageToActorWithDefaultUuid = { - val actor1 = actorOf[Tester1].start - val actor2 = actorOf[Tester1].start - val latch1 = (actor1 !! SetExpectedMessageCount(1)).as[CountDownLatch].get - val latch2 = (actor2 !! SetExpectedMessageCount(1)).as[CountDownLatch].get - val endpoint = actorEndpoint("actor:uuid:%s" format actor1.uuid) - val exchange1 = endpoint.createExchange(ExchangePattern.InOnly) - val exchange2 = endpoint.createExchange(ExchangePattern.InOnly) - exchange1.getIn.setBody("Test1") - exchange2.getIn.setBody("Test2") - exchange2.getIn.setHeader(ActorComponent.ActorIdentifier, actor2.uuid.toString) - actorProducer(endpoint).process(exchange1) - actorProducer(endpoint).process(exchange2) - assert(latch1.await(5, TimeUnit.SECONDS)) - assert(latch2.await(5, TimeUnit.SECONDS)) - val reply1 = (actor1 !! GetRetainedMessage).get.asInstanceOf[Message] - val reply2 = (actor2 !! GetRetainedMessage).get.asInstanceOf[Message] - assert(reply1.body === "Test1") - assert(reply2.body === "Test2") - } - - @Test def shouldDynamicallyRouteMessageToActorWithoutDefaultUuid = { - val actor1 = actorOf[Tester1].start - val actor2 = actorOf[Tester1].start - val latch1 = (actor1 !! SetExpectedMessageCount(1)).as[CountDownLatch].get - val latch2 = (actor2 !! SetExpectedMessageCount(1)).as[CountDownLatch].get - val endpoint = actorEndpoint("actor:uuid:") - val exchange1 = endpoint.createExchange(ExchangePattern.InOnly) - val exchange2 = endpoint.createExchange(ExchangePattern.InOnly) - exchange1.getIn.setBody("Test1") - exchange2.getIn.setBody("Test2") - exchange1.getIn.setHeader(ActorComponent.ActorIdentifier, actor1.uuid) - exchange2.getIn.setHeader(ActorComponent.ActorIdentifier, actor2.uuid.toString) - actorProducer(endpoint).process(exchange1) - actorProducer(endpoint).process(exchange2) - assert(latch1.await(5, TimeUnit.SECONDS)) - assert(latch2.await(5, TimeUnit.SECONDS)) - val reply1 = (actor1 !! GetRetainedMessage).get.asInstanceOf[Message] - val reply2 = (actor2 !! GetRetainedMessage).get.asInstanceOf[Message] - assert(reply1.body === "Test1") - assert(reply2.body === "Test2") - } - - @Test def shouldThrowExceptionWhenIdNotSet: Unit = { - val actor = actorOf[Tester1].start - val latch = (actor !! SetExpectedMessageCount(1)).as[CountDownLatch].get - val endpoint = actorEndpoint("actor:id:") - intercept[ActorIdentifierNotSetException] { - actorProducer(endpoint).process(endpoint.createExchange(ExchangePattern.InOnly)) - } - } - - @Test def shouldThrowExceptionWhenUuidNotSet: Unit = { - val actor = actorOf[Tester1].start - val latch = (actor !! SetExpectedMessageCount(1)).as[CountDownLatch].get - val endpoint = actorEndpoint("actor:uuid:") - intercept[ActorIdentifierNotSetException] { - actorProducer(endpoint).process(endpoint.createExchange(ExchangePattern.InOnly)) - } - } - - @Test def shouldSendMessageToActorAndTimeout(): Unit = { - val actor = actorOf[Tester3].start - val endpoint = actorEndpoint("actor:uuid:%s" format actor.uuid) - val exchange = endpoint.createExchange(ExchangePattern.InOut) - exchange.getIn.setBody("Martin") - intercept[TimeoutException] { - endpoint.createProducer.process(exchange) - } - } -} - -object ActorProducerTest { - def expectSyncCompletion = new AsyncCallback { - def done(doneSync: Boolean) = assert(doneSync) - } - - def expectAsyncCompletion = new AsyncCallback { - val latch = new CountDownLatch(1); - def done(doneSync: Boolean) = { - assert(!doneSync) - latch.countDown - } - } -} diff --git a/akka-camel/src/test/java/akka/camel/MessageJavaTestBase.java b/akka-camel/src/test/java/akka/camel/MessageJavaTestBase.java index 227ee8a5a4..ba483e7a13 100644 --- a/akka-camel/src/test/java/akka/camel/MessageJavaTestBase.java +++ b/akka-camel/src/test/java/akka/camel/MessageJavaTestBase.java @@ -35,50 +35,49 @@ public class MessageJavaTestBase { system.shutdown(); } - Message message(Object body){ return new Message(body, new HashMap()); } - Message message(Object body, Map headers){ return new Message(body, headers); } - private RichMessage rich(Message message) { return new RichMessage(message, camel.context()); } + CamelMessage message(Object body){ return new CamelMessage(body, new HashMap()); } + CamelMessage message(Object body, Map headers){ return new CamelMessage(body, headers); } @Test public void shouldConvertDoubleBodyToString() { - assertEquals("1.4", rich(message("1.4", empty)).getBodyAs(String.class)); + assertEquals("1.4", message("1.4", empty).getBodyAs(String.class,camel.context())); } @Test(expected=NoTypeConversionAvailableException.class) public void shouldThrowExceptionWhenConvertingDoubleBodyToInputStream() { - rich(message(1.4)).getBodyAs(InputStream.class); + message(1.4).getBodyAs(InputStream.class,camel.context()); } @Test public void shouldReturnDoubleHeader() { - Message message = message("test" , createMap("test", 1.4)); + CamelMessage message = message("test" , createMap("test", 1.4)); assertEquals(1.4, message.getHeader("test")); } @Test public void shouldConvertDoubleHeaderToString() { - Message message = message("test" , createMap("test", 1.4)); - assertEquals("1.4", rich(message).getHeaderAs("test", String.class)); + CamelMessage message = message("test" , createMap("test", 1.4)); + assertEquals("1.4", message.getHeaderAs("test", String.class,camel.context())); } @Test public void shouldReturnSubsetOfHeaders() { - Message message = message("test" , createMap("A", "1", "B", "2")); + CamelMessage message = message("test" , createMap("A", "1", "B", "2")); assertEquals(createMap("B", "2"), message.getHeaders(createSet("B"))); } @Test(expected=UnsupportedOperationException.class) public void shouldReturnSubsetOfHeadersUnmodifiable() { - Message message = message("test" , createMap("A", "1", "B", "2")); + CamelMessage message = message("test" , createMap("A", "1", "B", "2")); message.getHeaders(createSet("B")).put("x", "y"); } @Test public void shouldReturnAllHeaders() { - Message message = message("test" , createMap("A", "1", "B", "2")); + CamelMessage message = message("test" , createMap("A", "1", "B", "2")); assertEquals(createMap("A", "1", "B", "2"), message.getHeaders()); } @Test(expected=UnsupportedOperationException.class) public void shouldReturnAllHeadersUnmodifiable() { - Message message = message("test" , createMap("A", "1", "B", "2")); + CamelMessage message = message("test" , createMap("A", "1", "B", "2")); message.getHeaders().put("x", "y"); } @@ -91,7 +90,7 @@ public class MessageJavaTestBase { @Test public void shouldConvertBodyAndPreserveHeaders() { assertEquals( message("1.4", createMap("A", "1")), - rich(message(1.4 , createMap("A", "1"))).withBodyAs(String.class)); + message(1.4 , createMap("A", "1")).withBodyAs(String.class,camel.context())); } @Test public void shouldSetBodyAndPreserveHeaders() { @@ -109,13 +108,13 @@ public class MessageJavaTestBase { @Test public void shouldAddHeaderAndPreserveBodyAndHeaders() { assertEquals( message("test1" , createMap("A", "1", "B", "2")), - message("test1" , createMap("A", "1")).plusHeader("B", "2")); + message("test1" , createMap("A", "1")).addHeader("B", "2")); } @Test public void shouldAddHeadersAndPreserveBodyAndHeaders() { assertEquals( message("test1" , createMap("A", "1", "B", "2")), - message("test1" , createMap("A", "1")).plusHeaders(createMap("B", "2"))); + message("test1" , createMap("A", "1")).addHeaders(createMap("B", "2"))); } @Test public void shouldRemoveHeadersAndPreserveBodyAndRemainingHeaders() { diff --git a/akka-camel/src/test/java/akka/camel/SampleErrorHandlingConsumer.java b/akka-camel/src/test/java/akka/camel/SampleErrorHandlingConsumer.java index 79393b58da..0622a9a51a 100644 --- a/akka-camel/src/test/java/akka/camel/SampleErrorHandlingConsumer.java +++ b/akka-camel/src/test/java/akka/camel/SampleErrorHandlingConsumer.java @@ -34,8 +34,8 @@ public class SampleErrorHandlingConsumer extends UntypedConsumerActor { public void onReceive(Object message) throws Exception { - Message msg = (Message) message; - String body = rich(msg).getBodyAs(String.class); + CamelMessage msg = (CamelMessage) message; + String body = msg.getBodyAs(String.class,this.getCamelContext()); throw new Exception(String.format("error: %s", body)); } diff --git a/akka-camel/src/test/java/akka/camel/SampleUntypedConsumer.java b/akka-camel/src/test/java/akka/camel/SampleUntypedConsumer.java index 59062f647b..f52a484ccc 100644 --- a/akka-camel/src/test/java/akka/camel/SampleUntypedConsumer.java +++ b/akka-camel/src/test/java/akka/camel/SampleUntypedConsumer.java @@ -16,9 +16,9 @@ public class SampleUntypedConsumer extends UntypedConsumerActor { } public void onReceive(Object message) { - RichMessage msg = rich((Message)message); - String body = msg.getBodyAs(String.class); - String header = msg.getHeaderAs("test", String.class); + CamelMessage msg = (CamelMessage)message; + String body = msg.getBodyAs(String.class, getCamelContext()); + String header = msg.getHeaderAs("test", String.class,getCamelContext()); sender().tell(String.format("%s %s", body, header)); } diff --git a/akka-camel/src/test/java/akka/camel/SampleUntypedForwardingProducer.java b/akka-camel/src/test/java/akka/camel/SampleUntypedForwardingProducer.java index b52fec5d34..ef0b7465c5 100644 --- a/akka-camel/src/test/java/akka/camel/SampleUntypedForwardingProducer.java +++ b/akka-camel/src/test/java/akka/camel/SampleUntypedForwardingProducer.java @@ -16,8 +16,8 @@ public class SampleUntypedForwardingProducer extends UntypedProducerActor { @Override public void onReceiveAfterProduce(Object message) { - RichMessage msg = rich((Message)message); - String body = msg.getBodyAs(String.class); + CamelMessage msg = (CamelMessage)message; + String body = msg.getBodyAs(String.class,getCamelContext()); getProducerTemplate().sendBody("direct:forward-test-1", body); } } diff --git a/akka-camel/src/test/scala/akka/camel/ActivationIntegrationTest.scala b/akka-camel/src/test/scala/akka/camel/ActivationIntegrationTest.scala index 69f1420b6a..4fc15e8b5b 100644 --- a/akka-camel/src/test/scala/akka/camel/ActivationIntegrationTest.scala +++ b/akka-camel/src/test/scala/akka/camel/ActivationIntegrationTest.scala @@ -9,9 +9,10 @@ import akka.util.duration._ import org.apache.camel.ProducerTemplate import akka.actor._ import akka.util.Timeout -import java.util.concurrent.{ TimeUnit, CountDownLatch } import TestSupport._ import org.scalatest.WordSpec +import akka.testkit.TestLatch +import akka.dispatch.Await class ActivationIntegrationTest extends WordSpec with MustMatchers with SharedCamelSystem { implicit val timeout = Timeout(10 seconds) @@ -31,21 +32,21 @@ class ActivationIntegrationTest extends WordSpec with MustMatchers with SharedCa } "ActivationAware must be notified when endpoint is de-activated" in { - val stopped = new CountDownLatch(1) + val latch = TestLatch() val actor = start(new Consumer { def endpointUri = "direct:a3" def receive = { case _ ⇒ {} } override def postStop() = { super.postStop() - stopped.countDown() + latch.countDown() } }) camel.awaitActivation(actor, 1 second) system.stop(actor) camel.awaitDeactivation(actor, 1 second) - if (!stopped.await(1, TimeUnit.SECONDS)) fail("Actor must have stopped quickly after deactivation!") + Await.ready(latch, 1 second) } "ActivationAware must time out when waiting for endpoint de-activation for too long" in { @@ -66,7 +67,7 @@ class ActivationIntegrationTest extends WordSpec with MustMatchers with SharedCa class TestConsumer(uri: String) extends Consumer { def endpointUri = uri override def receive = { - case msg: Message ⇒ sender ! "received " + msg.body + case msg: CamelMessage ⇒ sender ! "received " + msg.body } } diff --git a/akka-camel/src/test/scala/akka/camel/CamelExchangeAdapterTest.scala b/akka-camel/src/test/scala/akka/camel/CamelExchangeAdapterTest.scala index b51fb23219..676062a2b7 100644 --- a/akka-camel/src/test/scala/akka/camel/CamelExchangeAdapterTest.scala +++ b/akka-camel/src/test/scala/akka/camel/CamelExchangeAdapterTest.scala @@ -26,19 +26,23 @@ class CamelExchangeAdapterTest extends FunSuite with SharedCamelSystem with Mess } test("mustSetOutMessageFromResponseMessage") { - val e1 = sampleInOut; e1.setResponse(Message("y")) + val e1 = sampleInOut + e1.setResponse(Message("y")) assert(e1.getOut.getBody === "y") } test("mustSetInMessageFromResponseMessage") { - val e1 = sampleInOnly; e1.setResponse(Message("x")) + val e1 = sampleInOnly + e1.setResponse(Message("x")) assert(e1.getIn.getBody === "x") } test("mustSetExceptionFromFailureMessage") { - val e1 = sampleInOnly; e1.setFailure(Failure(new Exception("test1"))) + val e1 = sampleInOnly + e1.setFailure(Failure(new Exception("test1"))) assert(e1.getException.getMessage === "test1") - val e2 = sampleInOut; e2.setFailure(Failure(new Exception("test2"))) + val e2 = sampleInOut + e2.setFailure(Failure(new Exception("test2"))) assert(e2.getException.getMessage === "test2") } diff --git a/akka-camel/src/test/scala/akka/camel/MessageTest.scala b/akka-camel/src/test/scala/akka/camel/CamelMessageTest.scala similarity index 77% rename from akka-camel/src/test/scala/akka/camel/MessageTest.scala rename to akka-camel/src/test/scala/akka/camel/CamelMessageTest.scala index cb1fab9e58..c5dfd01d00 100644 --- a/akka-camel/src/test/scala/akka/camel/MessageTest.scala +++ b/akka-camel/src/test/scala/akka/camel/CamelMessageTest.scala @@ -5,32 +5,31 @@ package akka.camel import org.apache.camel.impl.{ DefaultExchange, DefaultMessage } -import org.apache.camel.{ Message ⇒ CamelMessage } import akka.camel.TestSupport.SharedCamelSystem import org.scalatest.matchers.MustMatchers import org.scalatest.WordSpec //TODO merge it with MessageScalaTest -class MessageTest extends MustMatchers with WordSpec with SharedCamelSystem { +class CamelMessageTest extends MustMatchers with WordSpec with SharedCamelSystem { - "Message" must { + "CamelMessage" must { "overwrite body and add header" in { val msg = sampleMessage - Message("blah", Map("key" -> "baz")).copyContentTo(msg) + CamelMessage("blah", Map("key" -> "baz")).copyContentTo(msg) assert(msg.getBody === "blah") assert(msg.getHeader("foo") === "bar") assert(msg.getHeader("key") === "baz") } "create message with body and header" in { - val m = Message.from(sampleMessage) + val m = CamelMessage.from(sampleMessage) assert(m.body === "test") assert(m.headers("foo") === "bar") } "create message with body and header and custom header" in { - val m = Message.from(sampleMessage, Map("key" -> "baz")) + val m = CamelMessage.from(sampleMessage, Map("key" -> "baz")) assert(m.body === "test") assert(m.headers("foo") === "bar") assert(m.headers("key") === "baz") diff --git a/akka-camel/src/test/scala/akka/camel/ConsumerIntegrationTest.scala b/akka-camel/src/test/scala/akka/camel/ConsumerIntegrationTest.scala index 283206e8f6..46070337c7 100644 --- a/akka-camel/src/test/scala/akka/camel/ConsumerIntegrationTest.scala +++ b/akka-camel/src/test/scala/akka/camel/ConsumerIntegrationTest.scala @@ -7,29 +7,30 @@ package akka.camel import akka.actor._ import org.scalatest.matchers.MustMatchers import akka.util.duration._ -import java.util.concurrent.TimeUnit._ import TestSupport._ import org.scalatest.WordSpec import org.apache.camel.model.RouteDefinition import org.apache.camel.builder.Builder import org.apache.camel.{ FailedToCreateRouteException, CamelExecutionException } -import java.util.concurrent.{ ExecutionException, TimeUnit, TimeoutException, CountDownLatch } +import java.util.concurrent.{ ExecutionException, TimeUnit, TimeoutException } +import akka.testkit.TestLatch +import akka.dispatch.Await class ConsumerIntegrationTest extends WordSpec with MustMatchers with NonSharedCamelSystem { - + private val defaultTimeout = 10 "Consumer must throw FailedToCreateRouteException, while awaiting activation, if endpoint is invalid" in { val actorRef = system.actorOf(Props(new TestActor(uri = "some invalid uri"))) intercept[FailedToCreateRouteException] { - camel.awaitActivation(actorRef, timeout = 1 second) + camel.awaitActivation(actorRef, timeout = defaultTimeout seconds) } } "Consumer must support in-out messaging" in { start(new Consumer { def endpointUri = "direct:a1" - protected def receive = { - case m: Message ⇒ sender ! "received " + m.bodyAs[String] + def receive = { + case m: CamelMessage ⇒ sender ! "received " + m.bodyAs[String] } }) camel.sendTo("direct:a1", msg = "some message") must be("received some message") @@ -43,7 +44,7 @@ class ConsumerIntegrationTest extends WordSpec with MustMatchers with NonSharedC override def replyTimeout = SHORT_TIMEOUT def endpointUri = "direct:a3" - protected def receive = { case _ ⇒ { Thread.sleep(LONG_WAIT.toMillis); sender ! "done" } } + def receive = { case _ ⇒ { Thread.sleep(LONG_WAIT.toMillis); sender ! "done" } } }) val exception = intercept[CamelExecutionException] { @@ -53,13 +54,13 @@ class ConsumerIntegrationTest extends WordSpec with MustMatchers with NonSharedC } "Consumer must process messages even after actor restart" in { - val restarted = new CountDownLatch(1) + val restarted = TestLatch() val consumer = start(new Consumer { def endpointUri = "direct:a2" - protected def receive = { - case "throw" ⇒ throw new Exception - case m: Message ⇒ sender ! "received " + m.bodyAs[String] + def receive = { + case "throw" ⇒ throw new Exception + case m: CamelMessage ⇒ sender ! "received " + m.bodyAs[String] } override def postRestart(reason: Throwable) { @@ -67,7 +68,7 @@ class ConsumerIntegrationTest extends WordSpec with MustMatchers with NonSharedC } }) consumer ! "throw" - if (!restarted.await(1, SECONDS)) fail("Actor failed to restart!") + Await.ready(restarted, defaultTimeout seconds) val response = camel.sendTo("direct:a2", msg = "xyz") response must be("received xyz") @@ -75,12 +76,12 @@ class ConsumerIntegrationTest extends WordSpec with MustMatchers with NonSharedC "Consumer must unregister itself when stopped" in { val consumer = start(new TestActor()) - camel.awaitActivation(consumer, 1 second) + camel.awaitActivation(consumer, defaultTimeout seconds) camel.routeCount must be > (0) system.stop(consumer) - camel.awaitDeactivation(consumer, 1 second) + camel.awaitDeactivation(consumer, defaultTimeout seconds) camel.routeCount must be(0) } @@ -106,20 +107,20 @@ class ConsumerIntegrationTest extends WordSpec with MustMatchers with NonSharedC "Consumer supports manual Ack" in { start(new ManualAckConsumer() { def endpointUri = "direct:manual-ack" - protected def receive = { case _ ⇒ sender ! Ack } + def receive = { case _ ⇒ sender ! Ack } }) - camel.template.asyncSendBody("direct:manual-ack", "some message").get(1, TimeUnit.SECONDS) must be(null) //should not timeout + camel.template.asyncSendBody("direct:manual-ack", "some message").get(defaultTimeout, TimeUnit.SECONDS) must be(null) //should not timeout } "Consumer handles manual Ack failure" in { val someException = new Exception("e1") start(new ManualAckConsumer() { def endpointUri = "direct:manual-ack" - protected def receive = { case _ ⇒ sender ! Failure(someException) } + def receive = { case _ ⇒ sender ! Failure(someException) } }) intercept[ExecutionException] { - camel.template.asyncSendBody("direct:manual-ack", "some message").get(1, TimeUnit.SECONDS) + camel.template.asyncSendBody("direct:manual-ack", "some message").get(defaultTimeout, TimeUnit.SECONDS) }.getCause.getCause must be(someException) } @@ -127,25 +128,25 @@ class ConsumerIntegrationTest extends WordSpec with MustMatchers with NonSharedC start(new ManualAckConsumer() { override def replyTimeout = 10 millis def endpointUri = "direct:manual-ack" - protected def receive = { case _ ⇒ } + def receive = { case _ ⇒ } }) intercept[ExecutionException] { - camel.template.asyncSendBody("direct:manual-ack", "some message").get(1, TimeUnit.SECONDS) + camel.template.asyncSendBody("direct:manual-ack", "some message").get(defaultTimeout, TimeUnit.SECONDS) }.getCause.getCause.getMessage must include("Failed to get Ack") } } class ErrorThrowingConsumer(override val endpointUri: String) extends Consumer { def receive = { - case msg: Message ⇒ throw new Exception("error: %s" format msg.body) + case msg: CamelMessage ⇒ throw new Exception("error: %s" format msg.body) } } class FailingOnceConsumer(override val endpointUri: String) extends Consumer { def receive = { - case msg: Message ⇒ + case msg: CamelMessage ⇒ if (msg.headerAs[Boolean]("CamelRedelivered").getOrElse(false)) sender ! ("accepted: %s" format msg.body) else @@ -155,5 +156,16 @@ class FailingOnceConsumer(override val endpointUri: String) extends Consumer { class TestActor(uri: String = "file://target/abcde") extends Consumer { def endpointUri = uri - protected def receive = { case _ ⇒ /* do nothing */ } + def receive = { case _ ⇒ /* do nothing */ } +} + +trait ErrorPassing { + self: Actor ⇒ + final override def preRestart(reason: Throwable, message: Option[Any]) { + sender ! Failure(reason) + } +} + +trait ManualAckConsumer extends Consumer { + override def autoack = false } diff --git a/akka-camel/src/test/scala/akka/camel/MessageScalaTest.scala b/akka-camel/src/test/scala/akka/camel/MessageScalaTest.scala index 09e52fd4d2..81fa0678ed 100644 --- a/akka-camel/src/test/scala/akka/camel/MessageScalaTest.scala +++ b/akka-camel/src/test/scala/akka/camel/MessageScalaTest.scala @@ -12,7 +12,7 @@ import org.scalatest.FunSuite import org.scalatest.matchers.MustMatchers class MessageScalaTest extends FunSuite with MustMatchers with SharedCamelSystem with MessageSugar { - + implicit def camelContext = camel.context test("mustConvertDoubleBodyToString") { Message(1.4).bodyAs[String] must be("1.4") } @@ -59,13 +59,13 @@ class MessageScalaTest extends FunSuite with MustMatchers with SharedCamelSystem } test("mustAddHeaderAndPreserveBodyAndHeaders") { - Message("test1", Map("A" -> "1")).plusHeader("B" -> "2") must be( + Message("test1", Map("A" -> "1")).addHeader("B" -> "2") must be( Message("test1", Map("A" -> "1", "B" -> "2"))) } test("mustAddHeadersAndPreserveBodyAndHeaders") { - Message("test1", Map("A" -> "1")).plusHeaders(Map("B" -> "2")) must be( + Message("test1", Map("A" -> "1")).addHeaders(Map("B" -> "2")) must be( Message("test1", Map("A" -> "1", "B" -> "2"))) } diff --git a/akka-camel/src/test/scala/akka/camel/ProducerFeatureTest.scala b/akka-camel/src/test/scala/akka/camel/ProducerFeatureTest.scala index 2fdc076007..983ff8ed0c 100644 --- a/akka-camel/src/test/scala/akka/camel/ProducerFeatureTest.scala +++ b/akka-camel/src/test/scala/akka/camel/ProducerFeatureTest.scala @@ -7,17 +7,17 @@ package akka.camel import org.apache.camel.{ Exchange, Processor } import org.apache.camel.builder.RouteBuilder import org.apache.camel.component.mock.MockEndpoint -import org.scalatest.{ GivenWhenThen, BeforeAndAfterEach, BeforeAndAfterAll, FeatureSpec } import akka.actor._ import akka.pattern._ import akka.dispatch.Await import akka.util.duration._ import akka.camel.TestSupport.SharedCamelSystem +import org.scalatest._ /** * Tests the features of the Camel Producer. */ -class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with BeforeAndAfterEach with SharedCamelSystem with GivenWhenThen { +class ProducerFeatureTest extends WordSpec with BeforeAndAfterAll with BeforeAndAfterEach with SharedCamelSystem with GivenWhenThen { import ProducerFeatureTest._ @@ -31,158 +31,153 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before override protected def afterEach { mockEndpoint.reset() } - feature("Producer on a sync Camel route") { + "A Producer on a sync Camel route" must { - scenario("produces a message and receives normal response") { + "produce a message and receive normal response" in { given("a registered two-way producer") val producer = system.actorOf(Props(new TestProducer("direct:producer-test-2", true))) when("a test message is sent to the producer with ?") - val message = Message("test", Map(Message.MessageExchangeId -> "123")) + val message = CamelMessage("test", Map(CamelMessage.MessageExchangeId -> "123")) val future = producer.ask(message)(timeout) then("a normal response must have been returned by the producer") - val expected = Message("received TEST", Map(Message.MessageExchangeId -> "123")) + val expected = CamelMessage("received TEST", Map(CamelMessage.MessageExchangeId -> "123")) Await.result(future, timeout) match { - case result: Message ⇒ assert(result === expected) - case unexpected ⇒ fail("Actor responded with unexpected message:" + unexpected) + case result: CamelMessage ⇒ assert(result === expected) + case unexpected ⇒ fail("Actor responded with unexpected message:" + unexpected) } } - scenario("produces a message and receives failure response") { + "produce a message and receive failure response" in { given("a registered two-way producer") val producer = system.actorOf(Props(new TestProducer("direct:producer-test-2"))) when("a test message causing an exception is sent to the producer with ?") - val message = Message("fail", Map(Message.MessageExchangeId -> "123")) + val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123")) val future = producer.ask(message)(timeout) Await.result(future, timeout) match { - case result: Failure ⇒ { + case result: Failure ⇒ then("a failure response must have been returned by the producer") val expectedFailureText = result.cause.getMessage val expectedHeaders = result.headers assert(expectedFailureText === "failure") - assert(expectedHeaders === Map(Message.MessageExchangeId -> "123")) - } + assert(expectedHeaders === Map(CamelMessage.MessageExchangeId -> "123")) case unexpected ⇒ fail("Actor responded with unexpected message:" + unexpected) } } - scenario("produces message oneway") { + "produce a message oneway" in { given("a registered one-way producer") val producer = system.actorOf(Props(new TestProducer("direct:producer-test-1", true) with Oneway)) when("a test message is sent to the producer with !") mockEndpoint.expectedBodiesReceived("TEST") - producer ! Message("test", Map()) + producer ! CamelMessage("test", Map()) then("the test message must have been sent to mock:mock") mockEndpoint.assertIsSatisfied() } - scenario("produces message twoway without sender reference") { + "produces message twoway without sender reference" in { given("a registered two-way producer") val producer = system.actorOf(Props(new TestProducer("direct:producer-test-1"))) when("a test message is sent to the producer with !") mockEndpoint.expectedBodiesReceived("test") - producer ! Message("test", Map()) + producer ! CamelMessage("test", Map()) then("there must be only a warning that there's no sender reference") mockEndpoint.assertIsSatisfied() } } - feature("Producer on an async Camel route") { + "A Producer on an async Camel route" must { - scenario("produces message to direct:producer-test-3 and receives normal response") { + "produce message to direct:producer-test-3 and receive normal response" in { given("a registered two-way producer") val producer = system.actorOf(Props(new TestProducer("direct:producer-test-3"))) when("a test message is sent to the producer with ?") - val message = Message("test", Map(Message.MessageExchangeId -> "123")) + val message = CamelMessage("test", Map(CamelMessage.MessageExchangeId -> "123")) val future = producer.ask(message)(timeout) Await.result(future, timeout) match { - case result: Message ⇒ { + case result: CamelMessage ⇒ then("a normal response must have been returned by the producer") - val expected = Message("received test", Map(Message.MessageExchangeId -> "123")) + val expected = CamelMessage("received test", Map(CamelMessage.MessageExchangeId -> "123")) assert(result === expected) - } case unexpected ⇒ fail("Actor responded with unexpected message:" + unexpected) } } - scenario("produces message to direct:producer-test-3 and receives failure response") { + "produce message to direct:producer-test-3 and receive failure response" in { given("a registered two-way producer") val producer = system.actorOf(Props(new TestProducer("direct:producer-test-3"))) when("a test message causing an exception is sent to the producer with ?") - val message = Message("fail", Map(Message.MessageExchangeId -> "123")) + val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123")) val future = producer.ask(message)(timeout) Await.result(future, timeout) match { - case result: Failure ⇒ { + case result: Failure ⇒ then("a failure response must have been returned by the producer") val expectedFailureText = result.cause.getMessage val expectedHeaders = result.headers assert(expectedFailureText === "failure") - assert(expectedHeaders === Map(Message.MessageExchangeId -> "123")) - } + assert(expectedHeaders === Map(CamelMessage.MessageExchangeId -> "123")) case unexpected ⇒ fail("Actor responded with unexpected message:" + unexpected) } } - scenario("produces message, forwards normal response of direct:producer-test-2 to a replying target actor and receives response") { + "produce message, forward normal response of direct:producer-test-2 to a replying target actor and receive response" in { given("a registered two-way producer configured with a forward target") val target = system.actorOf(Props[ReplyingForwardTarget]) val producer = system.actorOf(Props(new TestForwarder("direct:producer-test-2", target))) when("a test message is sent to the producer with ?") - val message = Message("test", Map(Message.MessageExchangeId -> "123")) + val message = CamelMessage("test", Map(CamelMessage.MessageExchangeId -> "123")) val future = producer.ask(message)(timeout) Await.result(future, timeout) match { - case result: Message ⇒ { + case result: CamelMessage ⇒ then("a normal response must have been returned by the forward target") - val expected = Message("received test", Map(Message.MessageExchangeId -> "123", "test" -> "result")) + val expected = CamelMessage("received test", Map(CamelMessage.MessageExchangeId -> "123", "test" -> "result")) assert(result === expected) - } case unexpected ⇒ fail("Actor responded with unexpected message:" + unexpected) } } - scenario("produces message, forwards failure response of direct:producer-test-2 to a replying target actor and receives response") { + "produce message, forward failure response of direct:producer-test-2 to a replying target actor and receive response" in { given("a registered two-way producer configured with a forward target") val target = system.actorOf(Props[ReplyingForwardTarget]) val producer = system.actorOf(Props(new TestForwarder("direct:producer-test-2", target))) when("a test message causing an exception is sent to the producer with ?") - val message = Message("fail", Map(Message.MessageExchangeId -> "123")) + val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123")) val future = producer.ask(message)(timeout) Await.result(future, timeout) match { - case failure: Failure ⇒ { + case failure: Failure ⇒ then("a failure response must have been returned by the forward target") val expectedFailureText = failure.cause.getMessage val expectedHeaders = failure.headers assert(expectedFailureText === "failure") - assert(expectedHeaders === Map(Message.MessageExchangeId -> "123", "test" -> "failure")) - } + assert(expectedHeaders === Map(CamelMessage.MessageExchangeId -> "123", "test" -> "failure")) case unexpected ⇒ fail("Actor responded with unexpected message:" + unexpected) } } - scenario("produces message, forwards normal response to a producing target actor and produces response to direct:forward-test-1") { + "produce message, forward normal response to a producing target actor and produce response to direct:forward-test-1" in { given("a registered one-way producer configured with a forward target") val target = system.actorOf(Props[ProducingForwardTarget]) val producer = system.actorOf(Props(new TestForwarder("direct:producer-test-2", target))) when("a test message is sent to the producer with !") mockEndpoint.expectedBodiesReceived("received test") - producer.tell(Message("test", Map()), producer) + producer.tell(CamelMessage("test", Map()), producer) then("a normal response must have been produced by the forward target") mockEndpoint.assertIsSatisfied() } - scenario("produces message, forwards failure response to a producing target actor and produces response to direct:forward-test-1") { + "produce message, forward failure response to a producing target actor and produce response to direct:forward-test-1" in { given("a registered one-way producer configured with a forward target") val target = system.actorOf(Props[ProducingForwardTarget]) @@ -191,66 +186,64 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before when("a test message causing an exception is sent to the producer with !") mockEndpoint.expectedMessageCount(1) mockEndpoint.message(0).body().isInstanceOf(classOf[Failure]) - producer.tell(Message("fail", Map()), producer) + producer.tell(CamelMessage("fail", Map()), producer) then("a failure response must have been produced by the forward target") mockEndpoint.assertIsSatisfied() } - scenario("produces message, forwards normal response from direct:producer-test-3 to a replying target actor and receives response") { + "produce message, forward normal response from direct:producer-test-3 to a replying target actor and receive response" in { given("a registered two-way producer configured with a forward target") val target = system.actorOf(Props[ReplyingForwardTarget]) val producer = system.actorOf(Props(new TestForwarder("direct:producer-test-3", target))) when("a test message is sent to the producer with ?") - val message = Message("test", Map(Message.MessageExchangeId -> "123")) + val message = CamelMessage("test", Map(CamelMessage.MessageExchangeId -> "123")) val future = producer.ask(message)(timeout) then("a normal response must have been returned by the forward target") Await.result(future, timeout) match { - case message: Message ⇒ { - val expected = Message("received test", Map(Message.MessageExchangeId -> "123", "test" -> "result")) + case message: CamelMessage ⇒ + val expected = CamelMessage("received test", Map(CamelMessage.MessageExchangeId -> "123", "test" -> "result")) assert(message === expected) - } case unexpected ⇒ fail("Actor responded with unexpected message:" + unexpected) } } - scenario("produces message, forwards failure response from direct:producer-test-3 to a replying target actor and receives response") { + "produce message, forward failure response from direct:producer-test-3 to a replying target actor and receive response" in { given("a registered two-way producer configured with a forward target") val target = system.actorOf(Props[ReplyingForwardTarget]) val producer = system.actorOf(Props(new TestForwarder("direct:producer-test-3", target))) when("a test message causing an exception is sent to the producer with !!") - val message = Message("fail", Map(Message.MessageExchangeId -> "123")) + val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123")) val future = producer.ask(message)(timeout) Await.result(future, timeout) match { - case failure: Failure ⇒ { + case failure: Failure ⇒ then("a failure response must have been returned by the forward target") val expectedFailureText = failure.cause.getMessage val expectedHeaders = failure.headers assert(expectedFailureText === "failure") - assert(expectedHeaders === Map(Message.MessageExchangeId -> "123", "test" -> "failure")) - } + assert(expectedHeaders === Map(CamelMessage.MessageExchangeId -> "123", "test" -> "failure")) case unexpected ⇒ fail("Actor responded with unexpected message:" + unexpected) } } - scenario("produces message, forwards normal response from direct:producer-test-3 to a producing target actor and produces response to direct:forward-test-1") { + "produce message, forward normal response from direct:producer-test-3 to a producing target actor and produce response to direct:forward-test-1" in { given("a registered one-way producer configured with a forward target") val target = system.actorOf(Props[ProducingForwardTarget]) val producer = system.actorOf(Props(new TestForwarder("direct:producer-test-3", target))) when("a test message is sent to the producer with !") mockEndpoint.expectedBodiesReceived("received test") - producer.tell(Message("test", Map()), producer) + producer.tell(CamelMessage("test", Map()), producer) then("a normal response must have been produced by the forward target") mockEndpoint.assertIsSatisfied() } - scenario("produces message, forwards failure response from direct:producer-test-3 to a producing target actor and produces response to direct:forward-test-1") { + "produce message, forward failure response from direct:producer-test-3 to a producing target actor and produce response to direct:forward-test-1" in { given("a registered one-way producer configured with a forward target") val target = system.actorOf(Props[ProducingForwardTarget]) val producer = system.actorOf(Props(new TestForwarder("direct:producer-test-3", target))) @@ -258,7 +251,7 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before when("a test message causing an exception is sent to the producer with !") mockEndpoint.expectedMessageCount(1) mockEndpoint.message(0).body().isInstanceOf(classOf[Failure]) - producer.tell(Message("fail", Map()), producer) + producer.tell(CamelMessage("fail", Map()), producer) then("a failure response must have been produced by the forward target") mockEndpoint.assertIsSatisfied() @@ -274,7 +267,7 @@ object ProducerFeatureTest { def endpointUri = uri override protected def receiveBeforeProduce = { - case msg: Message ⇒ if (upper) msg.mapBody { + case msg: CamelMessage ⇒ if (upper) msg.mapBody { body: String ⇒ body.toUpperCase } else msg @@ -291,23 +284,20 @@ object ProducerFeatureTest { class TestResponder extends Actor { protected def receive = { - case msg: Message ⇒ msg.body match { - case "fail" ⇒ { - context.sender ! (Failure(new Exception("failure"), msg.headers)) - } - case bod: Any ⇒ { + case msg: CamelMessage ⇒ msg.body match { + case "fail" ⇒ context.sender ! (Failure(new Exception("failure"), msg.headers)) + case _ ⇒ context.sender ! (msg.mapBody { body: String ⇒ "received %s" format body }) - } } } } class ReplyingForwardTarget extends Actor { protected def receive = { - case msg: Message ⇒ - context.sender ! (msg.plusHeader("test" -> "result")) + case msg: CamelMessage ⇒ + context.sender ! (msg.addHeader("test" -> "result")) case msg: Failure ⇒ context.sender ! (Failure(msg.cause, msg.headers + ("test" -> "failure"))) } diff --git a/akka-camel/src/test/scala/akka/camel/TestSupport.scala b/akka-camel/src/test/scala/akka/camel/TestSupport.scala index 14262c889e..fee20267b1 100644 --- a/akka-camel/src/test/scala/akka/camel/TestSupport.scala +++ b/akka-camel/src/test/scala/akka/camel/TestSupport.scala @@ -41,8 +41,8 @@ private[camel] object TestSupport { @deprecated trait MessageSugar { - def Message(body: Any) = akka.camel.Message(body, Map.empty) - def Message(body: Any, headers: Map[String, Any]) = akka.camel.Message(body, headers) + def Message(body: Any) = akka.camel.CamelMessage(body, Map.empty) + def Message(body: Any, headers: Map[String, Any]) = akka.camel.CamelMessage(body, headers) } trait SharedCamelSystem extends BeforeAndAfterAll { this: Suite ⇒ diff --git a/akka-camel/src/test/scala/akka/camel/UntypedProducerTest.scala b/akka-camel/src/test/scala/akka/camel/UntypedProducerTest.scala index 24a2a1da87..460ac166cf 100644 --- a/akka-camel/src/test/scala/akka/camel/UntypedProducerTest.scala +++ b/akka-camel/src/test/scala/akka/camel/UntypedProducerTest.scala @@ -33,13 +33,13 @@ class UntypedProducerTest extends WordSpec with BeforeAndAfterAll with BeforeAnd val producer = system.actorOf(Props[SampleUntypedReplyingProducer]) when("a test message is sent to the producer with !!") - val message = Message("test", Map(Message.MessageExchangeId -> "123")) + val message = CamelMessage("test", Map(CamelMessage.MessageExchangeId -> "123")) val future = producer.ask(message)(timeout) then("a normal response should have been returned by the producer") - val expected = Message("received test", Map(Message.MessageExchangeId -> "123")) + val expected = CamelMessage("received test", Map(CamelMessage.MessageExchangeId -> "123")) Await.result(future, timeout) match { - case result: Message ⇒ assert(result === expected) - case unexpected ⇒ fail("Actor responded with unexpected message:" + unexpected) + case result: CamelMessage ⇒ assert(result === expected) + case unexpected ⇒ fail("Actor responded with unexpected message:" + unexpected) } } @@ -49,7 +49,7 @@ class UntypedProducerTest extends WordSpec with BeforeAndAfterAll with BeforeAnd val producer = system.actorOf(Props[SampleUntypedReplyingProducer]) when("a test message causing an exception is sent to the producer with !!") - val message = Message("fail", Map(Message.MessageExchangeId -> "123")) + val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123")) val future = producer.ask(message)(timeout) then("a failure response should have been returned by the producer") Await.result(future, timeout) match { @@ -57,7 +57,7 @@ class UntypedProducerTest extends WordSpec with BeforeAndAfterAll with BeforeAnd val expectedFailureText = result.cause.getMessage val expectedHeaders = result.headers assert(expectedFailureText === "failure") - assert(expectedHeaders === Map(Message.MessageExchangeId -> "123")) + assert(expectedHeaders === Map(CamelMessage.MessageExchangeId -> "123")) } case unexpected ⇒ fail("Actor responded with unexpected message:" + unexpected) } @@ -73,7 +73,7 @@ class UntypedProducerTest extends WordSpec with BeforeAndAfterAll with BeforeAnd when("a test message is sent to the producer with !") mockEndpoint.expectedBodiesReceived("received test") - val result = producer.tell(Message("test", Map[String, Any]()), producer) + val result = producer.tell(CamelMessage("test", Map[String, Any]()), producer) then("a normal response should have been sent") mockEndpoint.assertIsSatisfied diff --git a/akka-camel/src/test/scala/akka/camel/internal/TryTest.scala b/akka-camel/src/test/scala/akka/camel/internal/TryTest.scala deleted file mode 100644 index 2af0ccf11d..0000000000 --- a/akka-camel/src/test/scala/akka/camel/internal/TryTest.scala +++ /dev/null @@ -1,63 +0,0 @@ -package akka.camel.internal - -/** - * Copyright (C) 2009-2012 Typesafe Inc. - */ - -import akka.camel.internal.Try._ -import org.scalatest.matchers.MustMatchers -import org.scalatest.mock.MockitoSugar -import akka.event.LoggingAdapter -import org.scalatest.{ BeforeAndAfterEach, WordSpec } - -class TryTest extends WordSpec with MustMatchers with MockitoSugar with BeforeAndAfterEach { - - import org.mockito.Mockito._ - import org.mockito.Matchers._ - import org.mockito.Matchers.{ eq ⇒ the } - - implicit var log: LoggingAdapter = _ - - override def beforeEach() { - log = mock[LoggingAdapter] - } - - "Safe executes block" in { - var executed = false - safe { - executed = true - } - executed must be(true) - verifyNoMoreInteractions(log) - } - - "Safe swallows exception and logs it" in { - safe(throw new Exception) - verify(log).warning(any[String], any[Any]) - } - - "Try-otherwise runs otherwise and throws exception when the first block fails" in { - var otherwiseCalled = false - intercept[Exception] { - Try(throw new Exception) otherwise (otherwiseCalled = true) - } - otherwiseCalled must be(true) - verifyNoMoreInteractions(log) - } - - "Try-otherwise swallows exception thrown in otherwise clause and logs it" in { - val exceptionFromOtherwise = new RuntimeException("e2") - intercept[RuntimeException] { - Try(throw new RuntimeException("e1")) otherwise (throw exceptionFromOtherwise) - }.getMessage must be("e1") - verify(log, only()).warning(any[String], the(exceptionFromOtherwise)) - } - - "Try-otherwise doesnt run otherwise if first block doesnt fail" in { - var otherwiseCalled = false - Try(2 + 2) otherwise (otherwiseCalled = true) - otherwiseCalled must be(false) - verifyNoMoreInteractions(log) - } - -} diff --git a/akka-camel/src/test/scala/akka/camel/internal/component/ActorProducerTest.scala b/akka-camel/src/test/scala/akka/camel/internal/component/ActorProducerTest.scala index 35e8fadc5f..6199aaa7c6 100644 --- a/akka-camel/src/test/scala/akka/camel/internal/component/ActorProducerTest.scala +++ b/akka-camel/src/test/scala/akka/camel/internal/component/ActorProducerTest.scala @@ -31,7 +31,7 @@ class ActorProducerTest extends TestKit(ActorSystem("test")) with WordSpec with "consumer actor doesnt exist" must { "set failure message on exchange" in { producer = given(actor = null) - producer.process(exchange) + producer.processExchangeAdapter(exchange) verify(exchange).setFailure(any[Failure]) } @@ -41,12 +41,12 @@ class ActorProducerTest extends TestKit(ActorSystem("test")) with WordSpec with def producer = given(outCapable = false) "pass the message to the consumer" in { - producer.process(exchange) + producer.processExchangeAdapter(exchange) within(1 second)(probe.expectMsg(message)) } "not expect response and not block" in { - time(producer.process(exchange)) must be < (30 millis) + time(producer.processExchangeAdapter(exchange)) must be < (30 millis) } } @@ -57,7 +57,7 @@ class ActorProducerTest extends TestKit(ActorSystem("test")) with WordSpec with "get a response" in { producer = given(actor = echoActor, outCapable = true) - producer.process(exchange) + producer.processExchangeAdapter(exchange) verify(exchange).setResponse(msg("received " + message)) } @@ -67,17 +67,17 @@ class ActorProducerTest extends TestKit(ActorSystem("test")) with WordSpec with def process() = { producer = given(outCapable = true, replyTimeout = 100 millis) - time(producer.process(exchange)) + time(producer.processExchangeAdapter(exchange)) } "timeout after replyTimeout" in { val duration = process() - duration must (be >= (100 millis) and be < (200 millis)) + duration must (be >= (100 millis) and be < (300 millis)) } "never set the response on exchange" in { process() - verify(exchange, Mockito.never()).setResponse(any[Message]) + verify(exchange, Mockito.never()).setResponse(any[CamelMessage]) } "set failure message to timeout" in { @@ -95,7 +95,7 @@ class ActorProducerTest extends TestKit(ActorSystem("test")) with WordSpec with "asynchronous" when { def verifyFailureIsSet { - producer.process(exchange, asyncCallback) + producer.processExchangeAdapter(exchange, asyncCallback) asyncCallback.awaitCalled() verify(exchange).setFailure(any[Failure]) } @@ -113,12 +113,12 @@ class ActorProducerTest extends TestKit(ActorSystem("test")) with WordSpec with "get a response and async callback as soon as it gets the response (but not before)" in { producer = given(outCapable = true) - val doneSync = producer.process(exchange, asyncCallback) + val doneSync = producer.processExchangeAdapter(exchange, asyncCallback) asyncCallback.expectNoCallWithin(100 millis); info("no async callback before response") within(1 second) { - probe.expectMsgType[Message] + probe.expectMsgType[CamelMessage] probe.sender ! "some message" } doneSync must be(false); info("done async") @@ -134,10 +134,10 @@ class ActorProducerTest extends TestKit(ActorSystem("test")) with WordSpec with producer = given(outCapable = true) - producer.process(exchange, asyncCallback) + producer.processExchangeAdapter(exchange, asyncCallback) within(1 second) { - probe.expectMsgType[Message] + probe.expectMsgType[CamelMessage] probe.sender ! failure asyncCallback.awaitCalled(remaining) } @@ -149,7 +149,7 @@ class ActorProducerTest extends TestKit(ActorSystem("test")) with WordSpec with "no response is sent within timeout" must { "set TimeoutException on exchange" in { producer = given(outCapable = true, replyTimeout = 10 millis) - producer.process(exchange, asyncCallback) + producer.processExchangeAdapter(exchange, asyncCallback) asyncCallback.awaitCalled(100 millis) verify(exchange).setFailure(Matchers.argThat(new ArgumentMatcher[Failure] { def matches(failure: AnyRef) = { failure.asInstanceOf[Failure].getCause must be(anInstanceOf[TimeoutException]); true } @@ -174,11 +174,11 @@ class ActorProducerTest extends TestKit(ActorSystem("test")) with WordSpec with "get sync callback as soon as it sends a message" in { producer = given(outCapable = false, autoAck = true) - val doneSync = producer.process(exchange, asyncCallback) + val doneSync = producer.processExchangeAdapter(exchange, asyncCallback) doneSync must be(true); info("done sync") asyncCallback.expectDoneSyncWithin(1 second); info("async callback called") - verify(exchange, never()).setResponse(any[Message]); info("no response forwarded to exchange") + verify(exchange, never()).setResponse(any[CamelMessage]); info("no response forwarded to exchange") } } @@ -189,15 +189,15 @@ class ActorProducerTest extends TestKit(ActorSystem("test")) with WordSpec with "get async callback" in { producer = given(outCapable = false, autoAck = false) - val doneSync = producer.process(exchange, asyncCallback) + val doneSync = producer.processExchangeAdapter(exchange, asyncCallback) doneSync must be(false) within(1 second) { - probe.expectMsgType[Message]; info("message sent to consumer") + probe.expectMsgType[CamelMessage]; info("message sent to consumer") probe.sender ! Ack asyncCallback.expectDoneAsyncWithin(remaining); info("async callback called") } - verify(exchange, never()).setResponse(any[Message]); info("no response forwarded to exchange") + verify(exchange, never()).setResponse(any[CamelMessage]); info("no response forwarded to exchange") } } @@ -205,14 +205,14 @@ class ActorProducerTest extends TestKit(ActorSystem("test")) with WordSpec with "fail" in { producer = given(outCapable = false, autoAck = false) - producer.process(exchange, asyncCallback) + producer.processExchangeAdapter(exchange, asyncCallback) within(1 second) { - probe.expectMsgType[Message]; info("message sent to consumer") + probe.expectMsgType[CamelMessage]; info("message sent to consumer") probe.sender ! "some neither Ack nor Failure response" asyncCallback.expectDoneAsyncWithin(remaining); info("async callback called") } - verify(exchange, never()).setResponse(any[Message]); info("no response forwarded to exchange") + verify(exchange, never()).setResponse(any[CamelMessage]); info("no response forwarded to exchange") verify(exchange).setFailure(any[Failure]); info("failure set") } @@ -222,7 +222,7 @@ class ActorProducerTest extends TestKit(ActorSystem("test")) with WordSpec with "set failure on exchange" in { producer = given(outCapable = false, replyTimeout = 10 millis, autoAck = false) - producer.process(exchange, asyncCallback) + producer.processExchangeAdapter(exchange, asyncCallback) asyncCallback.awaitCalled(100 millis) verify(exchange).setFailure(any[Failure]) @@ -233,27 +233,22 @@ class ActorProducerTest extends TestKit(ActorSystem("test")) with WordSpec with "set an exception on exchange" in { producer = given(outCapable = false, autoAck = false) - val doneSync = producer.process(exchange, asyncCallback) + val doneSync = producer.processExchangeAdapter(exchange, asyncCallback) doneSync must be(false) within(1 second) { - probe.expectMsgType[Message]; info("message sent to consumer") + probe.expectMsgType[CamelMessage]; info("message sent to consumer") probe.sender ! Failure(new Exception) asyncCallback.awaitCalled(remaining); } - verify(exchange, never()).setResponse(any[Message]); info("no response forwarded to exchange") + verify(exchange, never()).setResponse(any[CamelMessage]); info("no response forwarded to exchange") verify(exchange).setFailure(any[Failure]); info("failure set") } - } - } - } - } } - } trait ActorProducerFixture extends MockitoSugar with BeforeAndAfterAll with BeforeAndAfterEach { self: TestKit with MustMatchers with Suite ⇒ @@ -261,11 +256,12 @@ trait ActorProducerFixture extends MockitoSugar with BeforeAndAfterAll with Befo var exchange: CamelExchangeAdapter = _ var callback: AsyncCallback = _ - var producer: ConsumerAsyncProcessor = _ - var message: Message = _ + var producer: ActorProducer = _ + var message: CamelMessage = _ var probe: TestProbe = _ var asyncCallback: TestAsyncCallback = _ var actorEndpointPath: ActorEndpointPath = _ + var actorComponent: ActorComponent = _ override protected def beforeEach() { asyncCallback = createAsyncCallback @@ -275,20 +271,20 @@ trait ActorProducerFixture extends MockitoSugar with BeforeAndAfterAll with Befo exchange = mock[CamelExchangeAdapter] callback = mock[AsyncCallback] actorEndpointPath = mock[ActorEndpointPath] - - producer = new ConsumerAsyncProcessor(config(), camel) - message = Message(null, null) + actorComponent = mock[ActorComponent] + producer = new ActorProducer(config(), camel) + message = CamelMessage(null, null) } override protected def afterAll() { system.shutdown() } - def msg(s: String) = Message(s, Map.empty) + def msg(s: String) = CamelMessage(s, Map.empty) def given(actor: ActorRef = probe.ref, outCapable: Boolean = true, autoAck: Boolean = true, replyTimeout: Duration = Int.MaxValue seconds) = { prepareMocks(actor, outCapable = outCapable) - new ConsumerAsyncProcessor(config(isAutoAck = autoAck, _replyTimeout = replyTimeout), camel) + new ActorProducer(config(isAutoAck = autoAck, _replyTimeout = replyTimeout), camel) } def createAsyncCallback = new TestAsyncCallback @@ -323,15 +319,13 @@ trait ActorProducerFixture extends MockitoSugar with BeforeAndAfterAll with Befo } def config(endpointUri: String = "test-uri", isAutoAck: Boolean = true, _replyTimeout: Duration = Int.MaxValue seconds) = { - new ActorEndpointConfig { - val path = actorEndpointPath - val getEndpointUri = endpointUri - autoack = isAutoAck - replyTimeout = _replyTimeout - } + val endpoint = new ActorEndpoint(endpointUri, actorComponent, actorEndpointPath, camel) + endpoint.autoack = isAutoAck + endpoint.replyTimeout = _replyTimeout + endpoint } - def prepareMocks(actor: ActorRef, message: Message = message, outCapable: Boolean) { + def prepareMocks(actor: ActorRef, message: CamelMessage = message, outCapable: Boolean) { when(actorEndpointPath.findActorIn(any[ActorSystem])) thenReturn Option(actor) when(exchange.toRequestMessage(any[Map[String, Any]])) thenReturn message when(exchange.isOutCapable) thenReturn outCapable