diff --git a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala index 7a250fbe1a..641c43d01c 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala @@ -870,7 +870,6 @@ private[akka] class ActorSystemImpl( "akka-actor-testkit-typed", "akka-actor-typed", "akka-agent", - "akka-camel", "akka-cluster", "akka-cluster-metrics", "akka-cluster-sharding", diff --git a/akka-camel/src/main/resources/reference.conf b/akka-camel/src/main/resources/reference.conf deleted file mode 100644 index 13dabc2ab8..0000000000 --- a/akka-camel/src/main/resources/reference.conf +++ /dev/null @@ -1,50 +0,0 @@ -#################################### -# Akka Camel Reference Config File # -#################################### - -# This is the reference config file that contains all the default settings. -# Make your edits/overrides in your application.conf. - -akka { - camel { - # FQCN of the ContextProvider to be used to create or locate a CamelContext - # it must implement akka.camel.ContextProvider and have a no-arg constructor - # the built-in default create a fresh DefaultCamelContext - context-provider = akka.camel.DefaultContextProvider - - # Whether JMX should be enabled or disabled for the Camel Context - jmx = off - # enable/disable streaming cache on the Camel Context - streamingCache = on - consumer { - # Configured setting which determines whether one-way communications - # between an endpoint and this consumer actor - # should be auto-acknowledged or application-acknowledged. - # This flag has only effect when exchange is in-only. - auto-ack = on - - # When endpoint is out-capable (can produce responses) reply-timeout is the - # maximum time the endpoint can take to send the response before the message - # exchange fails. This setting is used for out-capable, in-only, - # manually acknowledged communication. - reply-timeout = 1m - - # The duration of time to await activation of an endpoint. - activation-timeout = 10s - } - - producer { - # The id of the dispatcher to use for producer child actors, i.e. the actor that - # interacts with the Camel endpoint. Some endpoints may be blocking and then it - # can be good to define a dedicated dispatcher. - # If not defined the producer child actor is using the same dispatcher as the - # parent producer actor. - use-dispatcher = "" - } - - #Scheme to FQCN mappings for CamelMessage body conversions - conversions { - "file" = "java.io.InputStream" - } - } -} diff --git a/akka-camel/src/main/scala/akka/camel/Activation.scala b/akka-camel/src/main/scala/akka/camel/Activation.scala deleted file mode 100644 index 6d54e6b1f5..0000000000 --- a/akka-camel/src/main/scala/akka/camel/Activation.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import akka.util.Timeout -import akka.actor.{ ActorRef } -import scala.concurrent.{ ExecutionContext, Future } - -/** - * 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 { - - /** - * Produces a Future with the specified endpoint that will be completed when the endpoint has been activated, - * or if it times out, which will happen after the specified Timeout. - * - * @param endpoint the endpoint to be activated - * @param timeout the timeout for the Future - */ - def activationFutureFor(endpoint: ActorRef)(implicit timeout: Timeout, executor: ExecutionContext): Future[ActorRef] - - /** - * Produces a Future which will be completed when the given endpoint has been deactivated or - * or if it times out, which will happen after the specified Timeout. - * - * @param endpoint the endpoint to be deactivated - * @param timeout the timeout of the Future - */ - def deactivationFutureFor(endpoint: ActorRef)(implicit timeout: Timeout, executor: ExecutionContext): Future[ActorRef] -} diff --git a/akka-camel/src/main/scala/akka/camel/ActorNotRegisteredException.scala b/akka-camel/src/main/scala/akka/camel/ActorNotRegisteredException.scala deleted file mode 100644 index 4a930c1403..0000000000 --- a/akka-camel/src/main/scala/akka/camel/ActorNotRegisteredException.scala +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -/** - * Thrown to indicate that the actor referenced by an endpoint URI cannot be - * found in the actor system. - * - */ -class ActorNotRegisteredException(uri: String) extends RuntimeException { - override def getMessage: String = "Actor [%s] doesn't exist".format(uri) -} diff --git a/akka-camel/src/main/scala/akka/camel/ActorRouteDefinition.scala b/akka-camel/src/main/scala/akka/camel/ActorRouteDefinition.scala deleted file mode 100644 index 2ff096bc0b..0000000000 --- a/akka-camel/src/main/scala/akka/camel/ActorRouteDefinition.scala +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import akka.actor.ActorRef -import akka.camel.internal.component.CamelPath -import org.apache.camel.model.ProcessorDefinition -import scala.concurrent.duration.Duration - -/** - * Wraps a [[org.apache.camel.model.ProcessorDefinition]]. - * There is an implicit conversion in the `akka.camel` package object that converts a `ProcessorDefinition` into `this` type. - * Because of this conversion, it is possible to use an [[akka.actor.ActorRef]] as a `to` parameter in building a route: - * {{{ - * class TestRoute(system: ActorSystem) extends RouteBuilder { - * val responder = system.actorOf(Props[TestResponder], name = "TestResponder") - * - * def configure { - * from("direct:producer").to(responder) - * } - * } - * }}} - * @param definition the processor definition - */ -class ActorRouteDefinition[T <: ProcessorDefinition[T]](definition: ProcessorDefinition[T]) { - - /** - * Sends the message to an ActorRef endpoint. - * @param actorRef the actorRef to the actor. - * @return the path to the actor, as a camel uri String - */ - def to(actorRef: ActorRef): T = definition.to(CamelPath.toUri(actorRef)) - - /** - * Sends the message to an ActorRef endpoint - * @param actorRef the consumer - * @param autoAck Determines whether one-way communications between an endpoint and this consumer actor - * should be auto-acknowledged or application-acknowledged. - * This flag has only effect when exchange is in-only. - * @param replyTimeout When endpoint is out-capable (can produce responses) replyTimeout is the maximum time - * the endpoint can take to send the response before the message exchange fails. It defaults to 1 minute. - * This setting is used for out-capable, in-only, manually acknowledged communication. - * @return the path to the actor, as a camel uri String - */ - def to(actorRef: ActorRef, autoAck: Boolean, replyTimeout: Duration): T = - definition.to(CamelPath.toUri(actorRef, autoAck, replyTimeout)) -} diff --git a/akka-camel/src/main/scala/akka/camel/Camel.scala b/akka-camel/src/main/scala/akka/camel/Camel.scala deleted file mode 100644 index c9aeaf0ca4..0000000000 --- a/akka-camel/src/main/scala/akka/camel/Camel.scala +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import akka.camel.internal._ -import akka.actor._ -import akka.ConfigurationException -import org.apache.camel.ProducerTemplate -import org.apache.camel.impl.DefaultCamelContext -import org.apache.camel.model.RouteDefinition -import com.typesafe.config.Config -import scala.concurrent.duration.FiniteDuration -import scala.collection.immutable - -/** - * Camel trait encapsulates the underlying camel machinery. - * '''Note:''' `CamelContext` and `ProducerTemplate` are stopped when the associated actor system is shut down. - * This trait can be obtained through the [[akka.camel.CamelExtension]] object. - */ -trait Camel extends Extension with Activation { - - /** - * Underlying camel context. - * - * It can be used to configure camel manually, i.e. when the user wants to add new routes or endpoints, - * i.e. {{{camel.context.addRoutes(...)}}} - * - * @see [[org.apache.camel.impl.DefaultCamelContext]] - */ - def context: DefaultCamelContext - - /** - * The Camel ProducerTemplate. - * @see [[org.apache.camel.ProducerTemplate]] - */ - def template: ProducerTemplate - - /** - * The settings for the CamelExtension - */ - def settings: CamelSettings - - /** - * INTERNAL API - * Returns the camel supervisor actor. - */ - private[camel] def supervisor: ActorRef - - /** - * INTERNAL API - * Returns the associated ActorSystem. - */ - private[camel] def system: ActorSystem -} - -/** - * Settings for the Camel Extension - * @param config the config - */ -class CamelSettings private[camel] (config: Config, dynamicAccess: DynamicAccess) { - import akka.util.Helpers.ConfigOps - - /** - * Configured setting for how long the actor should wait for activation before it fails. - */ - final val ActivationTimeout: FiniteDuration = config.getMillisDuration("akka.camel.consumer.activation-timeout") - - /** - * Configured setting, when endpoint is out-capable (can produce responses) replyTimeout is the maximum time - * the endpoint can take to send the response before the message exchange fails. - * This setting is used for out-capable, in-only, manually acknowledged communication. - */ - final val ReplyTimeout: FiniteDuration = config.getMillisDuration("akka.camel.consumer.reply-timeout") - - /** - * Configured setting which determines whether one-way communications between an endpoint and this consumer actor - * should be auto-acknowledged or application-acknowledged. - * This flag has only effect when exchange is in-only. - */ - final val AutoAck: Boolean = config.getBoolean("akka.camel.consumer.auto-ack") - - final val JmxStatistics: Boolean = config.getBoolean("akka.camel.jmx") - - /** - * enables or disables streamingCache on the Camel Context - */ - final val StreamingCache: Boolean = config.getBoolean("akka.camel.streamingCache") - - final val ProducerChildDispatcher: String = config.getString("akka.camel.producer.use-dispatcher") - - final val Conversions: (String, RouteDefinition) => RouteDefinition = { - val specifiedConversions = { - import scala.collection.JavaConverters.asScalaSetConverter - val section = config.getConfig("akka.camel.conversions") - section.entrySet.asScala.map(e => (e.getKey, section.getString(e.getKey))) - } - val conversions = specifiedConversions.foldLeft(Map[String, Class[_ <: AnyRef]]()) { - case (m, (key, fqcn)) => - m.updated( - key, - dynamicAccess - .getClassFor[AnyRef](fqcn) - .recover { - case e => - throw new ConfigurationException("Could not find/load Camel Converter class [" + fqcn + "]", e) - } - .get) - } - - (s: String, r: RouteDefinition) => conversions.get(s).fold(r)(r.convertBodyTo) - } - - /** - * Configured setting, determine the class used to load/retrieve the instance of the Camel Context - */ - final val ContextProvider: ContextProvider = { - val fqcn = config.getString("akka.camel.context-provider") - dynamicAccess - .createInstanceFor[ContextProvider](fqcn, immutable.Seq.empty) - .recover { - case e => throw new ConfigurationException("Could not find/load Context Provider class [" + fqcn + "]", e) - } - .get - } -} - -/** - * This class can be used to get hold of an instance of the Camel class bound to the actor system. - *

For example: - * {{{ - * val system = ActorSystem("some system") - * val camel = CamelExtension(system) - * camel.context.addRoutes(...) - * }}} - * - * @see akka.actor.ExtensionId - * @see akka.actor.ExtensionIdProvider - */ -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. - */ - override def createExtension(system: ExtendedActorSystem): Camel = { - val camel = new DefaultCamel(system).start() - system.registerOnTermination(camel.shutdown()) - camel - } - - override def lookup(): ExtensionId[Camel] = CamelExtension - - override def get(system: ActorSystem): Camel = super.get(system) -} diff --git a/akka-camel/src/main/scala/akka/camel/CamelMessage.scala b/akka-camel/src/main/scala/akka/camel/CamelMessage.scala deleted file mode 100644 index 03daff459d..0000000000 --- a/akka-camel/src/main/scala/akka/camel/CamelMessage.scala +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import java.util.{ Map => JMap, Set => JSet } -import javax.activation.DataHandler -import org.apache.camel.{ CamelContext, Message => JCamelMessage, StreamCache } -import akka.AkkaException -import scala.reflect.ClassTag -import scala.runtime.ScalaRunTime -import scala.util.Try -import akka.dispatch.Mapper -import scala.collection.JavaConverters._ - -/** - * An immutable representation of a Camel message. - */ -@deprecated( - "Akka Camel is deprecated in favour of 'Alpakka', the Akka Streams based collection of integrations to various endpoints (including Camel).", - since = "2.5.0") -class CamelMessage(val body: Any, val headers: Map[String, Any], val attachments: Map[String, DataHandler]) - extends Serializable - with Product { - def this(body: Any, headers: JMap[String, Any]) = - this(body, headers.asScala.toMap, Map.empty[String, DataHandler]) //Java - def this(body: Any, headers: JMap[String, Any], attachments: JMap[String, DataHandler]) = - this(body, headers.asScala.toMap, attachments.asScala.toMap) //Java - def this(body: Any, headers: Map[String, Any]) = this(body, headers.toMap, Map.empty[String, DataHandler]) - - def copy(body: Any = this.body, headers: Map[String, Any] = this.headers): CamelMessage = - CamelMessage(body, headers, this.attachments) - - override def toString: String = "CamelMessage(%s, %s, %s)".format(body, headers, attachments) - - /** - * Returns those headers from this message whose name is contained in names. - */ - def headers(names: Set[String]): Map[String, Any] = headers.filterKeys(names).toMap - - /** - * Java API: Returns those headers from this message whose name is contained in names. - * The returned headers map is backed up by an immutable headers map. Any attempt to modify - * the returned map will throw an exception. - */ - def getHeaders(names: JSet[String]): JMap[String, Any] = headers(names.asScala.toSet).asJava - - /** - * Java API: Returns all headers from this message. The returned headers map is backed up by this - * message's immutable headers map. Any attempt to modify the returned map will throw an - * exception. - */ - def getHeaders: JMap[String, Any] = headers.asJava - - /** - * Java API: Creates a new CamelMessage with given headers. A copy of the headers map is made. - */ - def withHeaders[A](headers: JMap[String, A]): CamelMessage = copy(this.body, headers.asScala.toMap) - - /** - * Returns the header by given name parameter in a [[scala.util.Try]]. The header is converted to type T, which is returned - * in a [[scala.util.Success]]. If an exception occurs during the conversion to the type T or when the header cannot be found, - * the exception is returned in a [[scala.util.Failure]]. - * - * The CamelContext is accessible in a [[akka.camel.javaapi.UntypedConsumerActor]] and [[akka.camel.javaapi.UntypedProducerActor]] - * using the `getCamelContext` method, and is available on the [[akka.camel.CamelExtension]]. - * - */ - def headerAs[T](name: String)(implicit t: ClassTag[T], camelContext: CamelContext): Try[T] = - Try( - headers - .get(name) - .map(camelContext.getTypeConverter.mandatoryConvertTo[T](t.runtimeClass.asInstanceOf[Class[T]], _)) - .getOrElse(throw new NoSuchElementException(name))) - - /** - * Java API: Returns the header by given name parameter. The header is converted to type T as defined by the clazz parameter. - * An exception is thrown when the conversion to the type T fails or when the header cannot be found. - * - * The CamelContext is accessible in a [[akka.camel.javaapi.UntypedConsumerActor]] and [[akka.camel.javaapi.UntypedProducerActor]] - * using the `getCamelContext` method, and is available on the [[akka.camel.CamelExtension]]. - */ - def getHeaderAs[T](name: String, clazz: Class[T], camelContext: CamelContext): T = - headerAs[T](name)(ClassTag(clazz), camelContext).get - - /** - * Returns a new CamelMessage with a transformed body using a transformer function. - * This method will throw a [[java.lang.ClassCastException]] if the body cannot be mapped to type A. - */ - def mapBody[A, B](transformer: A => B): CamelMessage = copy(body = transformer(body.asInstanceOf[A])) - - /** - * Java API: Returns a new CamelMessage with a transformed body using a transformer function. - * This method will throw a [[java.lang.ClassCastException]] if the body cannot be mapped to type A. - */ - def mapBody[A, B](transformer: Mapper[A, B]): CamelMessage = copy(body = transformer(body.asInstanceOf[A])) - - /** - * 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 that is passed in. - * The CamelContext is accessible in a [[akka.camel.javaapi.UntypedConsumerActor]] and [[akka.camel.javaapi.UntypedProducerActor]] - * using the `getCamelContext` method, and is available on the [[akka.camel.CamelExtension]]. - */ - def bodyAs[T](implicit t: ClassTag[T], camelContext: CamelContext): T = - getBodyAs(t.runtimeClass.asInstanceOf[Class[T]], camelContext) - - /** - * Java API: Returns the body of the message converted to the type as given by the clazz - * parameter. Conversion is done using Camel's type converter. The type converter is obtained - * from the CamelContext that is passed in. - *

- * The CamelContext is accessible in a [[akka.camel.javaapi.UntypedConsumerActor]] and [[akka.camel.javaapi.UntypedProducerActor]] - * using the `getCamelContext` method, and is available on the [[akka.camel.CamelExtension]]. - */ - def getBodyAs[T](clazz: Class[T], camelContext: CamelContext): T = { - val result = camelContext.getTypeConverter.mandatoryConvertTo[T](clazz, body) - // to be able to re-read a StreamCache we must "undo" the side effect by resetting the StreamCache - resetStreamCache() - result - } - - /** - * Reset StreamCache body. Nothing is done if the body is not a StreamCache. - * See http://camel.apache.org/stream-caching.html - */ - def resetStreamCache(): Unit = body match { - case stream: StreamCache => stream.reset - case _ => - } - - /** - * Java API: Returns a new CamelMessage with a new body, while keeping the same headers. - */ - def withBody[T](body: T): CamelMessage = copy(body = body) - - /** - * Creates a CamelMessage with current body converted to type T. - * The CamelContext is accessible in a [[akka.camel.javaapi.UntypedConsumerActor]] and [[akka.camel.javaapi.UntypedProducerActor]] - * using the `getCamelContext` method, and is available on the [[akka.camel.CamelExtension]]. - */ - def withBodyAs[T](implicit t: ClassTag[T], camelContext: CamelContext): CamelMessage = - withBodyAs(t.runtimeClass.asInstanceOf[Class[T]]) - - /** - * Java API: Creates a CamelMessage with current body converted to type clazz. - *

- * The CamelContext is accessible in a [[akka.camel.javaapi.UntypedConsumerActor]] and [[akka.camel.javaapi.UntypedProducerActor]] - * using the `getCamelContext` method, and is available on the [[akka.camel.CamelExtension]]. - */ - def withBodyAs[T](clazz: Class[T])(implicit camelContext: CamelContext): CamelMessage = - copy(body = getBodyAs(clazz, camelContext)) - - /** - * Returns those attachments from this message whose name is contained in names. - */ - def attachments(names: Set[String]): Map[String, DataHandler] = attachments.filterKeys(names).toMap - - /** - * Java API: Returns those attachments from this message whose name is contained in names. - * The returned headers map is backed up by an immutable headers map. Any attempt to modify - * the returned map will throw an exception. - */ - def getAttachments(names: JSet[String]): JMap[String, DataHandler] = attachments(names.asScala.toSet).asJava - - /** - * Java API: Returns all attachments from this message. The returned attachments map is backed up by this - * message's immutable headers map. Any attempt to modify the returned map will throw an - * exception. - */ - def getAttachments: JMap[String, DataHandler] = attachments.asJava - - /** - * Java API: Creates a new CamelMessage with given attachments. A copy of the attachments map is made. - */ - def withAttachments(attachments: JMap[String, DataHandler]): CamelMessage = - CamelMessage(this.body, this.headers, attachments.asScala.toMap) - - /** - * SCALA API: Creates a new CamelMessage with given attachments. - */ - def withAttachments(attachments: Map[String, DataHandler]): CamelMessage = - CamelMessage(this.body, this.headers, attachments) - - /** - * Indicates whether some other object is "equal to" this one. - */ - override def equals(that: Any): Boolean = - that match { - case that: CamelMessage if canEqual(that) => - this.body == that.body && - this.headers == that.headers && - this.attachments == that.attachments - case _ => false - } - - /** - * Returns a hash code value for the object. - */ - override def hashCode(): Int = ScalaRunTime._hashCode(this) - - /** - * Returns the n-th element of this product, 0-based. - */ - override def productElement(n: Int): Any = n match { - case 0 => body - case 1 => headers - case 2 => attachments - } - - /** - * Returns the size of this product. - */ - override def productArity: Int = 3 - - /** - * Indicates if some other object can be compared (based on type). - * This method should be called from every well-designed equals method that is open to be overridden in a subclass. - */ - override def canEqual(that: Any): Boolean = that match { - case _: CamelMessage => true - case _ => false - } -} - -/** - * Companion object of CamelMessage class. - */ -object CamelMessage extends ((Any, Map[String, Any]) => CamelMessage) { - - /** - * Returns a new CamelMessage based on the body and headers. - */ - def apply(body: Any, headers: Map[String, Any]): CamelMessage = - new CamelMessage(body, headers, Map.empty[String, DataHandler]) - - /** - * Returns a new CamelMessage based on the body, headers and attachments. - */ - def apply(body: Any, headers: Map[String, Any], attachments: Map[String, DataHandler]): CamelMessage = - new CamelMessage(body, headers, attachments) - - /** - * Returns Some(body, headers). - */ - def unapply(camelMessage: CamelMessage): Option[(Any, Map[String, Any])] = - Some((camelMessage.body, camelMessage.headers)) - - /** - * 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. - */ - val MessageExchangeId = "MessageExchangeId" //Deliberately without type ascription to make it a constant - - /** - * Creates a canonical form of the given message msg. If msg of type - * CamelMessage then msg is returned, otherwise msg is set as body of a - * newly created CamelMessage object. - */ - private[camel] def canonicalize(msg: Any) = msg match { - case mobj: CamelMessage => mobj - case body => CamelMessage(body, Map.empty[String, Any]) - } - - /** - * Creates a new CamelMessage object from the Camel message. - * - * @param headers additional headers to set on the created CamelMessage in addition to those - * in the Camel message. - */ - private[camel] def from(camelMessage: JCamelMessage, headers: Map[String, Any]): CamelMessage = - CamelMessage( - camelMessage.getBody, - headers ++ camelMessage.getHeaders.asScala, - camelMessage.getAttachments.asScala.toMap) - - /** - * Creates a new CamelMessageWithAttachments object from the Camel message. - * - * @param headers additional headers to set on the created CamelMessageWithAttachments in addition to those - * in the Camel message. - * @param attachments additional attachments to set on the created CamelMessageWithAttachments in addition to those - * in the Camel message. - */ - private[camel] def from( - camelMessage: JCamelMessage, - headers: Map[String, Any], - attachments: Map[String, DataHandler]): CamelMessage = - CamelMessage( - camelMessage.getBody, - headers ++ camelMessage.getHeaders.asScala, - attachments ++ camelMessage.getAttachments.asScala) - - /** - * INTERNAL API - * copies the content of this CamelMessageWithAttachments to an Apache Camel Message. - */ - private[camel] def copyContent(from: CamelMessage, to: JCamelMessage): Unit = { - to.setBody(from.body) - for ((name, value) <- from.headers) to.getHeaders.put(name, value.asInstanceOf[AnyRef]) - to.getAttachments.putAll(from.getAttachments) - } -} - -/** - * Positive acknowledgement message (used for application-acknowledged message receipts). - * When `autoAck` is set to false in the [[akka.camel.Consumer]], you can send an `Ack` to the sender of the CamelMessage. - */ -case object Ack { - - /** Java API to get the Ack singleton */ - def getInstance = this -} - -/** - * An exception indicating that the exchange to the camel endpoint failed. - * It contains the failure cause obtained from Exchange.getException and the headers from either the Exchange.getIn - * message or Exchange.getOut message, depending on the exchange pattern. - */ -class AkkaCamelException private[akka] (cause: Throwable, val headers: Map[String, Any]) - extends AkkaException(cause.getMessage, cause) { - def this(cause: Throwable) = this(cause, Map.empty) -} diff --git a/akka-camel/src/main/scala/akka/camel/CamelSupport.scala b/akka-camel/src/main/scala/akka/camel/CamelSupport.scala deleted file mode 100644 index 1c2592c490..0000000000 --- a/akka-camel/src/main/scala/akka/camel/CamelSupport.scala +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import akka.actor.Actor - -private[camel] trait CamelSupport { this: Actor => - - /** - * INTERNAL API - * Returns a [[akka.camel.Camel]] trait which provides access to the CamelExtension. - */ - protected val camel = CamelExtension(context.system) - - /** - * Returns the CamelContext. - * The camelContext is defined implicit for simplifying the use of CamelMessage from the Scala API. - */ - protected implicit def camelContext = camel.context - -} diff --git a/akka-camel/src/main/scala/akka/camel/Consumer.scala b/akka-camel/src/main/scala/akka/camel/Consumer.scala deleted file mode 100644 index b5f556773c..0000000000 --- a/akka-camel/src/main/scala/akka/camel/Consumer.scala +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import akka.camel.internal.CamelSupervisor.Register -import org.apache.camel.model.{ ProcessorDefinition, RouteDefinition } -import akka.actor._ -import scala.concurrent.duration._ -import akka.dispatch.Mapper - -/** - * Mixed in by Actor implementations that consume message from Camel endpoints. - */ -@deprecated( - "Akka Camel is deprecated in favour of 'Alpakka', the Akka Streams based collection of integrations to various endpoints (including Camel).", - since = "2.5.0") -trait Consumer extends Actor with CamelSupport { - import Consumer._ - - /** - * Must return the Camel endpoint URI that the consumer wants to consume messages from. - */ - def endpointUri: String - - /** - * Registers the consumer endpoint. Note: when overriding this method, be sure to - * call 'super.preRestart', otherwise the consumer endpoint will not be registered. - */ - override def preStart(): Unit = { - super.preStart() - // Possible FIXME. registering the endpoint here because of problems - // with order of execution of trait body in the Java version (UntypedConsumerActor) - // where getEndpointUri is called before its constructor (where a uri is set to return from getEndpointUri) - // and remains null. CustomRouteTest provides a test to verify this. - register() - } - - private[this] def register(): Unit = { - camel.supervisor ! Register( - self, - endpointUri, - Some(ConsumerConfig(activationTimeout, replyTimeout, autoAck, onRouteDefinition))) - } - - /** - * How long the actor should wait for activation before it fails. - */ - def activationTimeout: FiniteDuration = camel.settings.ActivationTimeout - - /** - * When endpoint is out-capable (can produce responses) replyTimeout is the maximum time - * the endpoint can take to send the response before the message exchange fails. It defaults to 1 minute. - * This setting is used for out-capable, in-only, manually acknowledged communication. - */ - def replyTimeout: FiniteDuration = camel.settings.ReplyTimeout - - /** - * Determines whether one-way communications between an endpoint and this consumer actor - * should be auto-acknowledged or application-acknowledged. - * This flag has only effect when exchange is in-only. - */ - def autoAck: Boolean = camel.settings.AutoAck - - /** - * Returns the route definition handler for creating a custom route to this consumer. - * By default it returns an identity function, override this method to - * return a custom route definition handler. The returned function is not allowed to close over 'this', meaning it is - * not allowed to refer to the actor instance itself, since that can easily cause concurrent shared state issues. - */ - def onRouteDefinition: RouteDefinition => ProcessorDefinition[_] = { - val mapper = getRouteDefinitionHandler - if (mapper != identityRouteMapper) mapper.apply _ - else identityRouteMapper - } - - /** - * Java API: Returns the [[akka.dispatch.Mapper]] function that will be used as a route definition handler - * for creating custom route to this consumer. By default it returns an identity function, override this method to - * return a custom route definition handler. The [[akka.dispatch.Mapper]] is not allowed to close over 'this', meaning it is - * not allowed to refer to the actor instance itself, since that can easily cause concurrent shared state issues. - */ - def getRouteDefinitionHandler: Mapper[RouteDefinition, ProcessorDefinition[_]] = identityRouteMapper -} - -/** - * Internal use only. - */ -private[camel] object Consumer { - val identityRouteMapper = new Mapper[RouteDefinition, ProcessorDefinition[_]]() { - override def checkedApply(rd: RouteDefinition): ProcessorDefinition[_] = rd - } -} - -/** - * INTERNAL API - * Captures the configuration of the Consumer. - * - * Was a case class but has been split up as a workaround for SI-8283 - */ -private[camel] class ConsumerConfig( - val activationTimeout: FiniteDuration, - val replyTimeout: FiniteDuration, - val autoAck: Boolean, - val onRouteDefinition: RouteDefinition => ProcessorDefinition[_]) - extends NoSerializationVerificationNeeded - with scala.Serializable - -private[camel] object ConsumerConfig { - def apply( - activationTimeout: FiniteDuration, - replyTimeout: FiniteDuration, - autoAck: Boolean, - onRouteDefinition: RouteDefinition => ProcessorDefinition[_]): ConsumerConfig = - new ConsumerConfig(activationTimeout, replyTimeout, autoAck, onRouteDefinition) -} diff --git a/akka-camel/src/main/scala/akka/camel/ContextProvider.scala b/akka-camel/src/main/scala/akka/camel/ContextProvider.scala deleted file mode 100644 index 656b43edac..0000000000 --- a/akka-camel/src/main/scala/akka/camel/ContextProvider.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import akka.actor.ExtendedActorSystem -import org.apache.camel.impl.DefaultCamelContext - -/** - * Implement this interface in order to inject a specific CamelContext in a system - * An instance of this class must be instantiable using a no-arg constructor. - */ -trait ContextProvider { - - /** - * Retrieve or create a Camel Context for the given actor system - * Called once per actor system - */ - def getContext(system: ExtendedActorSystem): DefaultCamelContext -} - -/** - * Default implementation of [[akka.camel.ContextProvider]] - * Provides a new DefaultCamelContext per actor system - */ -final class DefaultContextProvider extends ContextProvider { - override def getContext(system: ExtendedActorSystem) = new DefaultCamelContext -} diff --git a/akka-camel/src/main/scala/akka/camel/Producer.scala b/akka-camel/src/main/scala/akka/camel/Producer.scala deleted file mode 100644 index 299a896501..0000000000 --- a/akka-camel/src/main/scala/akka/camel/Producer.scala +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import akka.actor.{ Actor, ActorRef, NoSerializationVerificationNeeded, Props } -import internal.CamelSupervisor.{ CamelProducerObjects, Register } -import internal.CamelExchangeAdapter -import akka.actor.Status.Failure -import org.apache.camel.{ AsyncCallback, Endpoint, ExchangePattern } -import org.apache.camel.processor.SendProcessor - -/** - * Support trait for producing messages to Camel endpoints. - */ -trait ProducerSupport extends Actor with CamelSupport { - private[this] var messages = Vector.empty[(ActorRef, Any)] - private[this] var producerChild: Option[ActorRef] = None - - override def preStart(): Unit = { - super.preStart() - register() - } - - private[this] def register(): Unit = { camel.supervisor ! Register(self, endpointUri) } - - /** - * CamelMessage headers to copy by default from request message to response-message. - */ - private val headersToCopyDefault: Set[String] = Set(CamelMessage.MessageExchangeId) - - /** - * If set to false (default), this producer expects a response message from the Camel endpoint. - * If set to true, this producer initiates an in-only message exchange with the Camel endpoint - * (fire and forget). - */ - def oneway: Boolean = false - - /** - * Returns the Camel endpoint URI to produce messages to. - */ - def endpointUri: String - - /** - * Returns the names of message headers to copy from a request message to a response message. - * 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 - - /** - * Produces msg to the endpoint specified by endpointUri. Before the message is - * actually sent it is pre-processed by calling transformOutgoingMessage. If oneway - * is true, an in-only message exchange is initiated, otherwise an in-out message exchange. - * - * @see Producer#produce - */ - protected def produce: Receive = { - case CamelProducerObjects(endpoint, processor) => - if (producerChild.isEmpty) { - val disp = camel.settings.ProducerChildDispatcher match { - case "" => context.props.dispatcher - case d => d - } - producerChild = Some(context.actorOf(Props(new ProducerChild(endpoint, processor)).withDispatcher(disp))) - messages = { - for (child <- producerChild; - (snd, msg) <- messages) child.tell(transformOutgoingMessage(msg), snd) - Vector.empty - } - } - case res: MessageResult => routeResponse(res.message) - case res: FailureResult => - val e = new AkkaCamelException(res.cause, res.headers) - routeResponse(Failure(e)) - throw e - - case msg => - producerChild match { - case Some(child) => child.forward(transformOutgoingMessage(msg)) - case None => messages :+= ((sender(), msg)) - } - } - - /** - * Called before the message is sent to the endpoint specified by endpointUri. The original - * message is passed as argument. By default, this method simply returns the argument but may be overridden - * by subtraits or subclasses. - */ - protected def transformOutgoingMessage(msg: Any): Any = msg - - /** - * Called before the response message is sent to the original sender. The original - * message is passed as argument. By default, this method simply returns the argument but may be overridden - * by subtraits or subclasses. - */ - protected def transformResponse(msg: Any): Any = msg - - /** - * Called after a response was received from the endpoint specified by endpointUri. The - * response is passed as argument. By default, this method sends the response back to the original sender - * if oneway is false. If oneway is true, nothing is - * done. This method may be overridden by subtraits or subclasses (e.g. to forward responses to another - * actor). - */ - protected def routeResponse(msg: Any): Unit = if (!oneway) sender() ! transformResponse(msg) - - private class ProducerChild(endpoint: Endpoint, processor: SendProcessor) extends Actor { - def receive = { - case msg @ (_: FailureResult | _: MessageResult) => context.parent.forward(msg) - case msg => produce(endpoint, processor, msg, if (oneway) ExchangePattern.InOnly else ExchangePattern.InOut) - } - - /** - * Initiates a message exchange of given pattern with the endpoint specified by - * endpointUri. The in-message of the initiated exchange is the canonical form - * of msg. After sending the in-message, the processing result (response) is passed - * as argument to receiveAfterProduce. If the response is received synchronously from - * the endpoint then receiveAfterProduce is called synchronously as well. If the - * response is received asynchronously, the receiveAfterProduce is called - * asynchronously. The original sender is preserved. - * - * @see CamelMessage#canonicalize - * @param endpoint the endpoint - * @param processor the processor - * @param msg message to produce - * @param pattern exchange pattern - */ - protected def produce(endpoint: Endpoint, processor: SendProcessor, msg: Any, pattern: ExchangePattern): Unit = { - // Need copies of sender reference here since the callback could be done - // later by another thread. - val producer = context.parent - val originalSender = sender() - val xchg = new CamelExchangeAdapter(endpoint.createExchange(pattern)) - val cmsg = CamelMessage.canonicalize(msg) - xchg.setRequest(cmsg) - - processor.process( - xchg.exchange, - new AsyncCallback { - // Ignoring doneSync, sending back async uniformly. - def done(doneSync: Boolean): Unit = - producer.tell( - if (xchg.exchange.isFailed) xchg.toFailureResult(cmsg.headers(headersToCopy)) - else MessageResult(xchg.toResponseMessage(cmsg.headers(headersToCopy))), - originalSender) - }) - } - } -} - -/** - * Mixed in by Actor implementations to produce messages to Camel endpoints. - */ -@deprecated( - "Akka Camel is deprecated in favour of 'Alpakka', the Akka Streams based collection of integrations to various endpoints (including Camel).", - since = "2.5.0") -trait Producer extends ProducerSupport { this: Actor => - - /** - * Implementation of Actor.receive. Any messages received by this actor - * will be produced to the endpoint specified by endpointUri. - */ - final def receive: Actor.Receive = produce -} - -/** - * INTERNAL API - */ -private final case class MessageResult(message: CamelMessage) extends NoSerializationVerificationNeeded - -/** - * INTERNAL API - */ -private final case class FailureResult(cause: Throwable, headers: Map[String, Any] = Map.empty) - extends NoSerializationVerificationNeeded - -/** - * A one-way producer. - * - * - */ -@deprecated( - "Akka Camel is deprecated in favour of 'Alpakka', the Akka Streams based collection of integrations to various endpoints (including Camel).", - since = "2.5.0") -trait Oneway extends Producer { this: Actor => - override def oneway: Boolean = true -} diff --git a/akka-camel/src/main/scala/akka/camel/internal/ActivationMessage.scala b/akka-camel/src/main/scala/akka/camel/internal/ActivationMessage.scala deleted file mode 100644 index 1b4edb61d8..0000000000 --- a/akka-camel/src/main/scala/akka/camel/internal/ActivationMessage.scala +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel.internal - -import akka.actor.ActorRef - -private[camel] object ActivationProtocol { - - /** - * Super class of all activation messages. Registration of the Camel [[akka.camel.Consumer]]s and [[akka.camel.Producer]]s - * is done asynchronously. Activation messages are sent in the Camel extension when endpoints are - * activated, de-activated, failed to activate and failed to de-activate. - * You can use the [[akka.camel.Activation]] trait which is available on [[akka.camel.Camel]] - * to await activation or de-activation of endpoints. - */ - @SerialVersionUID(1L) - private[camel] abstract class ActivationMessage(val actor: ActorRef) extends Serializable - - /** - * INTERNAL API - * companion object of ActivationMessage - */ - private[camel] object ActivationMessage { - def unapply(msg: ActivationMessage): Option[ActorRef] = Option(msg.actor) - } - - /** - * INTERNAL API - * Event message indicating that a single endpoint has been activated. - * You can use the [[akka.camel.Activation]] trait which is available on [[akka.camel.Camel]] - * to await activation or de-activation of endpoints. - * @param actorRef the endpoint that was activated - */ - @SerialVersionUID(1L) - final case class EndpointActivated(actorRef: ActorRef) extends ActivationMessage(actorRef) - - /** - * INTERNAL API - * Event message indicating that a single endpoint failed to activate. - * You can use the [[akka.camel.Activation]] trait which is available on [[akka.camel.Camel]] - * to await activation or de-activation of endpoints. - * @param actorRef the endpoint that failed to activate - * @param cause the cause for failure - */ - @SerialVersionUID(1L) - final case class EndpointFailedToActivate(actorRef: ActorRef, cause: Throwable) extends ActivationMessage(actorRef) - - /** - * INTERNAL API - * Event message indicating that a single endpoint was de-activated. - * You can use the [[akka.camel.Activation]] trait which is available on [[akka.camel.Camel]] - * to await activation or de-activation of endpoints. - * @param actorRef the endpoint that was de-activated - */ - @SerialVersionUID(1L) - final case class EndpointDeActivated(actorRef: ActorRef) extends ActivationMessage(actorRef) - - /** - * INTERNAL API - * Event message indicating that a single endpoint failed to de-activate. - * You can use the [[akka.camel.Activation]] trait which is available on [[akka.camel.Camel]] - * to await activation or de-activation of endpoints. - * @param actorRef the endpoint that failed to de-activate - * @param cause the cause for failure - */ - @SerialVersionUID(1L) - final case class EndpointFailedToDeActivate(actorRef: ActorRef, cause: Throwable) extends ActivationMessage(actorRef) -} diff --git a/akka-camel/src/main/scala/akka/camel/internal/ActivationTracker.scala b/akka-camel/src/main/scala/akka/camel/internal/ActivationTracker.scala deleted file mode 100644 index 824c3021b0..0000000000 --- a/akka-camel/src/main/scala/akka/camel/internal/ActivationTracker.scala +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel.internal - -import akka.actor._ -import collection.mutable.WeakHashMap -import akka.camel.internal.ActivationProtocol._ - -/** - * INTERNAL API - * An actor that tracks activation and de-activation of endpoints. - */ -private[camel] 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]() - - { - case AwaitActivation(ref) => awaitingActivation ::= sender() - case AwaitDeActivation(ref) => awaitingDeActivation ::= sender() - case msg @ EndpointActivated(ref) => - awaitingActivation.foreach(_ ! msg) - receive = activated(awaitingDeActivation) - 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) => - awaitingDeActivation.foreach(_ ! msg) - receive = deactivated - 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 = { - // deactivated means it was activated at some point, so tell sender() it was activated - case AwaitActivation(ref) => sender() ! EndpointActivated(ref) - case AwaitDeActivation(ref) => sender() ! EndpointDeActivated(ref) - //resurrected at restart. - case msg @ EndpointActivated(ref) => - receive = activated(Nil) - } - - /** - * 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) - case EndpointDeActivated(_) => // the de-register at termination always sends a de-activated when the cleanup is done. ignoring. - } - - /** - * 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) - case EndpointDeActivated(_) => // the de-register at termination always sends a de-activated when the cleanup is done. ignoring. - } - - } - - override def receive = { - case msg @ ActivationMessage(ref) => - activations.getOrElseUpdate(ref, new ActivationStateMachine).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) - } -} - -/** - * INTERNAL API - * A request message to the ActivationTracker for the status of activation. - * @param ref the actorRef - */ -private[camel] final case class AwaitActivation(ref: ActorRef) extends ActivationMessage(ref) - -/** - * INTERNAL API - * A request message to the ActivationTracker for the status of de-activation. - * @param ref the actorRef - */ -private[camel] final case class AwaitDeActivation(ref: ActorRef) extends ActivationMessage(ref) diff --git a/akka-camel/src/main/scala/akka/camel/internal/CamelExchangeAdapter.scala b/akka-camel/src/main/scala/akka/camel/internal/CamelExchangeAdapter.scala deleted file mode 100644 index 87b643b666..0000000000 --- a/akka-camel/src/main/scala/akka/camel/internal/CamelExchangeAdapter.scala +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel.internal - -import org.apache.camel.util.ExchangeHelper -import org.apache.camel.{ Exchange, Message => JCamelMessage } -import akka.camel.{ AkkaCamelException, CamelMessage, FailureResult } - -/** - * INTERNAL API - * Adapter for converting an [[org.apache.camel.Exchange]] to and from [[akka.camel.CamelMessage]] and [[akka.camel.FailureResult]] objects. - * The org.apache.camel.Message is mutable and not suitable to be used directly as messages between Actors. - * This adapter is used to convert to immutable messages to be used with Actors, and convert the immutable messages back - * to org.apache.camel.Message when using Camel. - */ -private[camel] class CamelExchangeAdapter(val exchange: Exchange) { - - /** - * Returns the exchange id - */ - def getExchangeId: String = exchange.getExchangeId - - /** - * Returns if the exchange is out capable. - */ - def isOutCapable: Boolean = exchange.getPattern.isOutCapable - - /** - * Sets Exchange.getIn from the given CamelMessage object. - */ - def setRequest(msg: CamelMessage): Unit = CamelMessage.copyContent(msg, request) - - /** - * Depending on the exchange pattern, sets Exchange.getIn or Exchange.getOut from the given - * CamelMessage object. If the exchange is out-capable then the Exchange.getOut is set, otherwise - * Exchange.getIn. - */ - def setResponse(msg: CamelMessage): Unit = CamelMessage.copyContent(msg, response) - - /** - * Sets Exchange.getException from the given FailureResult message. Headers of the FailureResult message - * are ignored. - */ - def setFailure(msg: FailureResult): Unit = exchange.setException(msg.cause) - - /** - * Creates an immutable CamelMessage object from Exchange.getIn so it can be used with Actors. - */ - def toRequestMessage: CamelMessage = toRequestMessage(Map.empty) - - /** - * Depending on the exchange pattern, creates an immutable CamelMessage object from Exchange.getIn or Exchange.getOut so it can be used with Actors. - * If the exchange is out-capable then the Exchange.getOut is set, otherwise Exchange.getIn. - */ - def toResponseMessage: CamelMessage = toResponseMessage(Map.empty) - - /** - * Creates an AkkaCamelException object from the adapted Exchange. - * The cause of the AkkaCamelException is set to the exception on the adapted Exchange. - * - * Depending on the exchange pattern, puts the headers from Exchange.getIn or Exchange.getOut - * on the AkkaCamelException. - * - * If the exchange is out-capable then the headers of Exchange.getOut are used, otherwise the headers of Exchange.getIn are used. - */ - def toAkkaCamelException: AkkaCamelException = toAkkaCamelException(Map.empty) - - /** - * Creates an AkkaCamelException object from the adapted Exchange. - * The cause of the AkkaCamelException is set to the exception on the adapted Exchange. - * - * Depending on the exchange pattern, adds the supplied headers and the headers from Exchange.getIn or Exchange.getOut - * together and passes these to the AkkaCamelException. - * - * If the exchange is out-capable then the headers of Exchange.getOut are used, otherwise the headers of Exchange.getIn are used. - * - * @param headers additional headers to set on the exception in addition to those - * in the exchange. - */ - def toAkkaCamelException(headers: Map[String, Any]): AkkaCamelException = { - import scala.collection.JavaConverters._ - new AkkaCamelException(exchange.getException, headers ++ response.getHeaders.asScala) - } - - /** - * Creates an immutable Failure object from the adapted Exchange so it can be used internally between Actors. - */ - def toFailureMessage: FailureResult = toFailureResult(Map.empty) - - /** - * Creates an immutable FailureResult object from the adapted Exchange so it can be used internally between Actors. - * - * @param headers additional headers to set on the created CamelMessage in addition to those - * in the Camel message. - */ - def toFailureResult(headers: Map[String, Any]): FailureResult = { - import scala.collection.JavaConverters._ - FailureResult(exchange.getException, headers ++ response.getHeaders.asScala) - } - - /** - * Creates an immutable CamelMessage object from Exchange.getIn so it can be used with Actors. - * - * @param headers additional headers to set on the created CamelMessage in addition to those - * in the Camel message. - */ - def toRequestMessage(headers: Map[String, Any]): CamelMessage = CamelMessage.from(request, headers) - - /** - * Depending on the exchange pattern, creates an immutable CamelMessage object from Exchange.getIn or Exchange.getOut so it can be used with Actors. - * If the exchange is out-capable then the Exchange.getOut is set, otherwise Exchange.getIn. - * - * @param headers additional headers to set on the created CamelMessage in addition to those - * in the Camel message. - */ - def toResponseMessage(headers: Map[String, Any]): CamelMessage = CamelMessage.from(response, headers) - - private def request: JCamelMessage = exchange.getIn - - private def response: JCamelMessage = ExchangeHelper.getResultMessage(exchange) - -} diff --git a/akka-camel/src/main/scala/akka/camel/internal/CamelSupervisor.scala b/akka-camel/src/main/scala/akka/camel/internal/CamelSupervisor.scala deleted file mode 100644 index e18ef47c53..0000000000 --- a/akka-camel/src/main/scala/akka/camel/internal/CamelSupervisor.scala +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel.internal - -import akka.actor._ -import akka.camel.{ CamelSupport, ConsumerConfig } -import org.apache.camel.Endpoint -import org.apache.camel.processor.SendProcessor -import scala.util.control.NonFatal -import akka.actor.Terminated -import akka.actor.SupervisorStrategy.Resume -import akka.camel.internal.CamelSupervisor._ -import akka.AkkaException -import akka.camel.internal.ActivationProtocol._ -import akka.event.Logging - -/** - * INTERNAL API - * Top level supervisor for internal Camel actors - */ -private[camel] class CamelSupervisor extends Actor with CamelSupport { - private val activationTracker = context.actorOf(Props[ActivationTracker], "activationTracker") - private val registry: ActorRef = context.actorOf(Props(classOf[Registry], activationTracker), "registry") - - override val supervisorStrategy = OneForOneStrategy() { - case NonFatal(e) => - Resume - } - - def receive = { - case AddWatch(actorRef) => context.watch(actorRef) - case Terminated(actorRef) => registry ! DeRegister(actorRef) - case msg: ActivationMessage => activationTracker.forward(msg) - case msg => registry.forward(msg) - } -} - -/** - * INTERNAL API - * Messages for the camel supervisor, registrations and de-registrations. - */ -private[camel] object CamelSupervisor { - - @SerialVersionUID(1L) - sealed trait CamelSupervisorMessage extends Serializable - - /** - * INTERNAL API - * Registers a consumer or a producer. - */ - final case class Register(actorRef: ActorRef, endpointUri: String, config: Option[ConsumerConfig] = None) - extends NoSerializationVerificationNeeded - - /** - * INTERNAL API - * De-registers a producer or a consumer. - */ - @SerialVersionUID(1L) - final case class DeRegister(actorRef: ActorRef) extends CamelSupervisorMessage - - /** - * INTERNAL API - * Adds a watch for the actor - */ - @SerialVersionUID(1L) - final case class AddWatch(actorRef: ActorRef) extends CamelSupervisorMessage - - /** - * INTERNAL API - * Provides a Producer with the required camel objects to function. - */ - final case class CamelProducerObjects(endpoint: Endpoint, processor: SendProcessor) - extends NoSerializationVerificationNeeded -} - -/** - * INTERNAL API - * Thrown by registrars to indicate that the actor could not be de-activated. - */ -private[camel] class ActorDeActivationException(val actorRef: ActorRef, cause: Throwable) - extends AkkaException(s"$actorRef failed to de-activate", cause) - -/** - * INTERNAL API - * Thrown by the registrars to indicate that the actor could not be activated. - */ -private[camel] class ActorActivationException(val actorRef: ActorRef, cause: Throwable) - extends AkkaException(s"$actorRef failed to activate", cause) - -/** - * INTERNAL API - * Registry for Camel Consumers and Producers. Supervises the registrars. - */ -private[camel] class Registry(activationTracker: ActorRef) extends Actor with CamelSupport { - import context.{ parent, stop } - - private val producerRegistrar = - context.actorOf(Props(classOf[ProducerRegistrar], activationTracker), "producerRegistrar") - private val consumerRegistrar = - context.actorOf(Props(classOf[ConsumerRegistrar], activationTracker), "consumerRegistrar") - private var producers = Set[ActorRef]() - private var consumers = Set[ActorRef]() - - class RegistryLogStrategy()(_decider: SupervisorStrategy.Decider) extends OneForOneStrategy()(_decider) { - override def logFailure( - context: ActorContext, - child: ActorRef, - cause: Throwable, - decision: SupervisorStrategy.Directive): Unit = - cause match { - case _: ActorActivationException | _: ActorDeActivationException => - try context.system.eventStream.publish { - Logging.Error(cause.getCause, child.path.toString, getClass, cause.getMessage) - } catch { case NonFatal(_) => } - case _ => super.logFailure(context, child, cause, decision) - } - } - - override val supervisorStrategy = new RegistryLogStrategy()({ - case e: ActorActivationException => - activationTracker ! EndpointFailedToActivate(e.actorRef, e.getCause) - stop(e.actorRef) - Resume - case e: ActorDeActivationException => - activationTracker ! EndpointFailedToDeActivate(e.actorRef, e.getCause) - stop(e.actorRef) - Resume - case NonFatal(e) => - Resume - }) - - def receive = { - case msg @ Register(consumer, _, Some(_)) => - if (!consumers(consumer)) { - consumers += consumer - consumerRegistrar.forward(msg) - parent ! AddWatch(consumer) - } - case msg @ Register(producer, _, None) => - if (!producers(producer)) { - producers += producer - parent ! AddWatch(producer) - } - producerRegistrar.forward(msg) - case DeRegister(actorRef) => - producers.find(_ == actorRef).foreach { p => - deRegisterProducer(p) - producers -= p - } - consumers.find(_ == actorRef).foreach { c => - deRegisterConsumer(c) - consumers -= c - } - } - - private def deRegisterConsumer(actorRef: ActorRef): Unit = { consumerRegistrar ! DeRegister(actorRef) } - - private def deRegisterProducer(actorRef: ActorRef): Unit = { producerRegistrar ! DeRegister(actorRef) } -} - -/** - * INTERNAL API - * Registers Producers. - */ -private[camel] class ProducerRegistrar(activationTracker: ActorRef) extends Actor with CamelSupport { - private var camelObjects = Map[ActorRef, (Endpoint, SendProcessor)]() - - def receive = { - case Register(producer, endpointUri, _) => - if (!camelObjects.contains(producer)) { - try { - val endpoint = camelContext.getEndpoint(endpointUri) - val processor = new SendProcessor(endpoint) - camelObjects = camelObjects.updated(producer, endpoint -> processor) - // if this throws, the supervisor stops the producer and de-registers it on termination - processor.start() - producer ! CamelProducerObjects(endpoint, processor) - activationTracker ! EndpointActivated(producer) - } catch { - case NonFatal(e) => throw new ActorActivationException(producer, e) - } - } else { - camelObjects.get(producer).foreach { - case (endpoint, processor) => producer ! CamelProducerObjects(endpoint, processor) - } - } - case DeRegister(producer) => - camelObjects.get(producer).foreach { - case (_, processor) => - try { - camelObjects.get(producer).foreach(_._2.stop()) - camelObjects -= producer - activationTracker ! EndpointDeActivated(producer) - } catch { - case NonFatal(e) => throw new ActorDeActivationException(producer, e) - } - } - } -} - -/** - * INTERNAL API - * Registers Consumers. - */ -private[camel] class ConsumerRegistrar(activationTracker: ActorRef) extends Actor with CamelSupport { - def receive = { - case Register(consumer, endpointUri, Some(consumerConfig)) => - try { - // if this throws, the supervisor stops the consumer and de-registers it on termination - camelContext.addRoutes(new ConsumerActorRouteBuilder(endpointUri, consumer, consumerConfig, camel.settings)) - activationTracker ! EndpointActivated(consumer) - } catch { - case NonFatal(e) => throw new ActorActivationException(consumer, e) - } - case DeRegister(consumer) => - try { - val route = consumer.path.toString - camelContext.stopRoute(route) - camelContext.removeRoute(route) - activationTracker ! EndpointDeActivated(consumer) - } catch { - case NonFatal(e) => throw new ActorDeActivationException(consumer, e) - } - } -} diff --git a/akka-camel/src/main/scala/akka/camel/internal/ConsumerActorRouteBuilder.scala b/akka-camel/src/main/scala/akka/camel/internal/ConsumerActorRouteBuilder.scala deleted file mode 100644 index 0fe6f0a6ec..0000000000 --- a/akka-camel/src/main/scala/akka/camel/internal/ConsumerActorRouteBuilder.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel.internal - -import akka.actor._ -import akka.camel._ -import akka.camel.internal.component.CamelPath -import org.apache.camel.builder.RouteBuilder -import org.apache.camel.model.RouteDefinition - -import scala.language.existentials - -/** - * INTERNAL API - * Builder of a route to a target which can be an actor. - * - * @param endpointUri endpoint URI of the consumer actor. - * - * - */ -private[camel] class ConsumerActorRouteBuilder( - endpointUri: String, - consumer: ActorRef, - config: ConsumerConfig, - settings: CamelSettings) - extends RouteBuilder { - - protected def targetActorUri = CamelPath.toUri(consumer, config.autoAck, config.replyTimeout) - - def configure(): Unit = - applyUserRouteCustomization( - settings.Conversions.apply( - endpointUri.take(endpointUri.indexOf(":")), // e.g. "http" from "http://whatever/..." - from(endpointUri).routeId(consumer.path.toString))).to(targetActorUri) - - def applyUserRouteCustomization(rd: RouteDefinition) = config.onRouteDefinition(rd) -} diff --git a/akka-camel/src/main/scala/akka/camel/internal/DefaultCamel.scala b/akka-camel/src/main/scala/akka/camel/internal/DefaultCamel.scala deleted file mode 100644 index 4b183dbc44..0000000000 --- a/akka-camel/src/main/scala/akka/camel/internal/DefaultCamel.scala +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel.internal - -import akka.camel.internal.component.{ ActorComponent, DurationTypeConverter } -import org.apache.camel.impl.DefaultCamelContext -import scala.Predef._ -import akka.event.Logging -import akka.camel.{ Camel, CamelSettings } -import akka.camel.internal.ActivationProtocol._ -import scala.util.control.NonFatal -import scala.concurrent.duration._ -import org.apache.camel.ProducerTemplate -import scala.concurrent.{ ExecutionContext, Future } -import akka.util.Timeout -import akka.pattern.ask -import akka.actor.{ ActorRef, ExtendedActorSystem, Props } - -/** - * INTERNAL API - * Creates an instance of the Camel subsystem. - * - * @param system is used to create internal actors needed by camel instance. - * Camel doesn't maintain the lifecycle of this actor system. The actor system has to be shut down by the user. - * In the typical scenario, when camel is used with akka extension, it is natural that camel reuses the actor system it extends. - * Also by not creating extra internal actor system we are conserving resources. - */ -private[camel] class DefaultCamel(val system: ExtendedActorSystem) extends Camel { - val supervisor = system.actorOf(Props[CamelSupervisor], "camel-supervisor") - private[camel] implicit val log = Logging(system, getClass.getName) - - lazy val context: DefaultCamelContext = { - val ctx = settings.ContextProvider.getContext(system) - if (!settings.JmxStatistics) ctx.disableJMX() - ctx.setName(system.name) - ctx.setStreamCaching(settings.StreamingCache) - ctx.addComponent("akka", new ActorComponent(this, system)) - ctx.getTypeConverterRegistry.addTypeConverter(classOf[FiniteDuration], classOf[String], DurationTypeConverter) - ctx - } - - val settings = new CamelSettings(system.settings.config, system.dynamicAccess) - - lazy val template: ProducerTemplate = context.createProducerTemplate() - - /** - * Starts camel and underlying camel context and template. - * Only the creator of Camel should start and stop it. - * @see akka.camel.internal.DefaultCamel#shutdown - */ - def start(): this.type = { - context.start() - try template.start() - catch { case NonFatal(e) => context.stop(); throw e } - log.debug("Started CamelContext[{}] for ActorSystem[{}]", context.getName, system.name) - this - } - - /** - * Stops camel and underlying camel context and template. - * Only the creator of Camel should shut it down. - * There is no need to stop Camel instance, which you get from the CamelExtension, as its lifecycle is bound to the actor system. - * - * @see akka.camel.internal.DefaultCamel#start - */ - def shutdown(): Unit = { - 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) - } - - /** - * Produces a Future with the specified endpoint that will be completed when the endpoint has been activated, - * or if it times out, which will happen after the specified Timeout. - * - * @param endpoint the endpoint to be activated - * @param timeout the timeout for the Future - */ - def activationFutureFor(endpoint: ActorRef)(implicit timeout: Timeout, executor: ExecutionContext): Future[ActorRef] = - (supervisor - .ask(AwaitActivation(endpoint))(timeout)) - .map[ActorRef]({ - case EndpointActivated(`endpoint`) => endpoint - case EndpointFailedToActivate(`endpoint`, cause) => throw cause - }) - - /** - * Produces a Future which will be completed when the given endpoint has been deactivated or - * or if it times out, which will happen after the specified Timeout. - * - * @param endpoint the endpoint to be deactivated - * @param timeout the timeout of the Future - */ - def deactivationFutureFor( - endpoint: ActorRef)(implicit timeout: Timeout, executor: ExecutionContext): Future[ActorRef] = - (supervisor - .ask(AwaitDeActivation(endpoint))(timeout)) - .map[ActorRef]({ - case EndpointDeActivated(`endpoint`) => endpoint - case EndpointFailedToDeActivate(`endpoint`, cause) => throw cause - }) -} 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 deleted file mode 100644 index 3dd6458fd7..0000000000 --- a/akka-camel/src/main/scala/akka/camel/internal/component/ActorComponent.scala +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel.internal.component - -import java.util.{ Map => JMap } -import org.apache.camel._ -import org.apache.camel.impl.{ DefaultComponent, DefaultEndpoint, DefaultProducer } -import akka.actor._ -import akka.pattern._ -import scala.beans.BeanProperty -import scala.concurrent.duration._ -import scala.concurrent.{ Future } -import scala.util.control.NonFatal -import java.util.concurrent.{ CountDownLatch, TimeoutException } -import akka.util.Timeout -import akka.camel.internal.CamelExchangeAdapter -import akka.camel.{ Ack, ActorNotRegisteredException, Camel, CamelMessage, FailureResult } -import support.TypeConverterSupport -import scala.util.{ Failure, Success, Try } - -/** - * INTERNAL API - * Creates Camel [[org.apache.camel.Endpoint]]s that send messages to [[akka.camel.Consumer]] actors through an [[akka.camel.internal.component.ActorProducer]]. - * The `ActorComponent` is a Camel [[org.apache.camel.Component]]. - * - * Camel integrates with Akka through this component. The [[akka.camel.internal.DefaultCamel]] module adds the - * `ActorComponent` to the [[org.apache.camel.CamelContext]] under the 'actor' component name. - * Messages are sent to [[akka.camel.Consumer]] actors through a [[akka.camel.internal.component.ActorEndpoint]] that - * this component provides. - */ -private[camel] class ActorComponent(camel: Camel, system: ActorSystem) extends DefaultComponent { - - /** - * @see org.apache.camel.Component - */ - def createEndpoint(uri: String, remaining: String, parameters: JMap[String, Object]): ActorEndpoint = - new ActorEndpoint(uri, this, ActorEndpointPath.fromCamelPath(uri), camel) -} - -/** - * INTERNAL API - * Does what an endpoint does, creates consumers and producers for the component. The `ActorEndpoint` is a Camel [[org.apache.camel.Endpoint]] that is used to - * receive messages from Camel. Sending messages from the `ActorComponent` is not supported, a [[akka.camel.Producer]] actor should be used instead. - * - * The `ActorEndpoint`s are created by the [[akka.camel.internal.component.ActorComponent]]. - * - * Actors are referenced using actor endpoint URIs of the following format: - * [actorPath]?[options]%s, - * where [actorPath] refers to the actor path to the actor. - */ -private[camel] class ActorEndpoint(uri: String, comp: ActorComponent, val path: ActorEndpointPath, val camel: Camel) - extends DefaultEndpoint(uri, comp) - with ActorEndpointConfig { - - /** - * The ActorEndpoint 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") - - /** - * Creates a new producer which is used send messages into the endpoint. - * - * @return a newly created producer - */ - def createProducer: ActorProducer = new ActorProducer(this, camel) - - /** - * Returns true. - */ - def isSingleton: Boolean = true -} - -/** - * INTERNAL API - * Configures the `ActorEndpoint`. This needs to be a `bean` for Camel purposes. - */ -private[camel] trait ActorEndpointConfig { - def path: ActorEndpointPath - def camel: Camel - - @BeanProperty var replyTimeout: FiniteDuration = camel.settings.ReplyTimeout - - @BeanProperty var autoAck: Boolean = camel.settings.AutoAck -} - -/** - * Sends the in-message of an exchange to an untyped actor, identified by an [[akka.camel.internal.component.ActorEndpoint]] - * - * @see akka.camel.internal.component.ActorComponent - * @see akka.camel.internal.component.ActorEndpoint - */ -private[camel] class ActorProducer(val endpoint: ActorEndpoint, camel: Camel) - extends DefaultProducer(endpoint) - with AsyncProcessor { - - /** - * Processes the exchange. - * Calls the synchronous version of the method and waits for the result (blocking). - * @param exchange the exchange to process - */ - def process(exchange: Exchange): Unit = processExchangeAdapter(new CamelExchangeAdapter(exchange)) - - /** - * 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) - - /** - * INTERNAL API - * Processes the [[akka.camel.internal.CamelExchangeAdapter]] - * @param exchange the [[akka.camel.internal.CamelExchangeAdapter]] - */ - private[camel] def processExchangeAdapter(exchange: CamelExchangeAdapter): Unit = { - val isDone = new CountDownLatch(1) - processExchangeAdapter(exchange, new AsyncCallback { def done(doneSync: Boolean): Unit = { isDone.countDown() } }) - isDone.await(endpoint.replyTimeout.length, endpoint.replyTimeout.unit) - } - - /** - * INTERNAL API - * 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 = { - if (!exchange.isOutCapable && endpoint.autoAck) { - fireAndForget(messageFor(exchange), exchange) - callback.done(true) - true // done sync - } else { - val action: PartialFunction[Try[Any], Unit] = - if (exchange.isOutCapable) { - case Success(failure: FailureResult) => exchange.setFailure(failure) - case Success(msg) => exchange.setResponse(CamelMessage.canonicalize(msg)) - case Failure(e: TimeoutException) => - exchange.setFailure( - FailureResult( - 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 Failure(throwable) => exchange.setFailure(FailureResult(throwable)) - } else { - case Success(Ack) => () /* no response message to set */ - case Success(failure: FailureResult) => exchange.setFailure(failure) - case Success(msg) => - exchange.setFailure( - FailureResult( - new IllegalArgumentException( - "Expected Ack or Failure message, but got: [%s] from actor [%s]".format(msg, endpoint.path)))) - case Failure(e: TimeoutException) => - exchange.setFailure( - FailureResult( - 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 Failure(throwable) => exchange.setFailure(FailureResult(throwable)) - } - - // FIXME #3074 how do we solve this with actorSelection? - val async = try actorFor(endpoint.path).ask(messageFor(exchange))(Timeout(endpoint.replyTimeout)) - catch { case NonFatal(e) => Future.failed(e) } - implicit val ec = camel.system.dispatcher // FIXME which ExecutionContext should be used here? - async.onComplete(action.andThen { _ => - callback.done(false) - }) - false - } - - } - - // FIXME #3074 how do we solve this with actorSelection? - private def fireAndForget(message: CamelMessage, exchange: CamelExchangeAdapter): Unit = - try { - actorFor(endpoint.path) ! message - } catch { case NonFatal(e) => exchange.setFailure(new FailureResult(e)) } - - 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(CamelMessage.MessageExchangeId -> exchange.getExchangeId)) -} - -/** - * INTERNAL API - * Converts Strings to [[scala.concurrent.duration.Duration]] - */ -private[camel] object DurationTypeConverter extends TypeConverterSupport { - - @throws(classOf[TypeConversionException]) - def convertTo[T](valueType: Class[T], exchange: Exchange, value: AnyRef): T = - valueType.cast(try { - val d = Duration(value.toString) - if (valueType.isInstance(d)) d else null - } catch { - case NonFatal(throwable) => throw new TypeConversionException(value, valueType, throwable) - }) -} - -/** - * INTERNAL API - * An endpoint to an [[akka.actor.ActorRef]] - * @param actorPath the String representation of the path to the actor - */ -private[camel] case class ActorEndpointPath private (actorPath: String) { - require(actorPath != null) - require(actorPath.length() > 0) - require(actorPath.startsWith("akka://")) - - def findActorIn(system: ActorSystem): Option[ActorRef] = { - // FIXME #3074 how do we solve this with actorSelection? - val ref = system.actorFor(actorPath) - if (ref.isTerminated) None else Some(ref) - } -} - -/** - * Converts ActorRefs and actorPaths to URI's that point to the actor through the Camel Actor Component. - * Can also be used in the Java API as a helper for custom route builders. the Scala API has an implicit conversion in the camel package to - * directly use `to(actorRef)`. In java you could use `to(CamelPath.toUri(actorRef)`. - * The URI to the actor is exactly the same as the string representation of the ActorPath, except that it can also have optional URI parameters to configure the Consumer Actor. - */ -object CamelPath { - - /** - * Converts the actorRef to a Camel URI (string) which can be used in custom routes. - * The created URI will have no parameters, it is purely the string representation of the actor's path. - * @param actorRef the actorRef - * @return the Camel URI to the actor. - */ - def toUri(actorRef: ActorRef): String = actorRef.path.toString - - /** - * Converts the actorRef to a Camel URI (string) which can be used in custom routes. - * Use this version of toUri when you know that the actorRef points to a Consumer Actor and you would like to - * set autoAck and replyTimeout parameters to non-default values. - * - * @param actorRef the actorRef - * @param autoAck parameter for a Consumer Actor, see [[akka.camel.ConsumerConfig]] - * @param replyTimeout parameter for a Consumer Actor, see [[akka.camel.ConsumerConfig]] - * @return the Camel URI to the Consumer Actor, including the parameters for auto acknowledgement and replyTimeout. - */ - def toUri(actorRef: ActorRef, autoAck: Boolean, replyTimeout: Duration): String = - "%s?autoAck=%s&replyTimeout=%s".format(actorRef.path.toString, autoAck, replyTimeout.toString) -} - -/** - * INTERNAL API - * Companion of `ActorEndpointPath` - */ -private[camel] case object ActorEndpointPath { - - def apply(actorRef: ActorRef): ActorEndpointPath = new ActorEndpointPath(actorRef.path.toString) - - /** - * Creates an [[akka.camel.internal.component.ActorEndpointPath]] from the uri - * Expects the uri in the akka [[akka.actor.ActorPath]] format, i.e 'akka://system/user/someactor'. - * parameters can be optionally added to the actor path to indicate auto-acknowledgement and replyTimeout for a [[akka.camel.Consumer]] actor. - */ - def fromCamelPath(camelPath: String): ActorEndpointPath = camelPath match { - case id if id.startsWith("akka://") => new ActorEndpointPath(id.split('?')(0)) - case _ => - throw new IllegalArgumentException( - "Invalid path: [%s] - should be an actorPath starting with 'akka://', optionally followed by options".format( - camelPath)) - } -} diff --git a/akka-camel/src/main/scala/akka/camel/javaapi/UntypedConsumerActor.scala b/akka-camel/src/main/scala/akka/camel/javaapi/UntypedConsumerActor.scala deleted file mode 100644 index d5fe0ca9de..0000000000 --- a/akka-camel/src/main/scala/akka/camel/javaapi/UntypedConsumerActor.scala +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel.javaapi - -import akka.actor.UntypedActor -import akka.camel._ -import org.apache.camel.ProducerTemplate -import org.apache.camel.impl.DefaultCamelContext - -/** - * Subclass this abstract class to create an MDB-style untyped consumer actor. This - * class is meant to be used from Java. - * - * @deprecated Akka Camel is deprecated since 2.5.0 in favour of 'Alpakka', the Akka Streams based collection of integrations to various endpoints (including Camel). - */ -@Deprecated -abstract class UntypedConsumerActor extends UntypedActor with Consumer { - final def endpointUri: String = getEndpointUri - - /** - * Java API: Returns the Camel endpoint URI to consume messages from. - */ - def getEndpointUri(): String - - /** - * Java API: Returns the [[org.apache.camel.impl.DefaultCamelContext]] - * @return the CamelContext - */ - protected def getCamelContext(): DefaultCamelContext = camelContext - - /** - * Java API: Returns the [[org.apache.camel.ProducerTemplate]] - * @return the ProducerTemplate - */ - protected def getProducerTemplate(): ProducerTemplate = camel.template - - /** - * Java API: Returns the [[akka.camel.Activation]] interface - * that can be used to wait on activation or de-activation of Camel endpoints. - * @return the Activation interface - */ - protected def getActivation(): Activation = camel -} diff --git a/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala b/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala deleted file mode 100644 index fcbfe0dabb..0000000000 --- a/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel.javaapi - -import akka.actor.UntypedActor -import akka.camel._ -import org.apache.camel.{ ProducerTemplate } -import org.apache.camel.impl.DefaultCamelContext - -/** - * Subclass this abstract class to create an untyped producer actor. This class is meant to be used from Java. - * - * @deprecated Akka Camel is deprecated since 2.5.0 in favour of 'Alpakka', the Akka Streams based collection of integrations to various endpoints (including Camel). - */ -@Deprecated -abstract class UntypedProducerActor extends UntypedActor with ProducerSupport { - - /** - * Called before the message is sent to the endpoint specified by getEndpointUri. The original - * message is passed as argument. By default, this method simply returns the argument but may be overridden - * by subclasses. - */ - def onTransformOutgoingMessage(message: AnyRef): AnyRef = message - - /** - * Called before the response message is sent to original sender. The original - * message is passed as argument. By default, this method simply returns the argument but may be overridden - * by subclasses. - */ - def onTransformResponse(message: AnyRef): AnyRef = message - - /** - * Called after a response was received from the endpoint specified by endpointUri. The - * response is passed as argument. By default, this method sends the response back to the original sender - * 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 onRouteResponse(message: AnyRef): Unit = super.routeResponse(message) - - final override def transformOutgoingMessage(msg: Any): AnyRef = onTransformOutgoingMessage(msg.asInstanceOf[AnyRef]) - final override def transformResponse(msg: Any): AnyRef = onTransformResponse(msg.asInstanceOf[AnyRef]) - final override def routeResponse(msg: Any): Unit = onRouteResponse(msg.asInstanceOf[AnyRef]) - - final override def endpointUri: String = getEndpointUri - - final override def oneway: Boolean = isOneway - - /** - * Default implementation of UntypedActor.onReceive - */ - final def onReceive(message: Any): Unit = produce(message) - - /** - * Returns the Camel endpoint URI to produce messages to. - */ - def getEndpointUri(): String - - /** - * If set to false (default), this producer expects a response message from the Camel endpoint. - * If set to true, this producer communicates with the Camel endpoint with an in-only message - * exchange pattern (fire and forget). - */ - def isOneway(): Boolean = super.oneway - - /** - * Returns the CamelContext. - */ - def getCamelContext(): DefaultCamelContext = camel.context - - /** - * Returns the ProducerTemplate. - */ - def getProducerTemplate(): ProducerTemplate = camel.template - - /** - * ''Java API'': Returns the [[akka.camel.Activation]] interface - * that can be used to wait on activation or de-activation of Camel endpoints. - * @return the Activation interface - */ - def getActivation(): Activation = camel -} diff --git a/akka-camel/src/main/scala/akka/package.scala b/akka-camel/src/main/scala/akka/package.scala deleted file mode 100644 index d53f77b108..0000000000 --- a/akka-camel/src/main/scala/akka/package.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka - -import language.implicitConversions - -import org.apache.camel.model.ProcessorDefinition - -package object camel { - - /** - * To allow using Actors with the Camel Route DSL: - * - * {{{ - * from("file://data/input/CamelConsumer").to(actor) - * }}} - */ - implicit def toActorRouteDefinition[T <: ProcessorDefinition[T]](definition: ProcessorDefinition[T]) = - new ActorRouteDefinition(definition) -} diff --git a/akka-camel/src/test/java/akka/camel/ConsumerJavaTest.java b/akka-camel/src/test/java/akka/camel/ConsumerJavaTest.java deleted file mode 100644 index 2597e0a913..0000000000 --- a/akka-camel/src/test/java/akka/camel/ConsumerJavaTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel; - -import akka.testkit.AkkaJUnitActorSystemResource; -import akka.testkit.AkkaSpec; -import akka.testkit.javadsl.EventFilter; -import akka.testkit.javadsl.TestKit; -import org.junit.ClassRule; -import org.scalatest.junit.JUnitSuite; -import akka.actor.ActorSystem; -import akka.actor.Props; -import akka.util.Timeout; -import scala.concurrent.Await; -import scala.concurrent.duration.FiniteDuration; -import scala.concurrent.duration.Duration; -import scala.concurrent.ExecutionContext; -import org.junit.Test; -import java.util.concurrent.TimeUnit; -import static org.junit.Assert.*; - -public class ConsumerJavaTest extends JUnitSuite { - - @ClassRule - public static AkkaJUnitActorSystemResource actorSystemResource = - new AkkaJUnitActorSystemResource("ConsumerJavaTest", AkkaSpec.testConf()); - - private final ActorSystem system = actorSystemResource.getSystem(); - - @Test - public void shouldHandleExceptionThrownByActorAndGenerateCustomResponse() throws Exception { - new TestKit(system) { - { - String result = - new EventFilter(Exception.class, system) - .occurrences(1) - .intercept( - () -> { - FiniteDuration duration = Duration.create(1, TimeUnit.SECONDS); - Timeout timeout = new Timeout(duration); - Camel camel = CamelExtension.get(system); - ExecutionContext executionContext = system.dispatcher(); - try { - Await.result( - camel.activationFutureFor( - system.actorOf( - Props.create(SampleErrorHandlingConsumer.class), - "sample-error-handling-consumer"), - timeout, - executionContext), - duration); - return camel - .template() - .requestBody("direct:error-handler-test-java", "hello", String.class); - } catch (Exception e) { - return e.getMessage(); - } - }); - assertEquals("error: hello", result); - } - }; - } -} diff --git a/akka-camel/src/test/java/akka/camel/CustomRouteTest.java b/akka-camel/src/test/java/akka/camel/CustomRouteTest.java deleted file mode 100644 index 66f5bd7496..0000000000 --- a/akka-camel/src/test/java/akka/camel/CustomRouteTest.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package akka.camel; - -import akka.actor.*; -import akka.camel.internal.component.CamelPath; -import akka.camel.javaapi.UntypedConsumerActor; -import akka.camel.javaapi.UntypedProducerActor; -import akka.testkit.AkkaJUnitActorSystemResource; -import akka.util.Timeout; -import org.junit.*; -import org.scalatest.junit.JUnitSuite; -import scala.concurrent.Await; -import scala.concurrent.ExecutionContext; -import scala.concurrent.duration.Duration; -import scala.concurrent.duration.FiniteDuration; -import org.apache.camel.CamelExecutionException; -import org.apache.camel.Exchange; -import org.apache.camel.Predicate; -import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.component.mock.MockEndpoint; - -import java.util.concurrent.TimeUnit; - -public class CustomRouteTest extends JUnitSuite { - - @Rule - public AkkaJUnitActorSystemResource actorSystemResource = - new AkkaJUnitActorSystemResource("CustomRouteTest"); - - private ActorSystem system = null; - private Camel camel = null; - - public static class MyActor extends AbstractActor { - @Override - public Receive createReceive() { - return receiveBuilder().build(); - } - } - - @Before - public void beforeEach() { - system = actorSystemResource.getSystem(); - camel = (Camel) CamelExtension.get(system); - } - - @Test - public void testCustomProducerRoute() throws Exception { - MockEndpoint mockEndpoint = - camel.context().getEndpoint("mock:mockProducer", MockEndpoint.class); - ActorRef producer = system.actorOf(Props.create(MockEndpointProducer.class), "mockEndpoint"); - camel.context().addRoutes(new CustomRouteBuilder("direct:test", producer)); - camel.template().sendBody("direct:test", "test"); - assertMockEndpoint(mockEndpoint); - system.stop(producer); - } - - @Test - public void testCustomProducerUriRoute() throws Exception { - MockEndpoint mockEndpoint = - camel.context().getEndpoint("mock:mockProducerUri", MockEndpoint.class); - ActorRef producer = - system.actorOf( - Props.create(EndpointProducer.class, "mock:mockProducerUri"), "mockEndpointUri"); - camel.context().addRoutes(new CustomRouteBuilder("direct:test", producer)); - camel.template().sendBody("direct:test", "test"); - assertMockEndpoint(mockEndpoint); - system.stop(producer); - } - - @Test - public void testCustomConsumerRoute() throws Exception { - MockEndpoint mockEndpoint = - camel.context().getEndpoint("mock:mockConsumer", MockEndpoint.class); - FiniteDuration duration = Duration.create(10, TimeUnit.SECONDS); - Timeout timeout = new Timeout(duration); - ExecutionContext executionContext = system.dispatcher(); - ActorRef consumer = - Await.result( - camel.activationFutureFor( - system.actorOf(Props.create(TestConsumer.class), "testConsumer"), - timeout, - executionContext), - duration); - camel.context().addRoutes(new CustomRouteBuilder("direct:testRouteConsumer", consumer)); - camel.template().sendBody("direct:testRouteConsumer", "test"); - assertMockEndpoint(mockEndpoint); - system.stop(consumer); - } - - @Test - public void testCustomAckConsumerRoute() throws Exception { - MockEndpoint mockEndpoint = camel.context().getEndpoint("mock:mockAck", MockEndpoint.class); - FiniteDuration duration = Duration.create(10, TimeUnit.SECONDS); - Timeout timeout = new Timeout(duration); - ExecutionContext executionContext = system.dispatcher(); - ActorRef consumer = - Await.result( - camel.activationFutureFor( - system.actorOf( - Props.create(TestAckConsumer.class, "direct:testConsumerAck", "mock:mockAck"), - "testConsumerAck"), - timeout, - executionContext), - duration); - camel.context().addRoutes(new CustomRouteBuilder("direct:testAck", consumer, false, duration)); - camel.template().sendBody("direct:testAck", "test"); - assertMockEndpoint(mockEndpoint); - system.stop(consumer); - } - - @Test - public void testCustomAckConsumerRouteFromUri() throws Exception { - MockEndpoint mockEndpoint = camel.context().getEndpoint("mock:mockAckUri", MockEndpoint.class); - ExecutionContext executionContext = system.dispatcher(); - FiniteDuration duration = Duration.create(10, TimeUnit.SECONDS); - Timeout timeout = new Timeout(duration); - ActorRef consumer = - Await.result( - camel.activationFutureFor( - system.actorOf( - Props.create( - TestAckConsumer.class, "direct:testConsumerAckFromUri", "mock:mockAckUri"), - "testConsumerAckUri"), - timeout, - executionContext), - duration); - camel - .context() - .addRoutes( - new CustomRouteBuilder( - "direct:testAckFromUri", - "akka://CustomRouteTest/user/testConsumerAckUri?autoAck=false")); - camel.template().sendBody("direct:testAckFromUri", "test"); - assertMockEndpoint(mockEndpoint); - system.stop(consumer); - } - - @Test(expected = CamelExecutionException.class) - public void testCustomTimeoutConsumerRoute() throws Exception { - FiniteDuration duration = Duration.create(10, TimeUnit.SECONDS); - Timeout timeout = new Timeout(duration); - ExecutionContext executionContext = system.dispatcher(); - ActorRef consumer = - Await.result( - camel.activationFutureFor( - system.actorOf( - Props.create( - TestAckConsumer.class, - "direct:testConsumerException", - "mock:mockException"), - "testConsumerException"), - timeout, - executionContext), - duration); - camel - .context() - .addRoutes( - new CustomRouteBuilder( - "direct:testException", consumer, false, Duration.create(0, TimeUnit.SECONDS))); - camel.template().sendBody("direct:testException", "test"); - } - - private void assertMockEndpoint(MockEndpoint mockEndpoint) throws InterruptedException { - mockEndpoint.expectedMessageCount(1); - mockEndpoint.expectedMessagesMatches( - new Predicate() { - @Override - public boolean matches(Exchange exchange) { - return exchange.getIn().getBody().equals("test"); - } - }); - mockEndpoint.assertIsSatisfied(); - } - - public static class CustomRouteBuilder extends RouteBuilder { - private final String uri; - private final String fromUri; - - public CustomRouteBuilder(String from, String to) { - fromUri = from; - uri = to; - } - - public CustomRouteBuilder(String from, ActorRef actor) { - fromUri = from; - uri = CamelPath.toUri(actor); - } - - public CustomRouteBuilder(String from, ActorRef actor, boolean autoAck, Duration replyTimeout) { - fromUri = from; - uri = CamelPath.toUri(actor, autoAck, replyTimeout); - } - - @Override - public void configure() throws Exception { - from(fromUri).to(uri); - } - } - - public static class TestConsumer extends UntypedConsumerActor { - @Override - public String getEndpointUri() { - return "direct:testconsumer"; - } - - @Override - public void onReceive(Object message) { - this.getProducerTemplate().sendBody("mock:mockConsumer", "test"); - } - } - - public static class EndpointProducer extends UntypedProducerActor { - private final String uri; - - public EndpointProducer(String uri) { - this.uri = uri; - } - - public String getEndpointUri() { - return uri; - } - - @Override - public boolean isOneway() { - return true; - } - } - - public static class MockEndpointProducer extends UntypedProducerActor { - public String getEndpointUri() { - return "mock:mockProducer"; - } - - @Override - public boolean isOneway() { - return true; - } - } - - public static class TestAckConsumer extends UntypedConsumerActor { - private final String myuri; - private final String to; - - public TestAckConsumer(String uri, String to) { - myuri = uri; - this.to = to; - } - - @Override - public String getEndpointUri() { - return myuri; - } - - @Override - public void onReceive(Object message) { - this.getProducerTemplate().sendBody(to, "test"); - getSender().tell(Ack.getInstance(), getSelf()); - } - } -} diff --git a/akka-camel/src/test/java/akka/camel/MessageJavaTest.java b/akka-camel/src/test/java/akka/camel/MessageJavaTest.java deleted file mode 100644 index 5e3204c0f5..0000000000 --- a/akka-camel/src/test/java/akka/camel/MessageJavaTest.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel; - -import akka.actor.ActorSystem; -import akka.dispatch.Mapper; -import akka.testkit.AkkaJUnitActorSystemResource; -import org.apache.camel.NoTypeConversionAvailableException; -import org.apache.camel.converter.stream.InputStreamCache; -import org.junit.ClassRule; -import org.junit.Test; -import org.scalatest.junit.JUnitSuite; - -import java.io.InputStream; -import java.util.*; - -import static org.junit.Assert.assertEquals; - -/** */ -public class MessageJavaTest extends JUnitSuite { - private Map empty = new HashMap(); - - @ClassRule - public static AkkaJUnitActorSystemResource actorSystemResource = - new AkkaJUnitActorSystemResource("MessageJavaTest"); - - private final ActorSystem system = actorSystemResource.getSystem(); - private Camel camel = (Camel) CamelExtension.get(system); - - 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", message("1.4", empty).getBodyAs(String.class, camel.context())); - } - - @Test(expected = NoTypeConversionAvailableException.class) - public void shouldThrowExceptionWhenConvertingDoubleBodyToInputStream() { - message(1.4).getBodyAs(InputStream.class, camel.context()); - } - - @Test - public void shouldConvertDoubleHeaderToString() { - CamelMessage message = message("test", createMap("test", 1.4)); - assertEquals("1.4", message.getHeaderAs("test", String.class, camel.context())); - } - - @Test - public void shouldReturnSubsetOfHeaders() { - CamelMessage message = message("test", createMap("A", "1", "B", "2")); - assertEquals(createMap("B", "2"), message.getHeaders(createSet("B"))); - } - - @Test(expected = UnsupportedOperationException.class) - public void shouldReturnSubsetOfHeadersUnmodifiable() { - CamelMessage message = message("test", createMap("A", "1", "B", "2")); - message.getHeaders(createSet("B")).put("x", "y"); - } - - @Test - public void shouldReturnAllHeaders() { - CamelMessage message = message("test", createMap("A", "1", "B", "2")); - assertEquals(createMap("A", "1", "B", "2"), message.getHeaders()); - } - - @Test(expected = UnsupportedOperationException.class) - public void shouldReturnAllHeadersUnmodifiable() { - CamelMessage message = message("test", createMap("A", "1", "B", "2")); - message.getHeaders().put("x", "y"); - } - - @Test - public void shouldTransformBodyAndPreserveHeaders() { - assertEquals( - message("ab", createMap("A", "1")), - message("a", createMap("A", "1")).mapBody(new TestTransformer())); - } - - @Test - public void shouldConvertBodyAndPreserveHeaders() { - assertEquals( - message("1.4", createMap("A", "1")), - message(1.4, createMap("A", "1")).withBodyAs(String.class, camel.context())); - } - - @Test - public void shouldSetBodyAndPreserveHeaders() { - assertEquals( - message("test2", createMap("A", "1")), - message("test1", createMap("A", "1")).withBody("test2")); - } - - @Test - public void shouldSetHeadersAndPreserveBody() { - assertEquals( - message("test1", createMap("C", "3")), - message("test1", createMap("A", "1")).withHeaders(createMap("C", "3"))); - } - - @Test - public void shouldBeAbleToReReadStreamCacheBody() throws Exception { - CamelMessage msg = new CamelMessage(new InputStreamCache("test1".getBytes("utf-8")), empty); - assertEquals("test1", msg.getBodyAs(String.class, camel.context())); - // re-read - assertEquals("test1", msg.getBodyAs(String.class, camel.context())); - } - - private static Set createSet(String... entries) { - HashSet set = new HashSet(); - set.addAll(Arrays.asList(entries)); - return set; - } - - private static Map createMap(Object... pairs) { - HashMap map = new HashMap(); - for (int i = 0; i < pairs.length; i += 2) { - map.put((String) pairs[i], pairs[i + 1]); - } - return map; - } - - private static class TestTransformer extends Mapper { - @Override - public String apply(String param) { - return param + "b"; - } - } -} diff --git a/akka-camel/src/test/java/akka/camel/SampleErrorHandlingConsumer.java b/akka-camel/src/test/java/akka/camel/SampleErrorHandlingConsumer.java deleted file mode 100644 index 495fa13fd7..0000000000 --- a/akka-camel/src/test/java/akka/camel/SampleErrorHandlingConsumer.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel; - -import akka.actor.Status; -import akka.camel.javaapi.UntypedConsumerActor; -import akka.dispatch.Mapper; -import scala.concurrent.duration.Duration; -import org.apache.camel.builder.Builder; -import org.apache.camel.model.ProcessorDefinition; -import org.apache.camel.model.RouteDefinition; -import scala.Option; -import scala.concurrent.duration.FiniteDuration; - -/** */ -public class SampleErrorHandlingConsumer extends UntypedConsumerActor { - private static Mapper> mapper = - new Mapper>() { - public ProcessorDefinition apply(RouteDefinition rd) { - return rd.onException(Exception.class) - .handled(true) - .transform(Builder.exceptionMessage()) - .end(); - } - }; - - public String getEndpointUri() { - return "direct:error-handler-test-java"; - } - - @Override - public Mapper> onRouteDefinition() { - return mapper; - } - - @Override - public FiniteDuration replyTimeout() { - return Duration.create(1, "second"); - } - - public void onReceive(Object message) throws Exception { - CamelMessage msg = (CamelMessage) message; - String body = msg.getBodyAs(String.class, this.getCamelContext()); - throw new Exception(String.format("error: %s", body)); - } - - @Override - public void preRestart(Throwable reason, Option message) { - getSender().tell(new Status.Failure(reason), getSelf()); - } -} diff --git a/akka-camel/src/test/java/akka/camel/SampleUntypedConsumer.java b/akka-camel/src/test/java/akka/camel/SampleUntypedConsumer.java deleted file mode 100644 index bebceced0f..0000000000 --- a/akka-camel/src/test/java/akka/camel/SampleUntypedConsumer.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel; - -import akka.camel.javaapi.UntypedConsumerActor; - -/** */ -public class SampleUntypedConsumer extends UntypedConsumerActor { - - public String getEndpointUri() { - return "direct:test-untyped-consumer"; - } - - public void onReceive(Object message) { - 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), getSelf()); - } -} diff --git a/akka-camel/src/test/java/akka/camel/SampleUntypedForwardingProducer.java b/akka-camel/src/test/java/akka/camel/SampleUntypedForwardingProducer.java deleted file mode 100644 index e9e41dae26..0000000000 --- a/akka-camel/src/test/java/akka/camel/SampleUntypedForwardingProducer.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel; - -import akka.camel.javaapi.UntypedProducerActor; -/** */ -public class SampleUntypedForwardingProducer extends UntypedProducerActor { - - public String getEndpointUri() { - return "direct:producer-test-1"; - } - - @Override - public void onRouteResponse(Object message) { - 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/java/akka/camel/SampleUntypedReplyingProducer.java b/akka-camel/src/test/java/akka/camel/SampleUntypedReplyingProducer.java deleted file mode 100644 index 45a962caf4..0000000000 --- a/akka-camel/src/test/java/akka/camel/SampleUntypedReplyingProducer.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel; - -import akka.camel.javaapi.UntypedProducerActor; - -/** */ -public class SampleUntypedReplyingProducer extends UntypedProducerActor { - - public String getEndpointUri() { - return "direct:producer-test-1"; - } -} diff --git a/akka-camel/src/test/resources/logback-test.xml b/akka-camel/src/test/resources/logback-test.xml deleted file mode 100644 index 1b571cf387..0000000000 --- a/akka-camel/src/test/resources/logback-test.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - %date{ISO8601} %-5level %logger %X{akkaSource} %X{sourceThread} - %msg%n - - - - - target/akka-camel.log - true - - %date{ISO8601} %-5level %logger %X{akkaSource} %X{sourceThread} - %msg%n - - - - - - - - diff --git a/akka-camel/src/test/scala/akka/camel/ActivationIntegrationTest.scala b/akka-camel/src/test/scala/akka/camel/ActivationIntegrationTest.scala deleted file mode 100644 index 0969ea0e23..0000000000 --- a/akka-camel/src/test/scala/akka/camel/ActivationIntegrationTest.scala +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import language.postfixOps - -import org.scalatest.Matchers -import scala.concurrent.duration._ -import org.apache.camel.ProducerTemplate -import akka.actor._ -import TestSupport._ -import org.scalatest.WordSpec -import akka.testkit.TestLatch -import scala.concurrent.Await -import java.util.concurrent.TimeoutException -import akka.util.Timeout - -class ActivationIntegrationTest extends WordSpec with Matchers with SharedCamelSystem { - val timeoutDuration = 10 seconds - implicit val timeout = Timeout(timeoutDuration) - def template: ProducerTemplate = camel.template - import system.dispatcher - - "ActivationAware should be notified when endpoint is activated" in { - val latch = new TestLatch(0) - val actor = system.actorOf(Props(new TestConsumer("direct:actor-1", latch)), "act-direct-actor-1") - Await.result(camel.activationFutureFor(actor), 10 seconds) should ===(actor) - - template.requestBody("direct:actor-1", "test") should ===("received test") - } - - "ActivationAware should be notified when endpoint is de-activated" in { - val latch = TestLatch(1) - val actor = start(new Consumer { - def endpointUri = "direct:a3" - def receive = { case _ => {} } - - override def postStop(): Unit = { - super.postStop() - latch.countDown() - } - }, name = "direct-a3") - Await.result(camel.activationFutureFor(actor), timeoutDuration) - - system.stop(actor) - Await.result(camel.deactivationFutureFor(actor), timeoutDuration) - Await.ready(latch, timeoutDuration) - } - - "ActivationAware must time out when waiting for endpoint de-activation for too long" in { - val latch = new TestLatch(0) - val actor = start(new TestConsumer("direct:a5", latch), name = "direct-a5") - Await.result(camel.activationFutureFor(actor), timeoutDuration) - intercept[TimeoutException] { Await.result(camel.deactivationFutureFor(actor), 1 millis) } - } - - "activationFutureFor must fail if notification timeout is too short and activation is not complete yet" in { - val latch = new TestLatch(1) - val actor = system.actorOf(Props(new TestConsumer("direct:actor-4", latch)), "direct-actor-4") - intercept[TimeoutException] { Await.result(camel.activationFutureFor(actor), 1 millis) } - latch.countDown() - // after the latch is removed, complete the wait for completion so this test does not later on - // print errors because of the registerConsumer timing out. - Await.result(camel.activationFutureFor(actor), timeoutDuration) - } - - class TestConsumer(uri: String, latch: TestLatch) extends Consumer { - def endpointUri = uri - - override def preStart(): Unit = { - Await.ready(latch, 60 seconds) - super.preStart() - } - - override def receive = { - case msg: CamelMessage => sender() ! "received " + msg.body - } - } - -} diff --git a/akka-camel/src/test/scala/akka/camel/CamelConfigSpec.scala b/akka-camel/src/test/scala/akka/camel/CamelConfigSpec.scala deleted file mode 100644 index e34b6bf3df..0000000000 --- a/akka-camel/src/test/scala/akka/camel/CamelConfigSpec.scala +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel -import org.scalatest.Matchers -import org.scalatest.WordSpec -import akka.actor.ActorSystem -import akka.testkit.TestKit -import akka.util.Helpers.ConfigOps - -class CamelConfigSpec extends WordSpec with Matchers { - - val (settings, config) = { - val system = ActorSystem("CamelConfigSpec") - val result = (CamelExtension(system).settings, system.settings.config) - TestKit.shutdownActorSystem(system) - result - } - "CamelConfigSpec" must { - "have correct activationTimeout config" in { - settings.ActivationTimeout should ===(config.getMillisDuration("akka.camel.consumer.activation-timeout")) - } - - "have correct autoAck config" in { - settings.AutoAck should ===(config.getBoolean("akka.camel.consumer.auto-ack")) - } - - "have correct replyTimeout config" in { - settings.ReplyTimeout should ===(config.getMillisDuration("akka.camel.consumer.reply-timeout")) - } - - "have correct streamingCache config" in { - settings.StreamingCache should ===(config.getBoolean("akka.camel.streamingCache")) - } - - "have correct jmxStatistics config" in { - settings.JmxStatistics should ===(config.getBoolean("akka.camel.jmx")) - } - - "have correct body conversions config" in { - val conversions = config.getConfig("akka.camel.conversions") - - conversions.getString("file") should ===("java.io.InputStream") - conversions.entrySet.size should ===(1) - } - - "have correct Context Provider" in { - settings.ContextProvider.isInstanceOf[DefaultContextProvider] should ===(true) - } - } -} diff --git a/akka-camel/src/test/scala/akka/camel/CamelExchangeAdapterTest.scala b/akka-camel/src/test/scala/akka/camel/CamelExchangeAdapterTest.scala deleted file mode 100644 index d14c859942..0000000000 --- a/akka-camel/src/test/scala/akka/camel/CamelExchangeAdapterTest.scala +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import akka.camel.TestSupport.SharedCamelSystem -import akka.camel.internal.CamelExchangeAdapter -import org.apache.camel.impl.DefaultExchange -import org.apache.camel.{ Exchange, ExchangePattern } -import org.scalatest.FunSuite - -class CamelExchangeAdapterTest extends FunSuite with SharedCamelSystem { - - test("mustSetInMessageFromRequestMessage") { - val e1 = sampleInOnly - exchangeToAdapter(e1).setRequest(CamelMessage("x", Map.empty)) - assert(e1.getIn.getBody === "x") - val e2 = sampleInOut - exchangeToAdapter(e2).setRequest(CamelMessage("y", Map.empty)) - assert(e2.getIn.getBody === "y") - } - - test("mustSetOutMessageFromResponseMessage") { - val e1 = sampleInOut - exchangeToAdapter(e1).setResponse(CamelMessage("y", Map.empty)) - assert(e1.getOut.getBody === "y") - } - - test("mustSetInMessageFromResponseMessage") { - val e1 = sampleInOnly - exchangeToAdapter(e1).setResponse(CamelMessage("x", Map.empty)) - assert(e1.getIn.getBody === "x") - } - - test("mustSetExceptionFromFailureMessage") { - val e1 = sampleInOnly - exchangeToAdapter(e1).setFailure(FailureResult(new Exception("test1"))) - assert(e1.getException.getMessage === "test1") - val e2 = sampleInOut - exchangeToAdapter(e2).setFailure(FailureResult(new Exception("test2"))) - assert(e2.getException.getMessage === "test2") - } - - test("mustCreateRequestMessageFromInMessage") { - val m = exchangeToAdapter(sampleInOnly).toRequestMessage - assert(m === CamelMessage("test-in", Map("key-in" -> "val-in"))) - } - - test("mustCreateResponseMessageFromInMessage") { - val m = exchangeToAdapter(sampleInOnly).toResponseMessage - assert(m === CamelMessage("test-in", Map("key-in" -> "val-in"))) - } - - test("mustCreateResponseMessageFromOutMessage") { - val m = exchangeToAdapter(sampleInOut).toResponseMessage - assert(m === CamelMessage("test-out", Map("key-out" -> "val-out"))) - } - - test("mustCreateFailureMessageFromExceptionAndInMessage") { - val e1 = sampleInOnly - e1.setException(new Exception("test1")) - val a1 = exchangeToAdapter(e1) - assert(a1.toAkkaCamelException.getMessage === "test1") - assert(a1.toAkkaCamelException.headers("key-in") === "val-in") - assert(a1.toFailureMessage.cause.getMessage === "test1") - assert(a1.toFailureMessage.headers("key-in") === "val-in") - } - - test("mustCreateFailureMessageFromExceptionAndOutMessage") { - val e1 = sampleInOut - e1.setException(new Exception("test2")) - val a1 = exchangeToAdapter(e1) - assert(a1.toAkkaCamelException.getMessage === "test2") - assert(a1.toAkkaCamelException.headers("key-out") === "val-out") - assert(a1.toFailureMessage.cause.getMessage === "test2") - assert(a1.toFailureMessage.headers("key-out") === "val-out") - } - - test("mustCreateRequestMessageFromInMessageWithAdditionalHeader") { - val m = exchangeToAdapter(sampleInOnly).toRequestMessage(Map("x" -> "y")) - assert(m === CamelMessage("test-in", Map("key-in" -> "val-in", "x" -> "y"))) - } - - test("mustCreateResponseMessageFromInMessageWithAdditionalHeader") { - val m = exchangeToAdapter(sampleInOnly).toResponseMessage(Map("x" -> "y")) - assert(m === CamelMessage("test-in", Map("key-in" -> "val-in", "x" -> "y"))) - } - - test("mustCreateResponseMessageFromOutMessageWithAdditionalHeader") { - val m = exchangeToAdapter(sampleInOut).toResponseMessage(Map("x" -> "y")) - assert(m === CamelMessage("test-out", Map("key-out" -> "val-out", "x" -> "y"))) - } - - test("mustCreateFailureMessageFromExceptionAndInMessageWithAdditionalHeader") { - val e1 = sampleInOnly - e1.setException(new Exception("test1")) - val a1 = exchangeToAdapter(e1) - assert(a1.toAkkaCamelException.getMessage === "test1") - val headers = a1.toAkkaCamelException(Map("x" -> "y")).headers - assert(headers("key-in") === "val-in") - assert(headers("x") === "y") - - val a2 = exchangeToAdapter(e1) - assert(a2.toFailureMessage.cause.getMessage === "test1") - val failureHeaders = a2.toFailureResult(Map("x" -> "y")).headers - assert(failureHeaders("key-in") === "val-in") - assert(failureHeaders("x") === "y") - - } - - test("mustCreateFailureMessageFromExceptionAndOutMessageWithAdditionalHeader") { - val e1 = sampleInOut - e1.setException(new Exception("test2")) - val a1 = exchangeToAdapter(e1) - assert(a1.toAkkaCamelException.getMessage === "test2") - val headers = a1.toAkkaCamelException(Map("x" -> "y")).headers - assert(headers("key-out") === "val-out") - assert(headers("x") === "y") - - val a2 = exchangeToAdapter(e1) - assert(a2.toFailureMessage.cause.getMessage === "test2") - val failureHeaders = a2.toFailureResult(Map("x" -> "y")).headers - assert(failureHeaders("key-out") === "val-out") - assert(failureHeaders("x") === "y") - } - - private def sampleInOnly = sampleExchange(ExchangePattern.InOnly) - private def sampleInOut = sampleExchange(ExchangePattern.InOut) - - private def sampleExchange(pattern: ExchangePattern) = { - val exchange = new DefaultExchange(camel.context) - exchange.getIn.setBody("test-in") - exchange.getOut.setBody("test-out") - exchange.getIn.setHeader("key-in", "val-in") - exchange.getOut.setHeader("key-out", "val-out") - exchange.setPattern(pattern) - exchange - } - - private def exchangeToAdapter(e: Exchange) = new CamelExchangeAdapter(e) -} diff --git a/akka-camel/src/test/scala/akka/camel/CamelMessageTest.scala b/akka-camel/src/test/scala/akka/camel/CamelMessageTest.scala deleted file mode 100644 index 823eec24ed..0000000000 --- a/akka-camel/src/test/scala/akka/camel/CamelMessageTest.scala +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import java.net.URL -import javax.activation.DataHandler - -import org.apache.camel.impl.{ DefaultExchange, DefaultMessage } -import akka.camel.TestSupport.SharedCamelSystem -import org.scalatest.Matchers -import org.scalatest.WordSpecLike - -//TODO merge it with MessageScalaTest -class CamelMessageTest extends Matchers with WordSpecLike with SharedCamelSystem { - - "CamelMessage copyContent" must { - "create a new CamelMessage with additional headers, attachments and new body" in { - val attachment = new DataHandler(new URL("https://foo.bar")) - val message = new DefaultMessage - message.setBody("test") - message.setHeader("foo", "bar") - message.addAttachment("foo", attachment) - message.setExchange(new DefaultExchange(camel.context)) - - val attachmentToAdd = new DataHandler(new URL("https://another.url")) - CamelMessage.copyContent(new CamelMessage("body", Map("key" -> "baz"), Map("key" -> attachmentToAdd)), message) - - assert(message.getBody === "body") - assert(message.getHeader("foo") === "bar") - assert(message.getHeader("key") === "baz") - assert(message.getAttachment("key") === attachmentToAdd) - assert(message.getAttachment("foo") === attachment) - } - } -} diff --git a/akka-camel/src/test/scala/akka/camel/ConcurrentActivationTest.scala b/akka-camel/src/test/scala/akka/camel/ConcurrentActivationTest.scala deleted file mode 100644 index 2cc3fe3d5d..0000000000 --- a/akka-camel/src/test/scala/akka/camel/ConcurrentActivationTest.scala +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import org.scalatest.WordSpec -import org.scalatest.Matchers -import scala.concurrent.{ Await, Future, Promise } -import scala.collection.immutable -import akka.camel.TestSupport.NonSharedCamelSystem -import akka.actor.{ Actor, ActorRef, Props } -import akka.routing.BroadcastGroup -import scala.concurrent.duration._ -import akka.testkit._ -import akka.util.Timeout -import org.apache.camel.model.RouteDefinition -import org.apache.camel.builder.Builder -import akka.actor.ActorLogging - -/** - * A test to concurrently register and de-register consumer and producer endpoints - */ -class ConcurrentActivationTest extends WordSpec with Matchers with NonSharedCamelSystem { - - "Activation" must { - "support concurrent registrations and de-registrations" in { - implicit val ec = system.dispatcher - val number = 10 - val eventFilter = EventFilter.warning(pattern = "received dead letter from .*producerRegistrar.*") - system.eventStream.publish(TestEvent.Mute(eventFilter)) - try { - // A ConsumerBroadcast creates 'number' amount of ConsumerRegistrars, which will register 'number' amount of endpoints, - // in total number*number endpoints, activating and deactivating every endpoint. - // a promise to the list of registrars, which have a list of actorRefs each. A tuple of a list of activated refs and a list of deactivated refs - val promiseRegistrarLists = Promise[(Future[List[List[ActorRef]]], Future[List[List[ActorRef]]])]() - // future to all the futures of activation and deactivation - val futureRegistrarLists = promiseRegistrarLists.future - - val ref = system.actorOf(Props(classOf[ConsumerBroadcast], promiseRegistrarLists), name = "broadcaster") - // create the registrars - ref ! CreateRegistrars(number) - // send a broadcast to all registrars, so that number * number messages are sent - // every Register registers a consumer and a producer - (1 to number).map(i => ref ! RegisterConsumersAndProducers("direct:concurrent-")) - // de-register all consumers and producers - ref ! DeRegisterConsumersAndProducers() - - val promiseAllRefs = Promise[(List[ActorRef], List[ActorRef])]() - val allRefsFuture = promiseAllRefs.future - // map over all futures, put all futures in one list of activated and deactivated actor refs. - futureRegistrarLists.map { - case (futureActivations, futureDeactivations) => - futureActivations.zip(futureDeactivations).map { - case (activations, deactivations) => - promiseAllRefs.success((activations.flatten, deactivations.flatten)) - } - } - val (activations, deactivations) = Await.result(allRefsFuture, 10.seconds.dilated) - // should be the size of the activated activated producers and consumers - activations.size should ===(2 * number * number) - // should be the size of the activated activated producers and consumers - deactivations.size should ===(2 * number * number) - def partitionNames(refs: immutable.Seq[ActorRef]) = - refs.map(_.path.name).partition(_.startsWith("concurrent-test-echo-consumer")) - def assertContainsSameElements(lists: (Seq[_], Seq[_])): Unit = { - val (a, b) = lists - a.intersect(b).size should ===(a.size) - } - val (activatedConsumerNames, activatedProducerNames) = partitionNames(activations) - val (deactivatedConsumerNames, deactivatedProducerNames) = partitionNames(deactivations) - assertContainsSameElements(activatedConsumerNames -> deactivatedConsumerNames) - assertContainsSameElements(activatedProducerNames -> deactivatedProducerNames) - } finally { - system.eventStream.publish(TestEvent.UnMute(eventFilter)) - } - } - } -} - -class ConsumerBroadcast(promise: Promise[(Future[List[List[ActorRef]]], Future[List[List[ActorRef]]])]) extends Actor { - private var broadcaster: Option[ActorRef] = None - private implicit val ec = context.dispatcher - def receive = { - case CreateRegistrars(number) => - var allActivationFutures = List[Future[List[ActorRef]]]() - var allDeactivationFutures = List[Future[List[ActorRef]]]() - - val routeePaths = (1 to number).map { i => - val activationListPromise = Promise[List[ActorRef]]() - val deactivationListPromise = Promise[List[ActorRef]]() - val activationListFuture = activationListPromise.future - val deactivationListFuture = deactivationListPromise.future - - allActivationFutures = allActivationFutures :+ activationListFuture - allDeactivationFutures = allDeactivationFutures :+ deactivationListFuture - val routee = - context.actorOf( - Props(classOf[Registrar], i, number, activationListPromise, deactivationListPromise), - "registrar-" + i) - routee.path.toString - } - promise.success(Future.sequence(allActivationFutures) -> Future.sequence(allDeactivationFutures)) - - broadcaster = Some(context.actorOf(BroadcastGroup(routeePaths).props(), "registrarRouter")) - case reg: Any => - broadcaster.foreach(_.forward(reg)) - } -} - -final case class CreateRegistrars(number: Int) -final case class RegisterConsumersAndProducers(endpointUri: String) -final case class DeRegisterConsumersAndProducers() -final case class Activations() -final case class DeActivations() - -class Registrar( - val start: Int, - val number: Int, - activationsPromise: Promise[List[ActorRef]], - deActivationsPromise: Promise[List[ActorRef]]) - extends Actor - with ActorLogging { - private var actorRefs = Set[ActorRef]() - private var activations = Set[Future[ActorRef]]() - private var deActivations = Set[Future[ActorRef]]() - private var index = 0 - private val camel = CamelExtension(context.system) - private implicit val ec = context.dispatcher - private implicit val timeout = Timeout(10.seconds.dilated(context.system)) - - def receive = { - case reg: RegisterConsumersAndProducers => - val i = index - val endpoint = reg.endpointUri + start + "-" + i - add(new EchoConsumer(endpoint), "concurrent-test-echo-consumer-" + start + "-" + i) - add(new TestProducer(endpoint), "concurrent-test-producer-" + start + "-" + i) - index = index + 1 - if (activations.size == number * 2) { - Future.sequence(activations.toList).map(activationsPromise.success) - } - case reg: DeRegisterConsumersAndProducers => - actorRefs.foreach { aref => - context.stop(aref) - val result = camel.deactivationFutureFor(aref) - result.failed.foreach { e => - log.error("deactivationFutureFor {} failed: {}", aref, e.getMessage) - } - deActivations += result - if (deActivations.size == number * 2) { - Future.sequence(deActivations.toList).map(deActivationsPromise.success) - } - } - } - - def add(actor: => Actor, name: String): Unit = { - val ref = context.actorOf(Props(actor), name) - actorRefs = actorRefs + ref - val result = camel.activationFutureFor(ref) - result.failed.foreach { e => - log.error("activationFutureFor {} failed: {}", ref, e.getMessage) - } - activations += result - } -} - -class EchoConsumer(endpoint: String) extends Actor with Consumer { - - def endpointUri = endpoint - - def receive = { - case msg: CamelMessage => sender() ! msg - } - - /** - * Returns the route definition handler for creating a custom route to this consumer. - * By default it returns an identity function, override this method to - * return a custom route definition handler. - */ - override def onRouteDefinition = - (rd: RouteDefinition) => rd.onException(classOf[Exception]).handled(true).transform(Builder.exceptionMessage).end -} - -class TestProducer(uri: String) extends Actor with Producer { - def endpointUri = uri -} diff --git a/akka-camel/src/test/scala/akka/camel/ConsumerIntegrationTest.scala b/akka-camel/src/test/scala/akka/camel/ConsumerIntegrationTest.scala deleted file mode 100644 index 5bde3e862c..0000000000 --- a/akka-camel/src/test/scala/akka/camel/ConsumerIntegrationTest.scala +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import language.postfixOps - -import akka.actor._ -import org.scalatest.Matchers -import org.scalatest.WordSpec -import akka.camel.TestSupport._ -import org.apache.camel.model.{ RouteDefinition } -import org.apache.camel.builder.Builder -import org.apache.camel.{ CamelExecutionException, FailedToCreateRouteException } -import java.util.concurrent.{ ExecutionException, TimeUnit, TimeoutException } -import akka.actor.Status.Failure -import scala.concurrent.duration._ -import scala.concurrent.{ Await, ExecutionContext } -import akka.testkit._ -import akka.util.Timeout - -class ConsumerIntegrationTest extends WordSpec with Matchers with NonSharedCamelSystem { - "ConsumerIntegrationTest" must { - val defaultTimeoutDuration = 10 seconds - implicit val defaultTimeout = Timeout(defaultTimeoutDuration) - implicit def ec: ExecutionContext = system.dispatcher - - "Consumer must throw FailedToCreateRouteException, while awaiting activation, if endpoint is invalid" in { - filterEvents(EventFilter[FailedToCreateRouteException](pattern = "failed to activate.*", occurrences = 1)) { - val actorRef = system.actorOf(Props(new TestActor(uri = "some invalid uri")), "invalidActor") - intercept[FailedToCreateRouteException] { - Await.result(camel.activationFutureFor(actorRef), defaultTimeoutDuration) - } - } - } - - "Consumer must support in-out messaging" in { - start(new Consumer { - def endpointUri = "direct:a1" - def receive = { - case m: CamelMessage => sender() ! "received " + m.bodyAs[String] - } - }, name = "direct-a1") - camel.sendTo("direct:a1", msg = "some message") should ===("received some message") - } - - "Consumer must time-out if consumer is slow" taggedAs TimingTest in { - val SHORT_TIMEOUT = 10 millis - val LONG_WAIT = 1 second - - val ref = start(new Consumer { - override def replyTimeout = SHORT_TIMEOUT - def endpointUri = "direct:a3" - def receive = { case _ => { Thread.sleep(LONG_WAIT.toMillis); sender() ! "done" } } - }, name = "ignore-this-deadletter-timeout-consumer-reply") - - intercept[CamelExecutionException] { - camel.sendTo("direct:a3", msg = "some msg 3") - }.getCause.getClass should ===(classOf[TimeoutException]) - - stop(ref) - } - - "Consumer must process messages even after actor restart" in { - val restarted = TestLatch() - val consumer = start(new Consumer { - def endpointUri = "direct:a2" - - def receive = { - case "throw" => throw new TestException("") - case m: CamelMessage => sender() ! "received " + m.bodyAs[String] - } - - override def postRestart(reason: Throwable): Unit = { - restarted.countDown() - } - }, "direct-a2") - filterEvents(EventFilter[TestException](occurrences = 1)) { - consumer ! "throw" - Await.ready(restarted, defaultTimeoutDuration) - - camel.sendTo("direct:a2", msg = "xyz") should ===("received xyz") - } - stop(consumer) - } - - "Consumer must unregister itself when stopped" in { - val consumer = start(new TestActor(), name = "test-actor-unregister") - Await.result(camel.activationFutureFor(consumer), defaultTimeoutDuration) - - camel.routeCount should be > (0) - - system.stop(consumer) - Await.result(camel.deactivationFutureFor(consumer), defaultTimeoutDuration) - - camel.routeCount should ===(0) - } - - "Consumer must register on uri passed in through constructor" in { - val consumer = start(new TestActor("direct://test"), name = "direct-test") - Await.result(camel.activationFutureFor(consumer), defaultTimeoutDuration) - - camel.routeCount should be > (0) - camel.routes.get(0).getEndpoint.getEndpointUri should ===("direct://test") - system.stop(consumer) - Await.result(camel.deactivationFutureFor(consumer), defaultTimeoutDuration) - camel.routeCount should ===(0) - stop(consumer) - } - - "Error passing consumer supports error handling through route modification" in { - val ref = start(new ErrorThrowingConsumer("direct:error-handler-test") { - override def onRouteDefinition = (rd: RouteDefinition) => { - rd.onException(classOf[TestException]).handled(true).transform(Builder.exceptionMessage).end - } - }, name = "direct-error-handler-test") - filterEvents(EventFilter[TestException](occurrences = 1)) { - camel.sendTo("direct:error-handler-test", msg = "hello") should ===("error: hello") - } - stop(ref) - } - - "Error passing consumer supports redelivery through route modification" in { - val ref = start(new FailingOnceConsumer("direct:failing-once-consumer") { - override def onRouteDefinition = (rd: RouteDefinition) => { - rd.onException(classOf[TestException]).redeliveryDelay(0L).maximumRedeliveries(1).end - } - }, name = "direct-failing-once-consumer") - filterEvents(EventFilter[TestException](occurrences = 1)) { - camel.sendTo("direct:failing-once-consumer", msg = "hello") should ===("accepted: hello") - } - stop(ref) - } - - "Consumer supports manual Ack" in { - val ref = start(new ManualAckConsumer() { - def endpointUri = "direct:manual-ack" - def receive = { case _ => sender() ! Ack } - }, name = "direct-manual-ack-1") - camel.template - .asyncSendBody("direct:manual-ack", "some message") - .get(defaultTimeoutDuration.toSeconds, TimeUnit.SECONDS) should ===(null) //should not timeout - stop(ref) - } - - "Consumer handles manual Ack failure" in { - val someException = new Exception("e1") - val ref = start(new ManualAckConsumer() { - def endpointUri = "direct:manual-ack" - def receive = { case _ => sender() ! Failure(someException) } - }, name = "direct-manual-ack-2") - - intercept[ExecutionException] { - camel.template - .asyncSendBody("direct:manual-ack", "some message") - .get(defaultTimeoutDuration.toSeconds, TimeUnit.SECONDS) - }.getCause.getCause should ===(someException) - stop(ref) - } - - "Consumer should time-out, if manual Ack not received within replyTimeout and should give a human readable error message" in { - val ref = start(new ManualAckConsumer() { - override def replyTimeout = 10 millis - def endpointUri = "direct:manual-ack" - def receive = { case _ => } - }, name = "direct-manual-ack-3") - - intercept[ExecutionException] { - camel.template - .asyncSendBody("direct:manual-ack", "some message") - .get(defaultTimeoutDuration.toSeconds, TimeUnit.SECONDS) - }.getCause.getCause.getMessage should include("Failed to get Ack") - stop(ref) - } - "respond to onRouteDefinition" in { - val ref = start(new ErrorRespondingConsumer("direct:error-responding-consumer-1"), "error-responding-consumer") - filterEvents(EventFilter[TestException](occurrences = 1)) { - val response = camel.sendTo("direct:error-responding-consumer-1", "some body") - response should ===("some body has an error") - } - stop(ref) - } - } -} - -class ErrorThrowingConsumer(override val endpointUri: String) extends Consumer { - def receive = { - case msg: CamelMessage => throw new TestException("error: %s".format(msg.body)) - } - override def preRestart(reason: Throwable, message: Option[Any]): Unit = { - super.preRestart(reason, message) - sender() ! Failure(reason) - } -} - -class ErrorRespondingConsumer(override val endpointUri: String) extends Consumer { - def receive = { - case msg: CamelMessage => throw new TestException("Error!") - } - override def onRouteDefinition = (rd: RouteDefinition) => { - // Catch TestException and handle it by returning a modified version of the in message - rd.onException(classOf[TestException]).handled(true).transform(Builder.body.append(" has an error")).end - } - - final override def preRestart(reason: Throwable, message: Option[Any]): Unit = { - super.preRestart(reason, message) - sender() ! Failure(reason) - } -} - -class FailingOnceConsumer(override val endpointUri: String) extends Consumer { - - def receive = { - case msg: CamelMessage => - if (msg.headerAs[Boolean]("CamelRedelivered").getOrElse(false)) - sender() ! ("accepted: %s".format(msg.body)) - else - throw new TestException("rejected: %s".format(msg.body)) - } - - final override def preRestart(reason: Throwable, message: Option[Any]): Unit = { - super.preRestart(reason, message) - sender() ! Failure(reason) - } -} - -class TestActor(uri: String = "file://target/abcde") extends Consumer { - def endpointUri = uri - def receive = { case _ => /* do nothing */ } -} - -trait ManualAckConsumer extends Consumer { - override def autoAck = false -} - -class TestException(msg: String) extends Exception(msg) diff --git a/akka-camel/src/test/scala/akka/camel/DefaultCamelTest.scala b/akka-camel/src/test/scala/akka/camel/DefaultCamelTest.scala deleted file mode 100644 index 00f88a0216..0000000000 --- a/akka-camel/src/test/scala/akka/camel/DefaultCamelTest.scala +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import akka.camel.TestSupport.SharedCamelSystem -import internal.DefaultCamel -import org.scalatest.Matchers -import org.scalatest.mock.MockitoSugar -import org.apache.camel.ProducerTemplate -import org.scalatest.WordSpec -import akka.event.MarkerLoggingAdapter -import akka.actor.ActorSystem.Settings -import com.typesafe.config.ConfigFactory -import org.apache.camel.impl.DefaultCamelContext -import akka.actor.ExtendedActorSystem - -class DefaultCamelTest extends WordSpec with SharedCamelSystem with Matchers with MockitoSugar { - - import org.mockito.Mockito.{ verify, when } - val sys = mock[ExtendedActorSystem] - val config = ConfigFactory.defaultReference() - when(sys.dynamicAccess).thenReturn(system.asInstanceOf[ExtendedActorSystem].dynamicAccess) - when(sys.settings).thenReturn(new Settings(this.getClass.getClassLoader, config, "mocksystem")) - when(sys.name).thenReturn("mocksystem") - - def camelWithMocks = new DefaultCamel(sys) { - override val log = mock[MarkerLoggingAdapter] - override lazy val template = mock[ProducerTemplate] - override lazy val context = mock[DefaultCamelContext] - override val settings = mock[CamelSettings] - } - - "during shutdown, when both context and template fail to shutdown" when { - val camel = camelWithMocks - - when(camel.context.stop()).thenThrow(new RuntimeException("context")) - when(camel.template.stop()).thenThrow(new RuntimeException("template")) - val exception = intercept[RuntimeException] { - camel.shutdown() - } - - "throws exception thrown by context.stop()" in { - exception.getMessage() should ===("context") - } - - "tries to stop both template and context" in { - verify(camel.template).stop() - verify(camel.context).stop() - } - - } - - "during start, if template fails to start, it will stop the context" in { - val camel = camelWithMocks - - when(camel.template.start()).thenThrow(new RuntimeException) - - intercept[RuntimeException] { - camel.start - } - - verify(camel.context).stop() - - } -} diff --git a/akka-camel/src/test/scala/akka/camel/MessageScalaTest.scala b/akka-camel/src/test/scala/akka/camel/MessageScalaTest.scala deleted file mode 100644 index 42a17106fa..0000000000 --- a/akka-camel/src/test/scala/akka/camel/MessageScalaTest.scala +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import java.io.InputStream -import org.apache.camel.NoTypeConversionAvailableException -import akka.camel.TestSupport.{ SharedCamelSystem } -import org.scalatest.FunSuite -import org.scalatest.Matchers -import org.apache.camel.converter.stream.InputStreamCache - -class MessageScalaTest extends FunSuite with Matchers with SharedCamelSystem { - implicit def camelContext = camel.context - test("mustConvertDoubleBodyToString") { - CamelMessage(1.4, Map.empty).bodyAs[String] should ===("1.4") - } - - test("mustThrowExceptionWhenConvertingDoubleBodyToInputStream") { - intercept[NoTypeConversionAvailableException] { - CamelMessage(1.4, Map.empty).bodyAs[InputStream] - } - } - - test("mustConvertDoubleHeaderToString") { - val message = CamelMessage("test", Map("test" -> 1.4)) - message.headerAs[String]("test").get should ===("1.4") - } - - test("mustReturnSubsetOfHeaders") { - val message = CamelMessage("test", Map("A" -> "1", "B" -> "2")) - message.headers(Set("B")) should ===(Map("B" -> "2")) - } - - test("mustTransformBodyAndPreserveHeaders") { - CamelMessage("a", Map("A" -> "1")).mapBody((body: String) => body + "b") should ===( - CamelMessage("ab", Map("A" -> "1"))) - } - - test("mustConvertBodyAndPreserveHeaders") { - CamelMessage(1.4, Map("A" -> "1")).withBodyAs[String] should ===(CamelMessage("1.4", Map("A" -> "1"))) - } - - test("mustSetBodyAndPreserveHeaders") { - CamelMessage("test1", Map("A" -> "1")).copy(body = "test2") should ===(CamelMessage("test2", Map("A" -> "1"))) - } - - test("mustSetHeadersAndPreserveBody") { - CamelMessage("test1", Map("A" -> "1")).copy(headers = Map("C" -> "3")) should ===( - CamelMessage("test1", Map("C" -> "3"))) - } - - test("mustBeAbleToReReadStreamCacheBody") { - val msg = CamelMessage(new InputStreamCache("test1".getBytes("utf-8")), Map.empty) - msg.bodyAs[String] should ===("test1") - // re-read - msg.bodyAs[String] should ===("test1") - } -} diff --git a/akka-camel/src/test/scala/akka/camel/ProducerFeatureTest.scala b/akka-camel/src/test/scala/akka/camel/ProducerFeatureTest.scala deleted file mode 100644 index 54bd6d3142..0000000000 --- a/akka-camel/src/test/scala/akka/camel/ProducerFeatureTest.scala +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import language.postfixOps - -import org.apache.camel.{ Exchange, Processor } -import org.apache.camel.builder.RouteBuilder -import org.apache.camel.component.mock.MockEndpoint -import scala.concurrent.Await -import akka.actor.SupervisorStrategy.Stop -import org.scalatest.{ BeforeAndAfterAll, BeforeAndAfterEach, WordSpecLike } -import akka.actor._ -import scala.concurrent.duration._ -import akka.util.Timeout -import org.scalatest.Matchers -import akka.testkit._ -import akka.actor.Status.Failure - -/** - * Tests the features of the Camel Producer. - */ -class ProducerFeatureTest - extends TestKit(ActorSystem("ProducerFeatureTest", AkkaSpec.testConf)) - with WordSpecLike - with BeforeAndAfterAll - with BeforeAndAfterEach - with Matchers { - - import ProducerFeatureTest._ - implicit def camel = CamelExtension(system) - - override protected def afterAll(): Unit = { - super.afterAll() - shutdown() - } - - val camelContext = camel.context - // to make testing equality of messages easier, otherwise the breadcrumb shows up in the result. - camelContext.setUseBreadcrumb(false) - val timeoutDuration = 1 second - implicit val timeout = Timeout(timeoutDuration) - override protected def beforeAll: Unit = { camelContext.addRoutes(new TestRoute(system)) } - - override protected def afterEach: Unit = { mockEndpoint.reset() } - - "A Producer on a sync Camel route" must { - - "01 produce a message and receive normal response" in { - val producer = - system.actorOf(Props(new TestProducer("direct:producer-test-2", true)), name = "01-direct-producer-2") - val message = CamelMessage("test", Map(CamelMessage.MessageExchangeId -> "123")) - producer.tell(message, testActor) - expectMsg(CamelMessage("received TEST", Map(CamelMessage.MessageExchangeId -> "123"))) - } - - "02 produce a message and receive failure response" in { - val latch = TestLatch() - var deadActor: Option[ActorRef] = None - val supervisor = system.actorOf( - Props(new Actor { - def receive = { - case p: Props => { - val producer = context.actorOf(p) - context.watch(producer) - sender() ! producer - } - case Terminated(actorRef) => { - deadActor = Some(actorRef) - latch.countDown() - } - } - override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) { - case _: AkkaCamelException => Stop - } - }), - name = "02-prod-anonymous-supervisor") - - supervisor.tell(Props(new TestProducer("direct:producer-test-2")), testActor) - val producer = receiveOne(timeoutDuration).asInstanceOf[ActorRef] - val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123")) - filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) { - producer.tell(message, testActor) - expectMsgPF(timeoutDuration) { - case Failure(e: AkkaCamelException) => - e.getMessage should ===("failure") - e.headers should ===(Map(CamelMessage.MessageExchangeId -> "123")) - } - } - Await.ready(latch, timeoutDuration) - deadActor should ===(Some(producer)) - } - - "03 produce a message oneway" in { - val producer = system.actorOf( - Props(new TestProducer("direct:producer-test-1", true) with Oneway), - name = "03-direct-producer-1-oneway") - mockEndpoint.expectedBodiesReceived("TEST") - producer ! CamelMessage("test", Map()) - mockEndpoint.assertIsSatisfied() - } - - "04 produces message twoway without sender reference" in { - // this test causes a dead letter which can be ignored. The producer is two-way but a oneway tell is used - // to communicate with it and the response is ignored, which ends up in a dead letter - val producer = system.actorOf( - Props(new TestProducer("direct:producer-test-1")), - name = "04-ignore-this-deadletter-direct-producer-test-no-sender") - mockEndpoint.expectedBodiesReceived("test") - producer ! CamelMessage("test", Map()) - mockEndpoint.assertIsSatisfied() - } - } - - "A Producer on an async Camel route" must { - - "10 produce message to direct:producer-test-3 and receive normal response" in { - val producer = - system.actorOf(Props(new TestProducer("direct:producer-test-3")), name = "10-direct-producer-test-3") - val message = CamelMessage("test", Map(CamelMessage.MessageExchangeId -> "123")) - producer.tell(message, testActor) - expectMsg(CamelMessage("received test", Map(CamelMessage.MessageExchangeId -> "123"))) - } - - "11 produce message to direct:producer-test-3 and receive failure response" in { - val producer = system.actorOf( - Props(new TestProducer("direct:producer-test-3")), - name = "11-direct-producer-test-3-receive-failure") - val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123")) - - filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) { - producer.tell(message, testActor) - expectMsgPF(timeoutDuration) { - case Failure(e: AkkaCamelException) => - e.getMessage should ===("failure") - e.headers should ===(Map(CamelMessage.MessageExchangeId -> "123")) - } - } - } - - "12 produce message, forward normal response of direct:producer-test-2 to a replying target actor and receive response" in { - val target = system.actorOf(Props[ReplyingForwardTarget], name = "12-reply-forwarding-target") - val producer = system.actorOf( - Props(new TestForwarder("direct:producer-test-2", target)), - name = "12-direct-producer-test-2-forwarder") - val message = CamelMessage("test", Map(CamelMessage.MessageExchangeId -> "123")) - producer.tell(message, testActor) - expectMsg(CamelMessage("received test", Map(CamelMessage.MessageExchangeId -> "123", "test" -> "result"))) - } - - "13 produce message, forward failure response of direct:producer-test-2 to a replying target actor and receive response" in { - val target = system.actorOf(Props[ReplyingForwardTarget], name = "13-reply-forwarding-target") - val producer = system.actorOf( - Props(new TestForwarder("direct:producer-test-2", target)), - name = "13-direct-producer-test-2-forwarder-failure") - val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123")) - - filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) { - producer.tell(message, testActor) - expectMsgPF(timeoutDuration) { - case Failure(e: AkkaCamelException) => - e.getMessage should ===("failure") - e.headers should ===(Map(CamelMessage.MessageExchangeId -> "123", "test" -> "failure")) - } - } - } - - "14 produce message, forward normal response to a producing target actor and produce response to direct:forward-test-1" in { - val target = system.actorOf(Props[ProducingForwardTarget], name = "14-producer-forwarding-target") - val producer = system.actorOf( - Props(new TestForwarder("direct:producer-test-2", target)), - name = "14-direct-producer-test-2-forwarder-to-producing-target") - mockEndpoint.expectedBodiesReceived("received test") - producer.tell(CamelMessage("test", Map()), producer) - mockEndpoint.assertIsSatisfied() - } - - "15 produce message, forward failure response to a producing target actor and produce response to direct:forward-test-1" in { - val target = system.actorOf(Props[ProducingForwardTarget], name = "15-producer-forwarding-target-failure") - val producer = system.actorOf( - Props(new TestForwarder("direct:producer-test-2", target)), - name = "15-direct-producer-test-2-forward-failure") - filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) { - mockEndpoint.expectedMessageCount(1) - mockEndpoint.message(0).body().isInstanceOf(classOf[akka.actor.Status.Failure]) - producer.tell(CamelMessage("fail", Map()), producer) - mockEndpoint.assertIsSatisfied() - } - } - - "16 produce message, forward normal response from direct:producer-test-3 to a replying target actor and receive response" in { - val target = system.actorOf(Props[ReplyingForwardTarget], name = "16-reply-forwarding-target") - val producer = system.actorOf( - Props(new TestForwarder("direct:producer-test-3", target)), - name = "16-direct-producer-test-3-to-replying-actor") - val message = CamelMessage("test", Map(CamelMessage.MessageExchangeId -> "123")) - - producer.tell(message, testActor) - expectMsg(CamelMessage("received test", Map(CamelMessage.MessageExchangeId -> "123", "test" -> "result"))) - } - - "17 produce message, forward failure response from direct:producer-test-3 to a replying target actor and receive response" in { - val target = system.actorOf(Props[ReplyingForwardTarget], name = "17-reply-forwarding-target") - val producer = system.actorOf( - Props(new TestForwarder("direct:producer-test-3", target)), - name = "17-direct-producer-test-3-forward-failure") - - val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123")) - filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) { - producer.tell(message, testActor) - expectMsgPF(timeoutDuration) { - case Failure(e: AkkaCamelException) => - e.getMessage should ===("failure") - e.headers should ===(Map(CamelMessage.MessageExchangeId -> "123", "test" -> "failure")) - } - } - } - - "18 produce message, forward normal response from direct:producer-test-3 to a producing target actor and produce response to direct:forward-test-1" in { - val target = system.actorOf(Props[ProducingForwardTarget], "18-producing-forward-target-normal") - val producer = system.actorOf( - Props(new TestForwarder("direct:producer-test-3", target)), - name = "18-direct-producer-test-3-forward-normal") - mockEndpoint.expectedBodiesReceived("received test") - producer.tell(CamelMessage("test", Map()), producer) - mockEndpoint.assertIsSatisfied() - } - - "19 produce message, forward failure response from direct:producer-test-3 to a producing target actor and produce response to direct:forward-test-1" in { - val target = system.actorOf(Props[ProducingForwardTarget], "19-producing-forward-target-failure") - val producer = system.actorOf( - Props(new TestForwarder("direct:producer-test-3", target)), - name = "19-direct-producer-test-3-forward-failure-producing-target") - filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) { - mockEndpoint.expectedMessageCount(1) - mockEndpoint.message(0).body().isInstanceOf(classOf[akka.actor.Status.Failure]) - producer.tell(CamelMessage("fail", Map()), producer) - mockEndpoint.assertIsSatisfied() - } - } - - "20 keep producing messages after error" in { - import TestSupport._ - val consumer = - start(new IntermittentErrorConsumer("direct:intermittentTest-1"), "20-intermittentTest-error-consumer") - val producer = start(new SimpleProducer("direct:intermittentTest-1"), "20-intermittentTest-producer") - filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) { - val futureFailed = producer.tell("fail", testActor) - expectMsgPF(timeoutDuration) { - case Failure(e) => - e.getMessage should ===("fail") - } - producer.tell("OK", testActor) - expectMsg("OK") - } - stop(consumer) - stop(producer) - } - - "21 be able to transform outgoing messages and have a valid sender reference" in { - import TestSupport._ - filterEvents(EventFilter[Exception](occurrences = 1)) { - val producerSupervisor = - system.actorOf( - Props(new ProducerSupervisor(Props(new ChildProducer("mock:mock", true)))), - "21-ignore-deadletter-sender-ref-test") - mockEndpoint.reset() - producerSupervisor.tell(CamelMessage("test", Map()), testActor) - producerSupervisor.tell(CamelMessage("err", Map()), testActor) - mockEndpoint.expectedMessageCount(1) - mockEndpoint.expectedBodiesReceived("TEST") - expectMsg("TEST") - } - } - } - - private def mockEndpoint = camel.context.getEndpoint("mock:mock", classOf[MockEndpoint]) -} - -object ProducerFeatureTest { - - class ProducerSupervisor(childProps: Props) extends Actor { - override def supervisorStrategy = SupervisorStrategy.stoppingStrategy - val child = context.actorOf(childProps, "producer-supervisor-child") - val duration = 10 seconds - implicit val timeout = Timeout(duration) - implicit val ec = context.system.dispatcher - Await.ready(CamelExtension(context.system).activationFutureFor(child), timeout.duration) - def receive = { - case msg: CamelMessage => - child.forward(msg) - case (aref: ActorRef, msg: String) => - aref ! msg - } - } - - class ChildProducer(uri: String, upper: Boolean = false) extends Actor with Producer { - override def oneway = true - - var lastSender: Option[ActorRef] = None - var lastMessage: Option[String] = None - def endpointUri = uri - - override def transformOutgoingMessage(msg: Any) = msg match { - case msg: CamelMessage => - if (upper) msg.mapBody { body: String => - if (body == "err") throw new Exception("Crash!") - val upperMsg = body.toUpperCase - lastSender = Some(sender()) - lastMessage = Some(upperMsg) - } else msg - } - - override def postStop(): Unit = { - for (msg <- lastMessage; aref <- lastSender) context.parent ! ((aref, msg)) - super.postStop() - } - } - - class TestProducer(uri: String, upper: Boolean = false) extends Actor with Producer { - def endpointUri = uri - - override def preRestart(reason: Throwable, message: Option[Any]): Unit = { - //overriding on purpose so it doesn't try to deRegister and reRegister at restart, - // which would cause a deadletter message in the test output. - } - - override protected def transformOutgoingMessage(msg: Any) = msg match { - case msg: CamelMessage => - if (upper) msg.mapBody { body: String => - body.toUpperCase - } else msg - } - } - - class TestForwarder(uri: String, target: ActorRef) extends Actor with Producer { - def endpointUri = uri - - override def headersToCopy = Set(CamelMessage.MessageExchangeId, "test") - - override def routeResponse(msg: Any): Unit = target.forward(msg) - } - - class TestResponder extends Actor { - def receive = { - case msg: CamelMessage => - msg.body match { - case "fail" => - context.sender() ! akka.actor.Status.Failure(new AkkaCamelException(new Exception("failure"), msg.headers)) - case _ => - context.sender() ! (msg.mapBody { body: String => - "received %s".format(body) - }) - } - } - } - - class ReplyingForwardTarget extends Actor { - def receive = { - case msg: CamelMessage => - context.sender() ! (msg.copy(headers = msg.headers + ("test" -> "result"))) - case msg: akka.actor.Status.Failure => - msg.cause match { - case e: AkkaCamelException => - context.sender() ! Status.Failure(new AkkaCamelException(e, e.headers + ("test" -> "failure"))) - } - } - } - - class ProducingForwardTarget extends Actor with Producer with Oneway { - def endpointUri = "direct:forward-test-1" - } - - class TestRoute(system: ActorSystem) extends RouteBuilder { - val responder = system.actorOf(Props[TestResponder], name = "TestResponder") - - def configure: Unit = { - from("direct:forward-test-1").to("mock:mock") - // for one-way messaging tests - from("direct:producer-test-1").to("mock:mock") - // for two-way messaging tests (async) - from("direct:producer-test-3").to(responder) - // for two-way messaging tests (sync) - from("direct:producer-test-2").process(new Processor() { - def process(exchange: Exchange) = { - exchange.getIn.getBody match { - case "fail" => throw new Exception("failure") - case body => exchange.getOut.setBody("received %s".format(body)) - } - } - }) - } - } - - class SimpleProducer(override val endpointUri: String) extends Producer { - override protected def transformResponse(msg: Any) = msg match { - case m: CamelMessage => m.bodyAs[String] - case m: Any => m - } - } - - class IntermittentErrorConsumer(override val endpointUri: String) extends Consumer { - def receive = { - case msg: CamelMessage if msg.bodyAs[String] == "fail" => sender() ! Failure(new Exception("fail")) - case msg: CamelMessage => sender() ! msg - } - } - -} diff --git a/akka-camel/src/test/scala/akka/camel/TestSupport.scala b/akka-camel/src/test/scala/akka/camel/TestSupport.scala deleted file mode 100644 index dc66c5692e..0000000000 --- a/akka-camel/src/test/scala/akka/camel/TestSupport.scala +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import language.postfixOps -import language.implicitConversions - -import scala.concurrent.duration._ -import java.util.concurrent.{ ExecutionException, TimeUnit, TimeoutException } -import org.scalatest.{ BeforeAndAfterAll, BeforeAndAfterEach, Suite } -import org.scalatest.matchers.{ BePropertyMatchResult, BePropertyMatcher } -import scala.reflect.ClassTag -import akka.actor.{ Actor, ActorRef, ActorSystem, Props } -import scala.concurrent.Await -import akka.util.Timeout -import akka.testkit.{ AkkaSpec, TestKit } - -private[camel] object TestSupport { - def start(actor: => Actor, name: String)(implicit system: ActorSystem, timeout: Timeout): ActorRef = - Await.result( - CamelExtension(system).activationFutureFor(system.actorOf(Props(actor), name))(timeout, system.dispatcher), - timeout.duration) - - def stop(actorRef: ActorRef)(implicit system: ActorSystem, timeout: Timeout): Unit = { - system.stop(actorRef) - Await.result(CamelExtension(system).deactivationFutureFor(actorRef)(timeout, system.dispatcher), timeout.duration) - } - - private[camel] implicit def camelToTestWrapper(camel: Camel) = new CamelTestWrapper(camel) - - class CamelTestWrapper(camel: Camel) { - - /** - * Sends msg to the endpoint and returns response. - * It only waits for the response until timeout passes. - * This is to reduce cases when unit-tests block infinitely. - */ - def sendTo(to: String, msg: String, timeout: Duration = 1 second): AnyRef = { - try { - camel.template.asyncRequestBody(to, msg).get(timeout.toNanos, TimeUnit.NANOSECONDS) - } catch { - case e: ExecutionException => throw e.getCause - case e: TimeoutException => - throw new AssertionError( - "Failed to get response to message [%s], send to endpoint [%s], within [%s]".format(msg, to, timeout)) - } - } - - def routeCount = camel.context.getRoutes().size() - def routes = camel.context.getRoutes - } - - trait SharedCamelSystem extends BeforeAndAfterAll { this: Suite => - implicit lazy val system = ActorSystem("SharedCamelSystem", AkkaSpec.testConf) - implicit lazy val camel = CamelExtension(system) - - abstract override protected def afterAll(): Unit = { - super.afterAll() - TestKit.shutdownActorSystem(system) - } - } - - trait NonSharedCamelSystem extends BeforeAndAfterEach { this: Suite => - implicit var system: ActorSystem = _ - implicit var camel: Camel = _ - - override protected def beforeEach(): Unit = { - super.beforeEach() - system = ActorSystem("NonSharedCamelSystem", AkkaSpec.testConf) - camel = CamelExtension(system) - } - - override protected def afterEach(): Unit = { - TestKit.shutdownActorSystem(system) - super.afterEach() - } - - } - def time[A](block: => A): FiniteDuration = { - val start = System.nanoTime() - block - val duration = System.nanoTime() - start - duration nanos - } - - def anInstanceOf[T](implicit tag: ClassTag[T]) = { - val clazz = tag.runtimeClass.asInstanceOf[Class[T]] - new BePropertyMatcher[AnyRef] { - def apply(left: AnyRef) = - BePropertyMatchResult(clazz.isAssignableFrom(left.getClass), "an instance of " + clazz.getName) - } - } - -} diff --git a/akka-camel/src/test/scala/akka/camel/UntypedProducerTest.scala b/akka-camel/src/test/scala/akka/camel/UntypedProducerTest.scala deleted file mode 100644 index 1b89f5311a..0000000000 --- a/akka-camel/src/test/scala/akka/camel/UntypedProducerTest.scala +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel - -import language.postfixOps - -import org.apache.camel.{ Exchange, Processor } -import org.apache.camel.builder.RouteBuilder -import org.apache.camel.component.mock.MockEndpoint - -import akka.camel.TestSupport.SharedCamelSystem -import akka.actor.Props -import akka.pattern._ -import scala.concurrent.Await -import scala.concurrent.duration._ -import org.scalatest._ -import akka.testkit._ - -class UntypedProducerTest - extends WordSpec - with Matchers - with BeforeAndAfterAll - with BeforeAndAfterEach - with SharedCamelSystem - with GivenWhenThen { - import UntypedProducerTest._ - val timeout = 1 second - override protected def beforeAll = { - camel.context.addRoutes(new TestRoute) - } - - override protected def afterEach = { - mockEndpoint.reset - } - - "An UntypedProducer producing a message to a sync Camel route" must { - - "produce a message and receive a normal response" in { - val producer = system.actorOf(Props[SampleUntypedReplyingProducer], name = "sample-untyped-replying-producer") - - val message = CamelMessage("test", Map(CamelMessage.MessageExchangeId -> "123")) - val future = producer.ask(message)(timeout) - - val expected = CamelMessage("received test", Map(CamelMessage.MessageExchangeId -> "123")) - Await.result(future, timeout) match { - case result: CamelMessage => result should ===(expected) - case unexpected => fail("Actor responded with unexpected message:" + unexpected) - } - - } - - "produce a message and receive a failure response" in { - val producer = - system.actorOf(Props[SampleUntypedReplyingProducer], name = "sample-untyped-replying-producer-failure") - - val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123")) - filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) { - val future = producer.ask(message)(timeout).failed - - Await.result(future, timeout) match { - case e: AkkaCamelException => - e.getMessage should ===("failure") - e.headers should ===(Map(CamelMessage.MessageExchangeId -> "123")) - case unexpected => fail("Actor responded with unexpected message:" + unexpected) - } - } - } - } - - "An UntypedProducer producing a message to a sync Camel route and then forwarding the response" must { - - "produce a message and send a normal response to direct:forward-test-1" in { - val producer = system.actorOf(Props[SampleUntypedForwardingProducer], name = "sample-untyped-forwarding-producer") - - mockEndpoint.expectedBodiesReceived("received test") - producer.tell(CamelMessage("test", Map[String, Any]()), producer) - mockEndpoint.assertIsSatisfied - } - - } - - private def mockEndpoint = camel.context.getEndpoint("mock:mock", classOf[MockEndpoint]) -} - -object UntypedProducerTest { - class TestRoute extends RouteBuilder { - def configure: Unit = { - from("direct:forward-test-1").to("mock:mock") - from("direct:producer-test-1").process(new Processor() { - def process(exchange: Exchange) = { - exchange.getIn.getBody match { - case "fail" => throw new Exception("failure") - case body => exchange.getOut.setBody("received %s".format(body)) - } - } - }) - } - } -} diff --git a/akka-camel/src/test/scala/akka/camel/internal/ActivationTrackerTest.scala b/akka-camel/src/test/scala/akka/camel/internal/ActivationTrackerTest.scala deleted file mode 100644 index 84b13f3f67..0000000000 --- a/akka-camel/src/test/scala/akka/camel/internal/ActivationTrackerTest.scala +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package akka.camel.internal - -import org.scalatest.Matchers -import scala.concurrent.duration._ -import org.scalatest.{ BeforeAndAfterAll, BeforeAndAfterEach, GivenWhenThen, WordSpecLike } -import akka.actor.{ ActorSystem, Props } -import akka.testkit.{ TestKit, TestProbe, TimingTest } -import akka.camel.internal.ActivationProtocol._ - -class ActivationTrackerTest - extends TestKit(ActorSystem("ActivationTrackerTest")) - with WordSpecLike - with Matchers - with BeforeAndAfterAll - with BeforeAndAfterEach - with GivenWhenThen { - - override protected def afterAll(): Unit = { shutdown() } - - var actor: TestProbe = _ - var awaiting: Awaiting = _ - var anotherAwaiting: Awaiting = _ - val cause = new Exception("cause of failure") - - override protected def beforeEach(): Unit = { - actor = TestProbe() - awaiting = new Awaiting(actor) - anotherAwaiting = new Awaiting(actor) - } - - val at = system.actorOf(Props[ActivationTracker], name = "activationTrackker") - "ActivationTracker" must { - def publish(msg: Any) = at ! msg - implicit def timeout = remainingOrDefault - "forwards activation message to all awaiting parties" taggedAs TimingTest in { - awaiting.awaitActivation() - anotherAwaiting.awaitActivation() - - publish(EndpointActivated(actor.ref)) - - awaiting.verifyActivated() - anotherAwaiting.verifyActivated() - } - - "send activation message even if activation happened earlier" taggedAs TimingTest in { - publish(EndpointActivated(actor.ref)) - Thread.sleep(50) - awaiting.awaitActivation() - - awaiting.verifyActivated() - } - - "send activation message even if actor is already deactivated" taggedAs TimingTest in { - publish(EndpointActivated(actor.ref)) - publish(EndpointDeActivated(actor.ref)) - Thread.sleep(50) - awaiting.awaitActivation() - - awaiting.verifyActivated() - } - - "forward de-activation message to all awaiting parties" taggedAs TimingTest in { - publish(EndpointActivated(actor.ref)) - publish(EndpointDeActivated(actor.ref)) - - awaiting.awaitDeActivation() - anotherAwaiting.awaitDeActivation() - - awaiting.verifyDeActivated() - anotherAwaiting.verifyDeActivated() - } - - "forward de-activation message even if deactivation happened earlier" taggedAs TimingTest in { - publish(EndpointActivated(actor.ref)) - - awaiting.awaitDeActivation() - - publish(EndpointDeActivated(actor.ref)) - - awaiting.verifyDeActivated() - } - - "forward de-activation message even if someone awaits de-activation even before activation happens" taggedAs TimingTest in { - val awaiting = new Awaiting(actor) - awaiting.awaitDeActivation() - - publish(EndpointActivated(actor.ref)) - - publish(EndpointDeActivated(actor.ref)) - - awaiting.verifyDeActivated() - } - - "send activation failure when failed to activate" taggedAs TimingTest in { - awaiting.awaitActivation() - publish(EndpointFailedToActivate(actor.ref, cause)) - - awaiting.verifyFailedToActivate() - } - - "send de-activation failure when failed to de-activate" taggedAs TimingTest in { - publish(EndpointActivated(actor.ref)) - awaiting.awaitDeActivation() - publish(EndpointFailedToDeActivate(actor.ref, cause)) - - awaiting.verifyFailedToDeActivate() - } - - "send activation message even if it failed to de-activate" taggedAs TimingTest in { - publish(EndpointActivated(actor.ref)) - publish(EndpointFailedToDeActivate(actor.ref, cause)) - awaiting.awaitActivation() - - awaiting.verifyActivated() - } - - "send activation message when an actor is activated, deactivated and activated again" taggedAs TimingTest in { - publish(EndpointActivated(actor.ref)) - publish(EndpointDeActivated(actor.ref)) - publish(EndpointActivated(actor.ref)) - awaiting.awaitActivation() - awaiting.verifyActivated() - } - } - - class Awaiting(actor: TestProbe) { - val probe = TestProbe() - def awaitActivation() = at.tell(AwaitActivation(actor.ref), probe.ref) - def awaitDeActivation() = at.tell(AwaitDeActivation(actor.ref), probe.ref) - def verifyActivated()(implicit timeout: FiniteDuration) = within(timeout) { - probe.expectMsg(EndpointActivated(actor.ref)) - } - def verifyDeActivated()(implicit timeout: FiniteDuration) = within(timeout) { - probe.expectMsg(EndpointDeActivated(actor.ref)) - } - - def verifyFailedToActivate()(implicit timeout: FiniteDuration) = within(timeout) { - probe.expectMsg(EndpointFailedToActivate(actor.ref, cause)) - } - def verifyFailedToDeActivate()(implicit timeout: FiniteDuration) = within(timeout) { - probe.expectMsg(EndpointFailedToDeActivate(actor.ref, cause)) - } - - } - -} diff --git a/akka-camel/src/test/scala/akka/camel/internal/component/ActorComponentConfigurationTest.scala b/akka-camel/src/test/scala/akka/camel/internal/component/ActorComponentConfigurationTest.scala deleted file mode 100644 index fbc5b9778d..0000000000 --- a/akka-camel/src/test/scala/akka/camel/internal/component/ActorComponentConfigurationTest.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel.internal.component - -import language.postfixOps - -import org.scalatest.Matchers -import scala.concurrent.duration._ -import akka.camel.TestSupport.SharedCamelSystem -import org.apache.camel.Component -import org.scalatest.WordSpec - -class ActorComponentConfigurationTest extends WordSpec with Matchers with SharedCamelSystem { - - val component: Component = camel.context.getComponent("akka") - - "Endpoint url config should be correctly parsed" in { - val actorEndpointConfig = component - .createEndpoint(s"akka://test/user/$$a?autoAck=false&replyTimeout=987000000+nanos") - .asInstanceOf[ActorEndpointConfig] - - actorEndpointConfig should have( - 'endpointUri (s"akka://test/user/$$a?autoAck=false&replyTimeout=987000000+nanos"), - 'path (ActorEndpointPath.fromCamelPath(s"akka://test/user/$$a")), - 'autoAck (false), - 'replyTimeout (987000000 nanos)) - } - -} diff --git a/akka-camel/src/test/scala/akka/camel/internal/component/ActorEndpointPathTest.scala b/akka-camel/src/test/scala/akka/camel/internal/component/ActorEndpointPathTest.scala deleted file mode 100644 index d6c2d24367..0000000000 --- a/akka-camel/src/test/scala/akka/camel/internal/component/ActorEndpointPathTest.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel.internal.component - -import org.scalatest.mock.MockitoSugar -import org.scalatest.Matchers -import akka.camel.TestSupport.SharedCamelSystem -import org.scalatest.WordSpec -import akka.actor.{ Actor, Props } - -class ActorEndpointPathTest extends WordSpec with SharedCamelSystem with Matchers with MockitoSugar { - - def find(path: String) = ActorEndpointPath.fromCamelPath(path).findActorIn(system) - - "findActorIn returns Some(actor ref) if actor exists" in { - val path = system.actorOf(Props(new Actor { def receive = { case _ => } }), "knownactor").path - find(path.toString) should be('defined) - } - - "findActorIn returns None" when { - "non existing valid path" in { find("akka://system/user/unknownactor") should ===(None) } - } - "fromCamelPath throws IllegalArgumentException" when { - "invalid path" in { - intercept[IllegalArgumentException] { - find("invalidpath") - } - } - } -} 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 deleted file mode 100644 index 5bb716c561..0000000000 --- a/akka-camel/src/test/scala/akka/camel/internal/component/ActorProducerTest.scala +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel.internal.component - -import language.postfixOps -import org.scalatest.mock.MockitoSugar -import org.mockito.ArgumentMatchers.any -import org.mockito.Mockito._ -import org.apache.camel.{ AsyncCallback, ProducerTemplate } -import java.util.concurrent.atomic.AtomicBoolean - -import scala.concurrent.duration._ -import akka.camel._ -import internal.{ CamelExchangeAdapter, DefaultCamel } -import org.scalatest.{ BeforeAndAfterAll, BeforeAndAfterEach, Suite, WordSpecLike } -import akka.camel.TestSupport._ -import java.util.concurrent.{ CountDownLatch, TimeoutException } - -import org.mockito.{ ArgumentMatcher, ArgumentMatchers, Mockito } -import org.scalatest.Matchers -import akka.actor.Status.Failure -import com.typesafe.config.ConfigFactory -import akka.actor.ActorSystem.Settings -import akka.event.MarkerLoggingAdapter -import akka.testkit.{ TestKit, TestLatch, TestProbe, TimingTest } -import org.apache.camel.impl.DefaultCamelContext - -import scala.concurrent.{ Await, Future } -import akka.util.Timeout -import akka.actor._ -import akka.testkit._ - -class ActorProducerTest - extends TestKit(ActorSystem("ActorProducerTest")) - with WordSpecLike - with Matchers - with ActorProducerFixture { - implicit val timeout = Timeout(10 seconds) - - "ActorProducer" when { - - "synchronous" when { - - "consumer actor doesnt exist" must { - "set failure message on exchange" in { - producer = given(actor = null) - producer.processExchangeAdapter(exchange) - - verify(exchange).setFailure(any[FailureResult]) - } - } - - "in-only" must { - def producer = given(outCapable = false) - - "pass the message to the consumer" taggedAs TimingTest in { - producer.processExchangeAdapter(exchange) - within(1 second)(probe.expectMsg(message)) - } - - "not expect response and not block" taggedAs TimingTest in { - time(producer.processExchangeAdapter(exchange)) should be < (200 millis) - } - } - - "manualAck" when { - - "response is Ack" must { - "process the exchange" in { - producer = given(outCapable = false, autoAck = false) - import system.dispatcher - val future = Future { producer.processExchangeAdapter(exchange) } - within(1 second) { - probe.expectMsgType[CamelMessage] - info("message sent to consumer") - probe.sender() ! Ack - } - verify(exchange, never()).setResponse(any[CamelMessage]) - info("no response forwarded to exchange") - Await.ready(future, timeout.duration) - } - } - "the consumer does not respond wit Ack" must { - "not block forever" in { - producer = given(outCapable = false, autoAck = false) - import system.dispatcher - val future = Future { - producer.processExchangeAdapter(exchange) - } - within(1 second) { - probe.expectMsgType[CamelMessage] - info("message sent to consumer") - } - verify(exchange, never()).setResponse(any[CamelMessage]) - info("no response forwarded to exchange") - intercept[TimeoutException] { - Await.ready(future, camel.settings.ReplyTimeout - (1 seconds)) - } - } - } - } - - "out capable" when { - "response is sent back by actor" must { - - "get a response" in { - producer = given(actor = echoActor, outCapable = true) - - producer.processExchangeAdapter(exchange) - - verify(exchange).setResponse(msg("received " + message)) - } - } - - "response is not sent by actor" must { - val latch = TestLatch(1) - val callback = new AsyncCallback { - def done(doneSync: Boolean): Unit = { - latch.countDown() - } - } - def process() = { - producer = given(outCapable = true, replyTimeout = 100 millis) - val duration = time { - producer.processExchangeAdapter(exchange, callback) - // wait for the actor to complete the callback - Await.ready(latch, 1.seconds.dilated) - } - latch.reset() - duration - } - - "timeout after replyTimeout" taggedAs TimingTest in { - val duration = process() - duration should (be >= (100 millis) and be < (2000 millis)) - } - - "never set the response on exchange" in { - process() - verify(exchange, Mockito.never()).setResponse(any[CamelMessage]) - } - - "set failure message to timeout" in { - process() - verify(exchange).setFailure(any[FailureResult]) - } - } - - } - } - - "asynchronous" when { - - def verifyFailureIsSet(): Unit = { - producer.processExchangeAdapter(exchange, asyncCallback) - asyncCallback.awaitCalled() - verify(exchange).setFailure(any[FailureResult]) - } - - "out-capable" when { - - "consumer actor doesnt exist" must { - "set failure message on exchange" in { - producer = given(actor = null, outCapable = true) - verifyFailureIsSet() - } - } - - "response is ok" must { - "get a response and async callback as soon as it gets the response (but not before)" in { - producer = given(outCapable = true) - - val doneSync = producer.processExchangeAdapter(exchange, asyncCallback) - - asyncCallback.expectNoCallWithin(100 millis) - info("no async callback before response") - - within(1 second) { - probe.expectMsgType[CamelMessage] - probe.sender() ! "some message" - } - doneSync should ===(false) - info("done async") - - asyncCallback.expectDoneAsyncWithin(1 second) - info("async callback received") - verify(exchange).setResponse(msg("some message")) - info("response as expected") - } - } - - "response is Failure" must { - "set an exception on exchange" in { - val exception = new RuntimeException("some failure") - val failure = Failure(exception) - - producer = given(outCapable = true) - - producer.processExchangeAdapter(exchange, asyncCallback) - - within(1 second) { - probe.expectMsgType[CamelMessage] - probe.sender() ! failure - asyncCallback.awaitCalled(remaining) - } - - verify(exchange).setFailure(FailureResult(exception)) - } - } - - "no response is sent within timeout" must { - "set TimeoutException on exchange" in { - producer = given(outCapable = true, replyTimeout = 10 millis) - producer.processExchangeAdapter(exchange, asyncCallback) - asyncCallback.awaitCalled(100 millis) - verify(exchange).setFailure(ArgumentMatchers.argThat(new ArgumentMatcher[FailureResult] { - def matches(failure: FailureResult) = { - failure.asInstanceOf[FailureResult].cause should be(anInstanceOf[TimeoutException]) - true - } - - })) - } - } - - } - - "in-only" when { - - "consumer actor doesnt exist" must { - "set failure message on exchange" in { - producer = given(actor = null, outCapable = false) - verifyFailureIsSet() - } - } - - "autoAck" must { - - "get sync callback as soon as it sends a message" in { - - producer = given(outCapable = false, autoAck = true) - val doneSync = producer.processExchangeAdapter(exchange, asyncCallback) - - doneSync should ===(true) - info("done sync") - asyncCallback.expectDoneSyncWithin(1 second) - info("async callback called") - verify(exchange, never()).setResponse(any[CamelMessage]) - info("no response forwarded to exchange") - } - - } - - "manualAck" when { - - "response is Ack" must { - "get async callback" in { - producer = given(outCapable = false, autoAck = false) - - val doneSync = producer.processExchangeAdapter(exchange, asyncCallback) - - doneSync should ===(false) - within(1 second) { - probe.expectMsgType[CamelMessage] - info("message sent to consumer") - probe.sender() ! Ack - asyncCallback.expectDoneAsyncWithin(remaining) - info("async callback called") - } - verify(exchange, never()).setResponse(any[CamelMessage]) - info("no response forwarded to exchange") - } - } - - "expecting Ack or Failure message and some other message is sent as a response" must { - "fail" in { - producer = given(outCapable = false, autoAck = false) - - producer.processExchangeAdapter(exchange, asyncCallback) - - within(1 second) { - 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[CamelMessage]) - info("no response forwarded to exchange") - verify(exchange).setFailure(any[FailureResult]) - info("failure set") - - } - } - - "no Ack is sent within timeout" must { - "set failure on exchange" in { - producer = given(outCapable = false, replyTimeout = 10 millis, autoAck = false) - - producer.processExchangeAdapter(exchange, asyncCallback) - asyncCallback.awaitCalled(100 millis) - verify(exchange).setFailure(any[FailureResult]) - - } - } - - "response is Failure" must { - "set an exception on exchange" in { - producer = given(outCapable = false, autoAck = false) - - val doneSync = producer.processExchangeAdapter(exchange, asyncCallback) - - doneSync should ===(false) - within(1 second) { - probe.expectMsgType[CamelMessage] - info("message sent to consumer") - probe.sender() ! Failure(new Exception) - asyncCallback.awaitCalled(remaining) - } - verify(exchange, never()).setResponse(any[CamelMessage]) - info("no response forwarded to exchange") - verify(exchange).setFailure(any[FailureResult]) - info("failure set") - } - } - } - } - } - } -} - -private[camel] trait ActorProducerFixture extends MockitoSugar with BeforeAndAfterAll with BeforeAndAfterEach { - self: TestKit with Matchers with Suite => - var camel: Camel = _ - var exchange: CamelExchangeAdapter = _ - var callback: AsyncCallback = _ - - var producer: ActorProducer = _ - var message: CamelMessage = _ - var probe: TestProbe = _ - var asyncCallback: TestAsyncCallback = _ - var actorEndpointPath: ActorEndpointPath = _ - var actorComponent: ActorComponent = _ - - override protected def beforeEach(): Unit = { - asyncCallback = createAsyncCallback - - probe = TestProbe() - - val sys = mock[ExtendedActorSystem] - val config = ConfigFactory.defaultReference() - when(sys.dispatcher).thenReturn(system.dispatcher) - when(sys.dynamicAccess).thenReturn(system.asInstanceOf[ExtendedActorSystem].dynamicAccess) - when(sys.settings).thenReturn(new Settings(this.getClass.getClassLoader, config, "mocksystem")) - when(sys.name).thenReturn("mocksystem") - - def camelWithMocks = new DefaultCamel(sys) { - override val log = mock[MarkerLoggingAdapter] - override lazy val template = mock[ProducerTemplate] - override lazy val context = mock[DefaultCamelContext] - override val settings = new CamelSettings( - ConfigFactory.parseString(""" - akka { - camel { - jmx = off - streamingCache = on - consumer { - auto-ack = on - reply-timeout = 2s - activation-timeout = 10s - } - } - } - """).withFallback(config), - sys.dynamicAccess) - } - camel = camelWithMocks - - exchange = mock[CamelExchangeAdapter] - callback = mock[AsyncCallback] - actorEndpointPath = mock[ActorEndpointPath] - actorComponent = mock[ActorComponent] - producer = new ActorProducer(configure(), camel) - message = CamelMessage(null, null) - } - - override protected def afterAll(): Unit = { - shutdown() - } - - def msg(s: String) = CamelMessage(s, Map.empty) - - def given( - actor: ActorRef = probe.ref, - outCapable: Boolean = true, - autoAck: Boolean = true, - replyTimeout: FiniteDuration = 20 seconds) = { - prepareMocks(actor, outCapable = outCapable) - new ActorProducer(configure(isAutoAck = autoAck, _replyTimeout = replyTimeout), camel) - } - - def createAsyncCallback = new TestAsyncCallback - - class TestAsyncCallback extends AsyncCallback { - def expectNoCallWithin(duration: Duration): Unit = - if (callbackReceived.await(duration.length, duration.unit)) fail("NOT expected callback, but received one!") - def awaitCalled(timeout: Duration = 1 second): Unit = { valueWithin(1 second) } - - val callbackReceived = new CountDownLatch(1) - val callbackValue = new AtomicBoolean() - - def done(doneSync: Boolean): Unit = { - callbackValue.set(doneSync) - callbackReceived.countDown() - } - - private[this] def valueWithin(implicit timeout: FiniteDuration) = - if (!callbackReceived.await(timeout.length, timeout.unit)) fail("Callback not received!") - else callbackValue.get - - def expectDoneSyncWithin(implicit timeout: FiniteDuration): Unit = - if (!valueWithin(timeout)) fail("Expected to be done Synchronously") - def expectDoneAsyncWithin(implicit timeout: FiniteDuration): Unit = - if (valueWithin(timeout)) fail("Expected to be done Asynchronously") - - } - - def configure( - endpointUri: String = "test-uri", - isAutoAck: Boolean = true, - _replyTimeout: FiniteDuration = 20 seconds) = { - val endpoint = new ActorEndpoint(endpointUri, actorComponent, actorEndpointPath, camel) - endpoint.autoAck = isAutoAck - endpoint.replyTimeout = _replyTimeout - endpoint - } - - def prepareMocks(actor: ActorRef, message: CamelMessage = message, outCapable: Boolean): Unit = { - when(actorEndpointPath.findActorIn(any[ActorSystem])).thenReturn(Option(actor)) - when(exchange.toRequestMessage(any[Map[String, Any]])).thenReturn(message) - when(exchange.isOutCapable).thenReturn(outCapable) - } - - def echoActor = - system.actorOf(Props(new Actor { - def receive = { case msg => sender() ! "received " + msg } - }), name = "echoActor") - -} diff --git a/akka-camel/src/test/scala/akka/camel/internal/component/DurationConverterTest.scala b/akka-camel/src/test/scala/akka/camel/internal/component/DurationConverterTest.scala deleted file mode 100644 index 6ba051d425..0000000000 --- a/akka-camel/src/test/scala/akka/camel/internal/component/DurationConverterTest.scala +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.camel.internal.component - -import language.postfixOps - -import org.scalatest.Matchers -import scala.concurrent.duration._ -import org.scalatest.WordSpec -import org.apache.camel.TypeConversionException - -class DurationConverterSpec extends WordSpec with Matchers { - import DurationTypeConverter._ - - "DurationTypeConverter must convert '10 nanos'" in { - convertTo(classOf[Duration], "10 nanos") should ===(10 nanos) - } - - "DurationTypeConverter must do the roundtrip" in { - convertTo(classOf[Duration], (10 seconds).toString()) should ===(10 seconds) - } - - "DurationTypeConverter must throw if invalid format" in { - tryConvertTo(classOf[Duration], "abc nanos") should ===(null) - - intercept[TypeConversionException] { - mandatoryConvertTo(classOf[Duration], "abc nanos") should ===(10 nanos) - }.getValue should ===("abc nanos") - } - - "DurationTypeConverter must throw if doesn't end with time unit" in { - tryConvertTo(classOf[Duration], "10233") should ===(null) - - intercept[TypeConversionException] { - mandatoryConvertTo(classOf[Duration], "10233") should ===(10 nanos) - }.getValue should ===("10233") - } - -} diff --git a/akka-camel/src/test/scala/application.conf b/akka-camel/src/test/scala/application.conf deleted file mode 100644 index 2b75ae7a47..0000000000 --- a/akka-camel/src/test/scala/application.conf +++ /dev/null @@ -1,3 +0,0 @@ -akka{ - loglevel = "ERROR" -} \ No newline at end of file diff --git a/akka-docs/src/main/paradox/camel.md b/akka-docs/src/main/paradox/camel.md index 4a1c60fab9..f37aafde3e 100644 --- a/akka-docs/src/main/paradox/camel.md +++ b/akka-docs/src/main/paradox/camel.md @@ -1,526 +1,7 @@ # Camel -## Dependency +The akka-camel module was deprecated in 2.5 and has been removed in 2.6. -To use Camel, you must add the following dependency in your project: +As an alternative we recommend [Alpakka](https://doc.akka.io/docs/alpakka/current/). This is of course not a drop-in replacement. -@@dependency[sbt,Maven,Gradle] { - group="com.typesafe.akka" - artifact="akka-camel_$scala.binary_version$" - version="$akka.version$" -} - -Camel depends on `jaxb-api` and `javax.activation` that were removed from the JDK. If running on a version of the JDK 9 or above also add -the following dependencies: - -@@dependency[sbt,Maven,Gradle] { - group="javax.xml.bind" - artifact="jaxb-api" - version="2.3.0" -} - -@@dependency[sbt,Maven,Gradle] { - group="com.sun.activation" - artifact="javax.activation" - version="1.2.0" -} - -## Introduction - -@@@ warning - -Akka Camel is deprecated in favour of [Alpakka](https://github.com/akka/alpakka) , the Akka Streams based collection of integrations to various endpoints (including Camel). - -@@@ - -## Introduction - -The akka-camel module allows Untyped Actors to receive -and send messages over a great variety of protocols and APIs. -In addition to the native Scala and Java actor API, actors can now exchange messages with other systems over large number -of protocols and APIs such as HTTP, SOAP, TCP, FTP, SMTP or JMS, to mention a -few. At the moment, approximately 80 protocols and APIs are supported. - -### Apache Camel - -The akka-camel module is based on [Apache Camel](http://camel.apache.org/), a powerful and light-weight -integration framework for the JVM. For an introduction to Apache Camel you may -want to read this [Apache Camel article](http://architects.dzone.com/articles/apache-camel-integration). Camel comes with a -large number of [components](http://camel.apache.org/components.html) that provide bindings to different protocols and -APIs. The [camel-extra](http://code.google.com/p/camel-extra/) project provides further components. - -### Consumer - -Here's an example of using Camel's integration components in Akka. - -Scala -: @@snip [Introduction.scala](/akka-docs/src/test/scala/docs/camel/Introduction.scala) { #Consumer-mina } - -Java -: @@snip [MyEndpoint.java](/akka-docs/src/test/java/jdocs/camel/MyEndpoint.java) { #Consumer-mina } - -The above example exposes an actor over a TCP endpoint via Apache -Camel's [Mina component](http://camel.apache.org/mina2.html). The actor implements the @scala[`endpointUri`]@java[`getEndpointUri`] method to define -an endpoint from which it can receive messages. After starting the actor, TCP -clients can immediately send messages to and receive responses from that -actor. If the message exchange should go over HTTP (via Camel's Jetty -component), the actor's @scala[`endpointUri`]@java[`getEndpointUri`] method should return a different URI, for instance `jetty:http://localhost:8877/example`. - -@@@ div { .group-scala } - -@@snip [Introduction.scala](/akka-docs/src/test/scala/docs/camel/Introduction.scala) { #Consumer } - -@@@ - -@@@ div { .group-java } - -In the above case an extra constructor is added that can set the endpoint URI, which would result in -the `getEndpointUri` returning the URI that was set using this constructor. - -@@@ - -### Producer - -Actors can also trigger message exchanges with external systems i.e. produce to -Camel endpoints. - -Scala -: @@snip [Introduction.scala](/akka-docs/src/test/scala/docs/camel/Introduction.scala) { #imports #Producer } - -Java -: @@snip [Orders.java](/akka-docs/src/test/java/jdocs/camel/Orders.java) { #Producer } - -In the above example, any message sent to this actor will be sent to -the JMS queue @scala[`orders`]@java[`Orders`]. Producer actors may choose from the same set of Camel -components as Consumer actors do. - -@@@ div { .group-java } - -Below an example of how to send a message to the `Orders` producer. - -@@snip [ProducerTestBase.java](/akka-docs/src/test/java/jdocs/camel/ProducerTestBase.java) { #TellProducer } - -@@@ - -### CamelMessage - -The number of Camel components is constantly increasing. The akka-camel module -can support these in a plug-and-play manner. Just add them to your application's -classpath, define a component-specific endpoint URI and use it to exchange -messages over the component-specific protocols or APIs. This is possible because -Camel components bind protocol-specific message formats to a Camel-specific -[normalized message format](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/Message.java). The normalized message format hides -protocol-specific details from Akka and makes it therefore very easy to support -a large number of protocols through a uniform Camel component interface. The -akka-camel module further converts mutable Camel messages into immutable -representations which are used by Consumer and Producer actors for pattern -matching, transformation, serialization or storage. In the above example of the Orders Producer, -the XML message is put in the body of a newly created Camel Message with an empty set of headers. -You can also create a CamelMessage yourself with the appropriate body and headers as you see fit. - -### CamelExtension - -The akka-camel module is implemented as an Akka Extension, the `CamelExtension` object. -Extensions will only be loaded once per `ActorSystem`, which will be managed by Akka. -The `CamelExtension` object provides access to the @extref[Camel](github:akka-camel/src/main/scala/akka/camel/Camel.scala) @scala[trait]@java[interface]. -The @extref[Camel](github:akka-camel/src/main/scala/akka/camel/Camel.scala) @scala[trait]@java[interface] in turn provides access to two important Apache Camel objects, the [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java) and the `ProducerTemplate`. -Below you can see how you can get access to these Apache Camel objects. - -Scala -: @@snip [Introduction.scala](/akka-docs/src/test/scala/docs/camel/Introduction.scala) { #CamelExtension } - -Java -: @@snip [CamelExtensionTest.java](/akka-docs/src/test/java/jdocs/camel/CamelExtensionTest.java) { #CamelExtension } - -One `CamelExtension` is only loaded once for every one `ActorSystem`, which makes it safe to call the `CamelExtension` at any point in your code to get to the -Apache Camel objects associated with it. There is one [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java) and one `ProducerTemplate` for every one `ActorSystem` that uses a `CamelExtension`. -By Default, a new [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java) is created when the `CamelExtension` starts. If you want to inject your own context instead, -you can @scala[extend]@java[implement] the @extref[ContextProvider](github:akka-camel/src/main/scala/akka/camel/ContextProvider.scala) @scala[trait]@java[interface] and add the FQCN of your implementation in the config, as the value of the "akka.camel.context-provider". -This interface define a single method `getContext()` used to load the [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java). - -Below an example on how to add the ActiveMQ component to the [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java), which is required when you would like to use the ActiveMQ component. - -Scala -: @@snip [Introduction.scala](/akka-docs/src/test/scala/docs/camel/Introduction.scala) { #CamelExtensionAddComponent } - -Java -: @@snip [CamelExtensionTest.java](/akka-docs/src/test/java/jdocs/camel/CamelExtensionTest.java) { #CamelExtensionAddComponent } - -The [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java) joins the lifecycle of the `ActorSystem` and `CamelExtension` it is associated with; the [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java) is started when -the `CamelExtension` is created, and it is shut down when the associated `ActorSystem` is shut down. The same is true for the `ProducerTemplate`. - -The `CamelExtension` is used by both `Producer` and `Consumer` actors to interact with Apache Camel internally. -You can access the `CamelExtension` inside a `Producer` or a `Consumer` using the `camel` @scala[definition]@java[method], or get straight at the `CamelContext` -using the @scala[`camelContext` definition]@java[`getCamelContext` method or to the `ProducerTemplate` using the `getProducerTemplate` method]. -Actors are created and started asynchronously. When a `Consumer` actor is created, the `Consumer` is published at its Camel endpoint (more precisely, the route is added to the [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java) from the [Endpoint](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/Endpoint.java) to the actor). -When a `Producer` actor is created, a [SendProcessor](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/processor/SendProcessor.java) and [Endpoint](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/Endpoint.java) are created so that the Producer can send messages to it. -Publication is done asynchronously; setting up an endpoint may still be in progress after you have -requested the actor to be created. Some Camel components can take a while to startup, and in some cases you might want to know when the endpoints are activated and ready to be used. -The @extref[Camel](github:akka-camel/src/main/scala/akka/camel/Camel.scala) @scala[trait]@java[interface] allows you to find out when the endpoint is activated or deactivated. - -Scala -: @@snip [Introduction.scala](/akka-docs/src/test/scala/docs/camel/Introduction.scala) { #CamelActivation } - -Java -: @@snip [ActivationTestBase.java](/akka-docs/src/test/java/jdocs/camel/ActivationTestBase.java) { #CamelActivation } - -The above code shows that you can get a `Future` to the activation of the route from the endpoint to the actor, or you can wait in a blocking fashion on the activation of the route. -An `ActivationTimeoutException` is thrown if the endpoint could not be activated within the specified timeout. Deactivation works in a similar fashion: - -Scala -: @@snip [Introduction.scala](/akka-docs/src/test/scala/docs/camel/Introduction.scala) { #CamelDeactivation } - -Java -: @@snip [ActivationTestBase.java](/akka-docs/src/test/java/jdocs/camel/ActivationTestBase.java) { #CamelDeactivation } - -Deactivation of a Consumer or a Producer actor happens when the actor is terminated. For a Consumer, the route to the actor is stopped. For a Producer, the [SendProcessor](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/processor/SendProcessor.java) is stopped. -A `DeActivationTimeoutException` is thrown if the associated camel objects could not be deactivated within the specified timeout. - -## Consumer Actors - -For objects to receive messages, they must @scala[mixin the @extref[Consumer](github:akka-camel/src/main/scala/akka/camel/Consumer.scala) trait]@java[inherit from the @extref[UntypedConsumerActor](github:akka-camel/src/main/scala/akka/camel/javaapi/UntypedConsumer.scala) class]. -For example, the following actor class (Consumer1) implements the -@scala[`endpointUri`]@java[`getEndpointUri`] method, which is declared in the @scala[`Consumer` trait]@java[@extref[UntypedConsumerActor](github:akka-camel/src/main/scala/akka/camel/javaapi/UntypedConsumer.scala) class], in order to receive -messages from the `file:data/input/actor` Camel endpoint. - -Scala -: @@snip [Consumers.scala](/akka-docs/src/test/scala/docs/camel/Consumers.scala) { #Consumer1 } - -Java -: @@snip [Consumer1.java](/akka-docs/src/test/java/jdocs/camel/Consumer1.java) { #Consumer1 } - -Whenever a file is put into the data/input/actor directory, its content is -picked up by the Camel [file component](http://camel.apache.org/file2.html) and sent as message to the -actor. Messages consumed by actors from Camel endpoints are of type -[CamelMessage](#camelmessage). These are immutable representations of Camel messages. - -Here's another example that sets the endpointUri to -`jetty:http://localhost:8877/camel/default`. It causes Camel's Jetty -component to start an embedded [Jetty](http://www.eclipse.org/jetty/) server, accepting HTTP connections -from localhost on port 8877. - -Scala -: @@snip [Consumers.scala](/akka-docs/src/test/scala/docs/camel/Consumers.scala) { #Consumer2 } - -Java -: @@snip [Consumer2.java](/akka-docs/src/test/java/jdocs/camel/Consumer2.java) { #Consumer2 } - -After starting the actor, clients can send messages to that actor by POSTing to -`http://localhost:8877/camel/default`. The actor sends a response by using the -sender @scala[`!`]@java[`getSender().tell`] method. For returning a message body and headers to the HTTP -client the response type should be [CamelMessage](#camelmessage). For any other response type, a -new CamelMessage object is created by akka-camel with the actor response as message -body. - - -### Delivery acknowledgements - -With in-out message exchanges, clients usually know that a message exchange is -done when they receive a reply from a consumer actor. The reply message can be a -CamelMessage (or any object which is then internally converted to a CamelMessage) on -success, and a Failure message on failure. - -With in-only message exchanges, by default, an exchange is done when a message -is added to the consumer actor's mailbox. Any failure or exception that occurs -during processing of that message by the consumer actor cannot be reported back -to the endpoint in this case. To allow consumer actors to positively or -negatively acknowledge the receipt of a message from an in-only message -exchange, they need to override the `autoAck` method to return false. -In this case, consumer actors must reply either with a -special akka.camel.Ack message (positive acknowledgement) or a akka.actor.Status.Failure (negative -acknowledgement). - -Scala -: @@snip [Consumers.scala](/akka-docs/src/test/scala/docs/camel/Consumers.scala) { #Consumer3 } - -Java -: @@snip [Consumer3.java](/akka-docs/src/test/java/jdocs/camel/Consumer3.java) { #Consumer3 } - - -### Consumer timeout - -Camel Exchanges (and their corresponding endpoints) that support two-way communications need to wait for a response from -an actor before returning it to the initiating client. -For some endpoint types, timeout values can be defined in an endpoint-specific -way which is described in the documentation of the individual Camel -components. Another option is to configure timeouts on the level of consumer actors. - -Two-way communications between a Camel endpoint and an actor are -initiated by sending the request message to the actor with the @scala[@extref[ask](github:akka-actor/src/main/scala/akka/pattern/AskSupport.scala)]@java[@extref[ask](github:akka-actor/src/main/scala/akka/pattern/Patterns.scala)] pattern -and the actor replies to the endpoint when the response is ready. The ask request to the actor can timeout, which will -result in the [Exchange](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/Exchange.java) failing with a TimeoutException set on the failure of the [Exchange](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/Exchange.java). -The timeout on the consumer actor can be overridden with the `replyTimeout`, as shown below. - -Scala -: @@snip [Consumers.scala](/akka-docs/src/test/scala/docs/camel/Consumers.scala) { #Consumer4 } - -Java -: @@snip [Consumer4.java](/akka-docs/src/test/java/jdocs/camel/Consumer4.java) { #Consumer4 } - -## Producer Actors - -For sending messages to Camel endpoints, actors need to @scala[mixin the @extref[Producer](github:akka-camel/src/main/scala/akka/camel/Producer.scala) trait] -@java[inherit from the @extref[UntypedProducerActor](github:akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala) class] and implement the `getEndpointUri` method. - -Scala -: @@snip [Producers.scala](/akka-docs/src/test/scala/docs/camel/Producers.scala) { #Producer1 } - -Java -: @@snip [Producer1.java](/akka-docs/src/test/java/jdocs/camel/Producer1.java) { #Producer1 } - -Producer1 inherits a default implementation of the @scala[`receive`]@java[`onReceive`] method from the -@scala[Producer trait]@java[@extref[UntypedProducerActor](github:akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala)] class. To customize a producer actor's default behavior you must override the -@scala[@extref[Producer](github:akka-camel/src/main/scala/akka/camel/Producer.scala).transformResponse]@java[@extref[UntypedProducerActor](github:akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala).onTransformResponse] and -@scala[@extref[Producer](github:akka-camel/src/main/scala/akka/camel/Producer.scala).transformOutgoingMessage methods]@java[@extref[UntypedProducerActor](github:akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala).onTransformOutgoingMessage methods]. This is explained later in more detail. -Producer Actors cannot override the @scala[default @extref[Producer](github:akka-camel/src/main/scala/akka/camel/Producer.scala).receive]@java[@extref[UntypedProducerActor](github:akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala).onReceive] method. - -Any message sent to a @scala[@extref[`Producer`](github:akka-camel/src/main/scala/akka/camel/Producer.scala)]@java[Producer] actor will be sent to -the associated Camel endpoint, in the above example to -`http://localhost:8080/news`. The @scala[@extref[`Producer`](github:akka-camel/src/main/scala/akka/camel/Producer.scala)]@java[@extref[`UntypedProducerActor`](github:akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala)] always sends messages asynchronously. Response messages (if supported by the -configured endpoint) will, by default, be returned to the original sender. The -following example uses the ask pattern to send a message to a -Producer actor and waits for a response. - -Scala -: @@snip [Producers.scala](/akka-docs/src/test/scala/docs/camel/Producers.scala) { #AskProducer } - -Java -: @@snip [ProducerTestBase.java](/akka-docs/src/test/java/jdocs/camel/ProducerTestBase.java) { #AskProducer } - -The future contains the response `CamelMessage`, or an `AkkaCamelException` when an error occurred, which contains the headers of the response. - - -### Custom Processing - -Instead of replying to the initial sender, producer actors can implement custom -response processing by overriding the @scala[`routeResponse`]@java[`onRouteResponse`] method. In the following example, the response -message is forwarded to a target actor instead of being replied to the original -sender. - -Scala -: @@snip [Producers.scala](/akka-docs/src/test/scala/docs/camel/Producers.scala) { #RouteResponse } - -Java -: @@snip [ResponseReceiver.java](/akka-docs/src/test/java/jdocs/camel/ResponseReceiver.java) { #RouteResponse } - @@snip [Forwarder.java](/akka-docs/src/test/java/jdocs/camel/Forwarder.java) { #RouteResponse } - @@snip [OnRouteResponseTestBase.java](/akka-docs/src/test/java/jdocs/camel/OnRouteResponseTestBase.java) { #RouteResponse } - -Before producing messages to endpoints, producer actors can pre-process them by -overriding the @scala[@extref[Producer](github:akka-camel/src/main/scala/akka/camel/Producer.scala).transformOutgoingMessage] -@java[@extref[UntypedProducerActor](github:akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala).onTransformOutgoingMessag] method. - -Scala -: @@snip [Producers.scala](/akka-docs/src/test/scala/docs/camel/Producers.scala) { #TransformOutgoingMessage } - -Java -: @@snip [Transformer.java](/akka-docs/src/test/java/jdocs/camel/Transformer.java) { #TransformOutgoingMessage } - -### Producer configuration options - -The interaction of producer actors with Camel endpoints can be configured to be -one-way or two-way (by initiating in-only or in-out message exchanges, -respectively). By default, the producer initiates an in-out message exchange -with the endpoint. For initiating an in-only exchange, producer actors have to override the @scala[`oneway`]@java[`isOneway`] method to return true. - -Scala -: @@snip [Producers.scala](/akka-docs/src/test/scala/docs/camel/Producers.scala) { #Oneway } - -Java -: @@snip [OnewaySender.java](/akka-docs/src/test/java/jdocs/camel/OnewaySender.java) { #Oneway } - -### Message correlation - -To correlate request with response messages, applications can set the -`Message.MessageExchangeId` message header. - -Scala -: @@snip [Producers.scala](/akka-docs/src/test/scala/docs/camel/Producers.scala) { #Correlate } - -Java -: @@snip [ProducerTestBase.java](/akka-docs/src/test/java/jdocs/camel/ProducerTestBase.java) { #Correlate } - -### ProducerTemplate - -The @scala[@extref[Producer](github:akka-camel/src/main/scala/akka/camel/Producer.scala) trait]@java[@extref[UntypedProducerActor](github:akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala) class] is a very -convenient way for actors to produce messages to Camel endpoints. Actors may also use a Camel -`ProducerTemplate` for producing messages to endpoints. - -Scala -: @@snip [Producers.scala](/akka-docs/src/test/scala/docs/camel/Producers.scala) { #ProducerTemplate } - -Java -: @@snip [MyActor.java](/akka-docs/src/test/java/jdocs/camel/MyActor.java) { #ProducerTemplate } - -For initiating a two-way message exchange, one of the -`ProducerTemplate.request*` methods must be used. - -Scala -: @@snip [Producers.scala](/akka-docs/src/test/scala/docs/camel/Producers.scala) { #RequestProducerTemplate } - -Java -: @@snip [RequestBodyActor.java](/akka-docs/src/test/java/jdocs/camel/RequestBodyActor.java) { #RequestProducerTemplate } - - -## Asynchronous routing - -In-out message exchanges between endpoints and actors are -designed to be asynchronous. This is the case for both, consumer and producer -actors. - - * A consumer endpoint sends request messages to its consumer actor using the @scala[`!` (tell) operator ]@java[`tell` method] -and the actor returns responses with @scala[`sender !`]@java[`getSender().tell`] once they are -ready. - * A producer actor sends request messages to its endpoint using Camel's -asynchronous routing engine. Asynchronous responses are wrapped and added to the -producer actor's mailbox for later processing. By default, response messages are -returned to the initial sender but this can be overridden by Producer -implementations (see also description of the @scala[`routeResponse`]@java[`onRouteResponse`] method -in [Custom Processing](#camel-custom-processing)). - -However, asynchronous two-way message exchanges, without allocating a thread for -the full duration of exchange, cannot be generically supported by Camel's -asynchronous routing engine alone. This must be supported by the individual -Camel components (from which endpoints are created) as well. They must be -able to suspend any work started for request processing (thereby freeing threads -to do other work) and resume processing when the response is ready. This is -currently the case for a [subset of components](http://camel.apache.org/asynchronous-routing-engine.html) -such as the Jetty component. -All other Camel components can still be used, but they will cause -allocation of a thread for the duration of an in-out message exchange. - -If the used Camel component is blocking it might be necessary to use a separate -@ref:[dispatcher](dispatchers.md) for the producer. The Camel processor is -invoked by a child actor of the producer and the dispatcher can be defined in -the deployment section of the configuration. For example, if your producer actor -has path `/user/integration/output` the dispatcher of the child actor can be -defined with: - -``` -akka.actor.deployment { - /integration/output/* { - dispatcher = my-dispatcher - } -} -``` - -## Custom Camel routes - -In all the examples so far, routes to consumer actors have been automatically -constructed by akka-camel, when the actor was started. Although the default -route construction templates, used by akka-camel internally, are sufficient for -most use cases, some applications may require more specialized routes to actors. -The akka-camel module provides two mechanisms for customizing routes to actors, -which will be explained in this section. These are: - - * Usage of [Akka Camel components](#camel-components) to access actors. -Any Camel route can use these components to access Akka actors. - * [Intercepting route construction](#camel-intercepting-route-construction) to actors. -This option gives you the ability to change routes that have already been added to Camel. -Consumer actors have a hook into the route definition process which can be used to change the route. - - -### Akka Camel components - -Akka actors can be accessed from Camel routes using the actor Camel component. This component can be used to -access any Akka actor (not only consumer actors) from Camel routes, as described in the following sections. - - -### Access to actors - -To access actors from custom Camel routes, the actor Camel -component should be used. It fully supports Camel's [asynchronous routing -engine](http://camel.apache.org/asynchronous-routing-engine.html). - -This component accepts the following endpoint URI format: - - * `[]?` - -where `` is the `ActorPath` to the actor. The `` are -name-value pairs separated by `&` (i.e. `name1=value1&name2=value2&...`). - -#### URI options - -The following URI options are supported: - -|Name | Type | Default | Description | -|-------------|----------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -|replyTimeout | Duration | false | The reply timeout, specified in the same way that you use the duration in akka, for instance `10 seconds` except that in the url it is handy to use a + between the amount and the unit, like for example `200+millis` See also [Consumer timeout](#camel-timeout).| -|autoAck | Boolean | true | If set to true, in-only message exchanges are auto-acknowledged when the message is added to the actor's mailbox. If set to false, actors must acknowledge the receipt of the message. See also [Delivery acknowledgements](#camel-acknowledgements). | - -Here's an actor endpoint URI example containing an actor path: - -``` -akka://some-system/user/myconsumer?autoAck=false&replyTimeout=100+millis -``` - -In the following example, a custom route to an actor is created, using the -actor's path. - -The Akka camel package contains an implicit `toActorRouteDefinition` that allows for a route to -reference an `ActorRef` directly as shown in the below example, The route starts from a [Jetty](http://www.eclipse.org/jetty/) endpoint and -ends at the target actor. - -Scala -: @@snip [CustomRoute.scala](/akka-docs/src/test/scala/docs/camel/CustomRoute.scala) { #CustomRoute } - -Java -: @@snip [Responder.java](/akka-docs/src/test/java/jdocs/camel/Responder.java) { #CustomRoute } - @@snip [CustomRouteBuilder.java](/akka-docs/src/test/java/jdocs/camel/CustomRouteBuilder.java) { #CustomRoute } - @@snip [CustomRouteTestBase.java](/akka-docs/src/test/java/jdocs/camel/CustomRouteTestBase.java) { #CustomRoute } - -@java[The `CamelPath.toCamelUri` converts the `ActorRef` to the Camel actor component URI format which points to the actor endpoint as described above.] -When a message is received on the jetty endpoint, it is routed to the `Responder` actor, which in return replies back to the client of -the HTTP request. - - -### Intercepting route construction - -The previous section, [camel components](#camel-components-2), explained how to setup a route to an actor manually. -It was the application's responsibility to define the route and add it to the current CamelContext. -This section explains a more convenient way to define custom routes: akka-camel is still setting up the routes to consumer actors (and adds these routes to the current CamelContext) but applications can define extensions to these routes. -Extensions can be defined with Camel's [Java DSL](http://camel.apache.org/dsl.html) or [Scala DSL](http://camel.apache.org/scala-dsl.html). -For example, an extension could be a custom error handler that redelivers messages from an endpoint to an actor's bounded mailbox when the mailbox was full. - -The following examples demonstrate how to extend a route to a consumer actor for -handling exceptions thrown by that actor. - -Scala -: @@snip [CustomRoute.scala](/akka-docs/src/test/scala/docs/camel/CustomRoute.scala) { #ErrorThrowingConsumer } - -Java -: @@snip [ErrorThrowingConsumer.java](/akka-docs/src/test/java/jdocs/camel/ErrorThrowingConsumer.java) { #ErrorThrowingConsumer } - -The above ErrorThrowingConsumer sends the Failure back to the sender in preRestart -because the Exception that is thrown in the actor would -otherwise just crash the actor, by default the actor would be restarted, and the response would never reach the client of the Consumer. - -The akka-camel module creates a RouteDefinition instance by calling -from(endpointUri) on a Camel RouteBuilder (where endpointUri is the endpoint URI -of the consumer actor) and passes that instance as argument to the route -definition handler *). The route definition handler then extends the route and -returns a ProcessorDefinition (in the above example, the ProcessorDefinition -returned by the end method. See the [org.apache.camel.model](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/model/) package for -details). After executing the route definition handler, akka-camel finally calls -a to(targetActorUri) on the returned ProcessorDefinition to complete the -route to the consumer actor (where targetActorUri is the actor component URI as described in [Access to actors](#access-to-actors)). -If the actor cannot be found, a `ActorNotRegisteredException` is thrown. - -*) Before passing the RouteDefinition instance to the route definition handler, -akka-camel may make some further modifications to it. - -## Configuration - -There are several configuration properties for the Camel module, please refer -to the @ref:[reference configuration](general/configuration.md#config-akka-camel). - -## Additional Resources - -For an introduction to akka-camel 2, see also the Peter Gabryanczyk's talk [Migrating akka-camel module to Akka 2.x](http://skillsmatter.com/podcast/scala/akka-2-x). - -For an introduction to akka-camel 1, see also the [Appendix E - Akka and Camel](http://www.manning.com/ibsen/appEsample.pdf) -(pdf) of the book [Camel in Action](http://www.manning.com/ibsen/). - -Other, more advanced external articles (for version 1) are: - - * [Akka Consumer Actors: New Features and Best Practices](http://krasserm.blogspot.com/2011/02/akka-consumer-actors-new-features-and.html) - * [Akka Producer Actors: New Features and Best Practices](http://krasserm.blogspot.com/2011/02/akka-producer-actor-new-features-and.html) +If anyone is interested in setting up akka-camel as a separate community-maintained repository then please get in touch. \ No newline at end of file diff --git a/akka-docs/src/main/paradox/general/configuration.md b/akka-docs/src/main/paradox/general/configuration.md index 1b1e7d60f4..551969b77a 100644 --- a/akka-docs/src/main/paradox/general/configuration.md +++ b/akka-docs/src/main/paradox/general/configuration.md @@ -429,11 +429,6 @@ Each Akka module has a reference configuration file with the default values. @@snip [reference.conf](/akka-agent/src/main/resources/reference.conf) - -### akka-camel - -@@snip [reference.conf](/akka-camel/src/main/resources/reference.conf) - ### akka-cluster diff --git a/akka-docs/src/main/paradox/index-network.md b/akka-docs/src/main/paradox/index-network.md index f35f593501..96d54aa15d 100644 --- a/akka-docs/src/main/paradox/index-network.md +++ b/akka-docs/src/main/paradox/index-network.md @@ -11,6 +11,5 @@ * [io-tcp](io-tcp.md) * [io-udp](io-udp.md) * [io-dns](io-dns.md) -* [camel](camel.md) @@@ diff --git a/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md b/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md index 1d171089cd..2d1f79d348 100644 --- a/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md +++ b/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md @@ -1,5 +1,14 @@ # Migration Guide 2.5.x to 2.6.x +## akka-camel removed + +After being deprecated in 2.5.0, the akka-camel module has been removed in 2.6. +As an alternative we recommend [Alpakka](https://doc.akka.io/docs/alpakka/current/). + +This is of course not a drop-in replacement. If there is community interest we +are open to setting up akka-camel as a separate community-maintained +repository. + ## Scala 2.11 no longer supported If you are still using Scala 2.11 then you must upgrade to 2.12 or 2.13 diff --git a/akka-docs/src/test/java/jdocs/camel/ActivationTestBase.java b/akka-docs/src/test/java/jdocs/camel/ActivationTestBase.java deleted file mode 100644 index 4ce572fc9b..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/ActivationTestBase.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #CamelActivation -import akka.actor.ActorRef; -import akka.actor.ActorSystem; -import akka.actor.Props; -import akka.camel.Camel; -import akka.camel.CamelExtension; -import akka.camel.javaapi.UntypedConsumerActor; -import akka.testkit.javadsl.TestKit; -import akka.util.Timeout; -import jdocs.AbstractJavaTest; -import scala.concurrent.Future; -import scala.concurrent.duration.Duration; -import static java.util.concurrent.TimeUnit.SECONDS; -// #CamelActivation - -import org.junit.Test; - -public class ActivationTestBase extends AbstractJavaTest { - - @SuppressWarnings("unused") - @Test - public void testActivation() { - // #CamelActivation - - // .. - ActorSystem system = ActorSystem.create("some-system"); - Props props = Props.create(MyConsumer.class); - ActorRef producer = system.actorOf(props, "myproducer"); - Camel camel = CamelExtension.get(system); - // get a future reference to the activation of the endpoint of the Consumer Actor - Timeout timeout = new Timeout(Duration.create(10, SECONDS)); - Future activationFuture = - camel.activationFutureFor(producer, timeout, system.dispatcher()); - // #CamelActivation - // #CamelDeactivation - // .. - system.stop(producer); - // get a future reference to the deactivation of the endpoint of the Consumer Actor - Future deactivationFuture = - camel.deactivationFutureFor(producer, timeout, system.dispatcher()); - // #CamelDeactivation - TestKit.shutdownActorSystem(system); - } - - public static class MyConsumer extends UntypedConsumerActor { - public String getEndpointUri() { - return "direct:test"; - } - - public void onReceive(Object message) {} - } -} diff --git a/akka-docs/src/test/java/jdocs/camel/CamelExtensionTest.java b/akka-docs/src/test/java/jdocs/camel/CamelExtensionTest.java deleted file mode 100644 index 041fe3909c..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/CamelExtensionTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; - -import akka.actor.ActorSystem; -import akka.camel.Camel; -import akka.camel.CamelExtension; -import jdocs.AbstractJavaTest; -import akka.testkit.javadsl.TestKit; -import org.apache.camel.CamelContext; -import org.apache.camel.ProducerTemplate; -import org.junit.Test; - -public class CamelExtensionTest extends AbstractJavaTest { - @Test - public void getCamelExtension() { - // #CamelExtension - ActorSystem system = ActorSystem.create("some-system"); - Camel camel = CamelExtension.get(system); - CamelContext camelContext = camel.context(); - ProducerTemplate producerTemplate = camel.template(); - // #CamelExtension - TestKit.shutdownActorSystem(system); - } - - public void addActiveMQComponent() { - // #CamelExtensionAddComponent - ActorSystem system = ActorSystem.create("some-system"); - Camel camel = CamelExtension.get(system); - CamelContext camelContext = camel.context(); - // camelContext.addComponent("activemq", ActiveMQComponent.activeMQComponent( - // "vm://localhost?broker.persistent=false")); - // #CamelExtensionAddComponent - TestKit.shutdownActorSystem(system); - } -} diff --git a/akka-docs/src/test/java/jdocs/camel/Consumer1.java b/akka-docs/src/test/java/jdocs/camel/Consumer1.java deleted file mode 100644 index 418ed9bd35..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/Consumer1.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #Consumer1 -import akka.camel.CamelMessage; -import akka.camel.javaapi.UntypedConsumerActor; -import akka.event.Logging; -import akka.event.LoggingAdapter; - -public class Consumer1 extends UntypedConsumerActor { - LoggingAdapter log = Logging.getLogger(getContext().system(), this); - - public String getEndpointUri() { - return "file:data/input/actor"; - } - - public void onReceive(Object message) { - if (message instanceof CamelMessage) { - CamelMessage camelMessage = (CamelMessage) message; - String body = camelMessage.getBodyAs(String.class, getCamelContext()); - log.info("Received message: {}", body); - } else unhandled(message); - } -} -// #Consumer1 diff --git a/akka-docs/src/test/java/jdocs/camel/Consumer2.java b/akka-docs/src/test/java/jdocs/camel/Consumer2.java deleted file mode 100644 index bbace1c693..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/Consumer2.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #Consumer2 -import akka.camel.CamelMessage; -import akka.camel.javaapi.UntypedConsumerActor; - -public class Consumer2 extends UntypedConsumerActor { - public String getEndpointUri() { - return "jetty:http://localhost:8877/camel/default"; - } - - public void onReceive(Object message) { - if (message instanceof CamelMessage) { - CamelMessage camelMessage = (CamelMessage) message; - String body = camelMessage.getBodyAs(String.class, getCamelContext()); - getSender().tell(String.format("Received message: %s", body), getSelf()); - } else unhandled(message); - } -} -// #Consumer2 diff --git a/akka-docs/src/test/java/jdocs/camel/Consumer3.java b/akka-docs/src/test/java/jdocs/camel/Consumer3.java deleted file mode 100644 index d1f78dfe01..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/Consumer3.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #Consumer3 -import akka.actor.Status; -import akka.camel.Ack; -import akka.camel.CamelMessage; -import akka.camel.javaapi.UntypedConsumerActor; - -public class Consumer3 extends UntypedConsumerActor { - - @Override - public boolean autoAck() { - return false; - } - - public String getEndpointUri() { - return "jms:queue:test"; - } - - public void onReceive(Object message) { - if (message instanceof CamelMessage) { - getSender().tell(Ack.getInstance(), getSelf()); - // on success - // .. - Exception someException = new Exception("e1"); - // on failure - getSender().tell(new Status.Failure(someException), getSelf()); - } else unhandled(message); - } -} -// #Consumer3 diff --git a/akka-docs/src/test/java/jdocs/camel/Consumer4.java b/akka-docs/src/test/java/jdocs/camel/Consumer4.java deleted file mode 100644 index 54fd1f159e..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/Consumer4.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #Consumer4 -import akka.camel.CamelMessage; -import akka.camel.javaapi.UntypedConsumerActor; -import scala.concurrent.duration.Duration; -import scala.concurrent.duration.FiniteDuration; - -import java.util.concurrent.TimeUnit; - -public class Consumer4 extends UntypedConsumerActor { - private static final FiniteDuration timeout = Duration.create(500, TimeUnit.MILLISECONDS); - - @Override - public FiniteDuration replyTimeout() { - return timeout; - } - - public String getEndpointUri() { - return "jetty:http://localhost:8877/camel/default"; - } - - public void onReceive(Object message) { - if (message instanceof CamelMessage) { - CamelMessage camelMessage = (CamelMessage) message; - String body = camelMessage.getBodyAs(String.class, getCamelContext()); - getSender().tell(String.format("Hello %s", body), getSelf()); - } else unhandled(message); - } -} -// #Consumer4 diff --git a/akka-docs/src/test/java/jdocs/camel/CustomRouteBuilder.java b/akka-docs/src/test/java/jdocs/camel/CustomRouteBuilder.java deleted file mode 100644 index bebeb449a6..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/CustomRouteBuilder.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #CustomRoute -import akka.actor.ActorRef; -import akka.camel.internal.component.CamelPath; -import org.apache.camel.builder.RouteBuilder; - -public class CustomRouteBuilder extends RouteBuilder { - private String uri; - - public CustomRouteBuilder(ActorRef responder) { - uri = CamelPath.toUri(responder); - } - - public void configure() throws Exception { - from("jetty:http://localhost:8877/camel/custom").to(uri); - } -} -// #CustomRoute diff --git a/akka-docs/src/test/java/jdocs/camel/CustomRouteTestBase.java b/akka-docs/src/test/java/jdocs/camel/CustomRouteTestBase.java deleted file mode 100644 index b05978f00e..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/CustomRouteTestBase.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; - -import akka.actor.ActorRef; -import akka.actor.ActorSystem; -import akka.actor.Props; -import akka.camel.Camel; -import akka.camel.CamelExtension; -import akka.testkit.javadsl.TestKit; - -public class CustomRouteTestBase { - public void customRoute() throws Exception { - // #CustomRoute - ActorSystem system = ActorSystem.create("some-system"); - try { - Camel camel = CamelExtension.get(system); - ActorRef responder = system.actorOf(Props.create(Responder.class), "TestResponder"); - camel.context().addRoutes(new CustomRouteBuilder(responder)); - // #CustomRoute - } finally { - TestKit.shutdownActorSystem(system); - } - } -} diff --git a/akka-docs/src/test/java/jdocs/camel/ErrorThrowingConsumer.java b/akka-docs/src/test/java/jdocs/camel/ErrorThrowingConsumer.java deleted file mode 100644 index f77a6cfb2f..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/ErrorThrowingConsumer.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #ErrorThrowingConsumer -import akka.actor.Status; -import akka.camel.CamelMessage; -import akka.camel.javaapi.UntypedConsumerActor; -import akka.dispatch.Mapper; -import org.apache.camel.builder.Builder; -import org.apache.camel.model.ProcessorDefinition; -import org.apache.camel.model.RouteDefinition; -import scala.Option; - -public class ErrorThrowingConsumer extends UntypedConsumerActor { - private String uri; - - private static Mapper> mapper = - new Mapper>() { - public ProcessorDefinition apply(RouteDefinition rd) { - // Catch any exception and handle it by returning the exception message - // as response - return rd.onException(Exception.class) - .handled(true) - .transform(Builder.exceptionMessage()) - .end(); - } - }; - - public ErrorThrowingConsumer(String uri) { - this.uri = uri; - } - - public String getEndpointUri() { - return uri; - } - - public void onReceive(Object message) throws Exception { - if (message instanceof CamelMessage) { - CamelMessage camelMessage = (CamelMessage) message; - String body = camelMessage.getBodyAs(String.class, getCamelContext()); - throw new Exception(String.format("error: %s", body)); - } else unhandled(message); - } - - @Override - public Mapper> getRouteDefinitionHandler() { - return mapper; - } - - @Override - public void preRestart(Throwable reason, Option message) { - getSender().tell(new Status.Failure(reason), getSelf()); - } -} -// #ErrorThrowingConsumer diff --git a/akka-docs/src/test/java/jdocs/camel/FirstProducer.java b/akka-docs/src/test/java/jdocs/camel/FirstProducer.java deleted file mode 100644 index d2e24184f2..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/FirstProducer.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; - -// #Producer1 -import akka.camel.javaapi.UntypedProducerActor; - -public class FirstProducer extends UntypedProducerActor { - public String getEndpointUri() { - return "http://localhost:8080/news"; - } -} -// #Producer1 diff --git a/akka-docs/src/test/java/jdocs/camel/Forwarder.java b/akka-docs/src/test/java/jdocs/camel/Forwarder.java deleted file mode 100644 index 854e6d357c..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/Forwarder.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #RouteResponse -import akka.actor.ActorRef; -import akka.camel.javaapi.UntypedProducerActor; - -public class Forwarder extends UntypedProducerActor { - private String uri; - private ActorRef target; - - public Forwarder(String uri, ActorRef target) { - this.uri = uri; - this.target = target; - } - - public String getEndpointUri() { - return uri; - } - - @Override - public void onRouteResponse(Object message) { - target.forward(message, getContext()); - } -} -// #RouteResponse diff --git a/akka-docs/src/test/java/jdocs/camel/MyActor.java b/akka-docs/src/test/java/jdocs/camel/MyActor.java deleted file mode 100644 index 419dfc2f5e..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/MyActor.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #ProducerTemplate -import akka.actor.UntypedAbstractActor; -import akka.camel.Camel; -import akka.camel.CamelExtension; -import org.apache.camel.ProducerTemplate; - -public class MyActor extends UntypedAbstractActor { - public void onReceive(Object message) { - Camel camel = CamelExtension.get(getContext().getSystem()); - ProducerTemplate template = camel.template(); - template.sendBody("direct:news", message); - } -} -// #ProducerTemplate diff --git a/akka-docs/src/test/java/jdocs/camel/MyEndpoint.java b/akka-docs/src/test/java/jdocs/camel/MyEndpoint.java deleted file mode 100644 index 7db8164306..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/MyEndpoint.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; - -// #Consumer-mina -import akka.camel.CamelMessage; -import akka.camel.javaapi.UntypedConsumerActor; - -public class MyEndpoint extends UntypedConsumerActor { - private String uri; - - public String getEndpointUri() { - return uri; - } - - public void onReceive(Object message) throws Exception { - if (message instanceof CamelMessage) { - /* ... */ - } else unhandled(message); - } - - // Extra constructor to change the default uri, - // for instance to "jetty:http://localhost:8877/example" - public MyEndpoint(String uri) { - this.uri = uri; - } - - public MyEndpoint() { - this.uri = "mina2:tcp://localhost:6200?textline=true"; - } -} -// #Consumer-mina diff --git a/akka-docs/src/test/java/jdocs/camel/OnRouteResponseTestBase.java b/akka-docs/src/test/java/jdocs/camel/OnRouteResponseTestBase.java deleted file mode 100644 index 2f589adad4..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/OnRouteResponseTestBase.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; - -import akka.actor.*; -import akka.testkit.javadsl.TestKit; - -public class OnRouteResponseTestBase { - - public void onRouteResponse() { - // #RouteResponse - ActorSystem system = ActorSystem.create("some-system"); - Props receiverProps = Props.create(ResponseReceiver.class); - final ActorRef receiver = system.actorOf(receiverProps, "responseReceiver"); - ActorRef forwardResponse = - system.actorOf(Props.create(Forwarder.class, "http://localhost:8080/news/akka", receiver)); - // the Forwarder sends out a request to the web page and forwards the response to - // the ResponseReceiver - forwardResponse.tell("some request", ActorRef.noSender()); - // #RouteResponse - system.stop(receiver); - system.stop(forwardResponse); - TestKit.shutdownActorSystem(system); - } -} diff --git a/akka-docs/src/test/java/jdocs/camel/OnewaySender.java b/akka-docs/src/test/java/jdocs/camel/OnewaySender.java deleted file mode 100644 index 15ac577eba..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/OnewaySender.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #Oneway -import akka.camel.javaapi.UntypedProducerActor; - -public class OnewaySender extends UntypedProducerActor { - private String uri; - - public OnewaySender(String uri) { - this.uri = uri; - } - - public String getEndpointUri() { - return uri; - } - - @Override - public boolean isOneway() { - return true; - } -} -// #Oneway diff --git a/akka-docs/src/test/java/jdocs/camel/Orders.java b/akka-docs/src/test/java/jdocs/camel/Orders.java deleted file mode 100644 index 219b102b50..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/Orders.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #Producer -import akka.camel.javaapi.UntypedProducerActor; - -public class Orders extends UntypedProducerActor { - public String getEndpointUri() { - return "jms:queue:Orders"; - } -} -// #Producer diff --git a/akka-docs/src/test/java/jdocs/camel/Producer1.java b/akka-docs/src/test/java/jdocs/camel/Producer1.java deleted file mode 100644 index 3e2788620d..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/Producer1.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #Producer1 -import akka.camel.javaapi.UntypedProducerActor; - -public class Producer1 extends UntypedProducerActor { - public String getEndpointUri() { - return "http://localhost:8080/news"; - } -} -// #Producer1 diff --git a/akka-docs/src/test/java/jdocs/camel/ProducerTestBase.java b/akka-docs/src/test/java/jdocs/camel/ProducerTestBase.java deleted file mode 100644 index beacde3d13..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/ProducerTestBase.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; - -import java.time.Duration; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletionStage; - -import akka.pattern.Patterns; -import akka.testkit.javadsl.TestKit; -import akka.actor.ActorRef; -import akka.actor.ActorSystem; -import akka.actor.Props; -import akka.camel.CamelMessage; - -public class ProducerTestBase { - public void tellJmsProducer() { - // #TellProducer - ActorSystem system = ActorSystem.create("some-system"); - Props props = Props.create(Orders.class); - ActorRef producer = system.actorOf(props, "jmsproducer"); - producer.tell("", ActorRef.noSender()); - // #TellProducer - TestKit.shutdownActorSystem(system); - } - - @SuppressWarnings("unused") - public void askProducer() { - // #AskProducer - ActorSystem system = ActorSystem.create("some-system"); - Props props = Props.create(FirstProducer.class); - ActorRef producer = system.actorOf(props, "myproducer"); - CompletionStage future = - Patterns.ask(producer, "some request", Duration.ofMillis(1000L)); - // #AskProducer - system.stop(producer); - TestKit.shutdownActorSystem(system); - } - - public void correlate() { - // #Correlate - ActorSystem system = ActorSystem.create("some-system"); - Props props = Props.create(Orders.class); - ActorRef producer = system.actorOf(props, "jmsproducer"); - Map headers = new HashMap(); - headers.put(CamelMessage.MessageExchangeId(), "123"); - producer.tell( - new CamelMessage("", headers), - ActorRef.noSender()); - // #Correlate - system.stop(producer); - TestKit.shutdownActorSystem(system); - } -} diff --git a/akka-docs/src/test/java/jdocs/camel/RequestBodyActor.java b/akka-docs/src/test/java/jdocs/camel/RequestBodyActor.java deleted file mode 100644 index 817f7b8928..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/RequestBodyActor.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #RequestProducerTemplate -import akka.actor.AbstractActor; -import akka.camel.Camel; -import akka.camel.CamelExtension; -import org.apache.camel.ProducerTemplate; - -public class RequestBodyActor extends AbstractActor { - @Override - public Receive createReceive() { - return receiveBuilder() - .matchAny( - message -> { - Camel camel = CamelExtension.get(getContext().getSystem()); - ProducerTemplate template = camel.template(); - getSender().tell(template.requestBody("direct:news", message), getSelf()); - }) - .build(); - } -} -// #RequestProducerTemplate diff --git a/akka-docs/src/test/java/jdocs/camel/Responder.java b/akka-docs/src/test/java/jdocs/camel/Responder.java deleted file mode 100644 index 4e79a12e1e..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/Responder.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #CustomRoute -import akka.actor.UntypedAbstractActor; -import akka.camel.CamelMessage; -import akka.dispatch.Mapper; - -public class Responder extends UntypedAbstractActor { - - public void onReceive(Object message) { - if (message instanceof CamelMessage) { - CamelMessage camelMessage = (CamelMessage) message; - getSender().tell(createResponse(camelMessage), getSelf()); - } else unhandled(message); - } - - private CamelMessage createResponse(CamelMessage msg) { - return msg.mapBody( - new Mapper() { - @Override - public String apply(String body) { - return String.format("received %s", body); - } - }); - } -} -// #CustomRoute diff --git a/akka-docs/src/test/java/jdocs/camel/ResponseReceiver.java b/akka-docs/src/test/java/jdocs/camel/ResponseReceiver.java deleted file mode 100644 index efdd75860c..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/ResponseReceiver.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #RouteResponse -import akka.actor.UntypedAbstractActor; -import akka.camel.CamelMessage; - -public class ResponseReceiver extends UntypedAbstractActor { - public void onReceive(Object message) { - if (message instanceof CamelMessage) { - // do something with the forwarded response - } - } -} -// #RouteResponse diff --git a/akka-docs/src/test/java/jdocs/camel/Transformer.java b/akka-docs/src/test/java/jdocs/camel/Transformer.java deleted file mode 100644 index a18cf7781b..0000000000 --- a/akka-docs/src/test/java/jdocs/camel/Transformer.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.camel; -// #TransformOutgoingMessage -import akka.camel.CamelMessage; -import akka.camel.javaapi.UntypedProducerActor; -import akka.dispatch.Mapper; - -public class Transformer extends UntypedProducerActor { - private String uri; - - public Transformer(String uri) { - this.uri = uri; - } - - public String getEndpointUri() { - return uri; - } - - private CamelMessage upperCase(CamelMessage msg) { - return msg.mapBody( - new Mapper() { - @Override - public String apply(String body) { - return body.toUpperCase(); - } - }); - } - - @Override - public Object onTransformOutgoingMessage(Object message) { - if (message instanceof CamelMessage) { - CamelMessage camelMessage = (CamelMessage) message; - return upperCase(camelMessage); - } else { - return message; - } - } -} -// #TransformOutgoingMessage diff --git a/akka-docs/src/test/scala/docs/camel/Consumers.scala b/akka-docs/src/test/scala/docs/camel/Consumers.scala deleted file mode 100644 index b3cca5bbf5..0000000000 --- a/akka-docs/src/test/scala/docs/camel/Consumers.scala +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package docs.camel - -import language.postfixOps - -object Consumers { - object Sample1 { - //#Consumer1 - import akka.camel.{ CamelMessage, Consumer } - - class Consumer1 extends Consumer { - def endpointUri = "file:data/input/actor" - - def receive = { - case msg: CamelMessage => println("received %s".format(msg.bodyAs[String])) - } - } - //#Consumer1 - } - object Sample2 { - //#Consumer2 - import akka.camel.{ CamelMessage, Consumer } - - class Consumer2 extends Consumer { - def endpointUri = "jetty:http://localhost:8877/camel/default" - - def receive = { - case msg: CamelMessage => sender() ! ("Hello %s".format(msg.bodyAs[String])) - } - } - //#Consumer2 - } - object Sample3 { - //#Consumer3 - import akka.camel.{ CamelMessage, Consumer } - import akka.camel.Ack - import akka.actor.Status.Failure - - class Consumer3 extends Consumer { - override def autoAck = false - - def endpointUri = "jms:queue:test" - - def receive = { - case msg: CamelMessage => - sender() ! Ack - // on success - // .. - val someException = new Exception("e1") - // on failure - sender() ! Failure(someException) - } - } - //#Consumer3 - } - object Sample4 { - //#Consumer4 - import akka.camel.{ CamelMessage, Consumer } - import scala.concurrent.duration._ - - class Consumer4 extends Consumer { - def endpointUri = "jetty:http://localhost:8877/camel/default" - override def replyTimeout = 500 millis - def receive = { - case msg: CamelMessage => sender() ! ("Hello %s".format(msg.bodyAs[String])) - } - } - //#Consumer4 - } -} diff --git a/akka-docs/src/test/scala/docs/camel/CustomRoute.scala b/akka-docs/src/test/scala/docs/camel/CustomRoute.scala deleted file mode 100644 index 59ec0ef35d..0000000000 --- a/akka-docs/src/test/scala/docs/camel/CustomRoute.scala +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package docs.camel - -import akka.camel.CamelMessage -import akka.actor.Status.Failure - -import language.existentials - -object CustomRoute { - object Sample1 { - //#CustomRoute - import akka.actor.{ Actor, ActorRef, ActorSystem, Props } - import akka.camel.{ CamelExtension, CamelMessage } - import org.apache.camel.builder.RouteBuilder - import akka.camel._ - class Responder extends Actor { - def receive = { - case msg: CamelMessage => - sender() ! (msg.mapBody { body: String => - "received %s".format(body) - }) - } - } - - class CustomRouteBuilder(system: ActorSystem, responder: ActorRef) extends RouteBuilder { - def configure: Unit = { - from("jetty:http://localhost:8877/camel/custom").to(responder) - } - } - val system = ActorSystem("some-system") - val camel = CamelExtension(system) - val responder = system.actorOf(Props[Responder], name = "TestResponder") - camel.context.addRoutes(new CustomRouteBuilder(system, responder)) - //#CustomRoute - - } - object Sample2 { - //#ErrorThrowingConsumer - import akka.camel.Consumer - - import org.apache.camel.builder.Builder - import org.apache.camel.model.RouteDefinition - - class ErrorThrowingConsumer(override val endpointUri: String) extends Consumer { - def receive = { - case msg: CamelMessage => throw new Exception("error: %s".format(msg.body)) - } - override def onRouteDefinition = - (rd) => rd.onException(classOf[Exception]).handled(true).transform(Builder.exceptionMessage).end - - final override def preRestart(reason: Throwable, message: Option[Any]): Unit = { - sender() ! Failure(reason) - } - } - //#ErrorThrowingConsumer - } - -} diff --git a/akka-docs/src/test/scala/docs/camel/Introduction.scala b/akka-docs/src/test/scala/docs/camel/Introduction.scala deleted file mode 100644 index ad78f8a986..0000000000 --- a/akka-docs/src/test/scala/docs/camel/Introduction.scala +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package docs.camel - -//#imports -import akka.actor.{ ActorSystem, Props } -import akka.camel.CamelExtension - -import language.postfixOps -import akka.util.Timeout -//#imports - -object Introduction { - def foo(): Unit = { - //#Consumer-mina - import akka.camel.{ CamelMessage, Consumer } - - class MyEndpoint extends Consumer { - def endpointUri = "mina2:tcp://localhost:6200?textline=true" - - def receive = { - case msg: CamelMessage => { /* ... */ } - case _ => { /* ... */ } - } - } - - // start and expose actor via tcp - import akka.actor.{ ActorSystem, Props } - - val system = ActorSystem("some-system") - val mina = system.actorOf(Props[MyEndpoint]) - //#Consumer-mina - } - def bar(): Unit = { - //#Consumer - import akka.camel.{ CamelMessage, Consumer } - - class MyEndpoint extends Consumer { - def endpointUri = "jetty:http://localhost:8877/example" - - def receive = { - case msg: CamelMessage => { /* ... */ } - case _ => { /* ... */ } - } - } - //#Consumer - } - def baz(): Unit = { - //#Producer - import akka.actor.Actor - import akka.camel.{ Oneway, Producer } - import akka.actor.{ ActorSystem, Props } - - class Orders extends Actor with Producer with Oneway { - def endpointUri = "jms:queue:Orders" - } - - val sys = ActorSystem("some-system") - val orders = sys.actorOf(Props[Orders]) - - orders ! - //#Producer - } - { - //#CamelExtension - val system = ActorSystem("some-system") - val camel = CamelExtension(system) - val camelContext = camel.context - val producerTemplate = camel.template - - //#CamelExtension - } - { - //#CamelExtensionAddComponent - // import org.apache.activemq.camel.component.ActiveMQComponent - val system = ActorSystem("some-system") - val camel = CamelExtension(system) - val camelContext = camel.context - // camelContext.addComponent("activemq", ActiveMQComponent.activeMQComponent( - // "vm://localhost?broker.persistent=false")) - //#CamelExtensionAddComponent - } - { - //#CamelActivation - import akka.camel.{ CamelMessage, Consumer } - import scala.concurrent.duration._ - - class MyEndpoint extends Consumer { - def endpointUri = "mina2:tcp://localhost:6200?textline=true" - - def receive = { - case msg: CamelMessage => { /* ... */ } - case _ => { /* ... */ } - } - } - val system = ActorSystem("some-system") - val camel = CamelExtension(system) - val actorRef = system.actorOf(Props[MyEndpoint]) - // get a future reference to the activation of the endpoint of the Consumer Actor - val activationFuture = camel.activationFutureFor(actorRef)(timeout = 10 seconds, executor = system.dispatcher) - //#CamelActivation - //#CamelDeactivation - system.stop(actorRef) - // get a future reference to the deactivation of the endpoint of the Consumer Actor - val deactivationFuture = camel.deactivationFutureFor(actorRef)(timeout = 10 seconds, executor = system.dispatcher) - //#CamelDeactivation - } - -} diff --git a/akka-docs/src/test/scala/docs/camel/Producers.scala b/akka-docs/src/test/scala/docs/camel/Producers.scala deleted file mode 100644 index ff6ffe9b5a..0000000000 --- a/akka-docs/src/test/scala/docs/camel/Producers.scala +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package docs.camel - -import akka.camel.CamelExtension -import language.postfixOps - -object Producers { - object Sample1 { - //#Producer1 - import akka.actor.Actor - import akka.actor.{ ActorSystem, Props } - import akka.camel.{ CamelMessage, Producer } - import akka.util.Timeout - - class Producer1 extends Actor with Producer { - def endpointUri = "http://localhost:8080/news" - } - //#Producer1 - //#AskProducer - import akka.pattern.ask - import scala.concurrent.duration._ - implicit val timeout = Timeout(10 seconds) - - val system = ActorSystem("some-system") - val producer = system.actorOf(Props[Producer1]) - val future = producer.ask("some request").mapTo[CamelMessage] - //#AskProducer - } - object Sample2 { - //#RouteResponse - import akka.actor.{ Actor, ActorRef } - import akka.camel.{ CamelMessage, Producer } - import akka.actor.{ ActorSystem, Props } - - class ResponseReceiver extends Actor { - def receive = { - case msg: CamelMessage => - // do something with the forwarded response - } - } - - class Forwarder(uri: String, target: ActorRef) extends Actor with Producer { - def endpointUri = uri - - override def routeResponse(msg: Any): Unit = { target.forward(msg) } - } - val system = ActorSystem("some-system") - val receiver = system.actorOf(Props[ResponseReceiver]) - val forwardResponse = system.actorOf(Props(classOf[Forwarder], this, "http://localhost:8080/news/akka", receiver)) - // the Forwarder sends out a request to the web page and forwards the response to - // the ResponseReceiver - forwardResponse ! "some request" - //#RouteResponse - } - object Sample3 { - //#TransformOutgoingMessage - import akka.actor.Actor - import akka.camel.{ CamelMessage, Producer } - - class Transformer(uri: String) extends Actor with Producer { - def endpointUri = uri - - def upperCase(msg: CamelMessage) = msg.mapBody { body: String => - body.toUpperCase - } - - override def transformOutgoingMessage(msg: Any) = msg match { - case msg: CamelMessage => upperCase(msg) - } - } - //#TransformOutgoingMessage - } - object Sample4 { - //#Oneway - import akka.actor.{ Actor, ActorSystem, Props } - import akka.camel.Producer - - class OnewaySender(uri: String) extends Actor with Producer { - def endpointUri = uri - override def oneway: Boolean = true - } - - val system = ActorSystem("some-system") - val producer = system.actorOf(Props(classOf[OnewaySender], this, "activemq:FOO.BAR")) - producer ! "Some message" - //#Oneway - - } - object Sample5 { - //#Correlate - import akka.camel.{ CamelMessage, Producer } - import akka.actor.Actor - import akka.actor.{ ActorSystem, Props } - - class Producer2 extends Actor with Producer { - def endpointUri = "activemq:FOO.BAR" - } - val system = ActorSystem("some-system") - val producer = system.actorOf(Props[Producer2]) - - producer ! CamelMessage("bar", Map(CamelMessage.MessageExchangeId -> "123")) - //#Correlate - } - object Sample6 { - //#ProducerTemplate - import akka.actor.Actor - class MyActor extends Actor { - def receive = { - case msg => - val template = CamelExtension(context.system).template - template.sendBody("direct:news", msg) - } - } - //#ProducerTemplate - } - object Sample7 { - //#RequestProducerTemplate - import akka.actor.Actor - class MyActor extends Actor { - def receive = { - case msg => - val template = CamelExtension(context.system).template - sender() ! template.requestBody("direct:news", msg) - } - } - //#RequestProducerTemplate - } - -} diff --git a/akka-docs/src/test/scala/docs/camel/PublishSubscribe.scala b/akka-docs/src/test/scala/docs/camel/PublishSubscribe.scala deleted file mode 100644 index ba70dbda91..0000000000 --- a/akka-docs/src/test/scala/docs/camel/PublishSubscribe.scala +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package docs.camel - -object PublishSubscribe { - //#PubSub - import akka.actor.{ Actor, ActorRef, ActorSystem, Props } - import akka.camel.{ CamelMessage, Consumer, Producer } - - class Subscriber(name: String, uri: String) extends Actor with Consumer { - def endpointUri = uri - - def receive = { - case msg: CamelMessage => println("%s received: %s".format(name, msg.body)) - } - } - - class Publisher(name: String, uri: String) extends Actor with Producer { - - def endpointUri = uri - - // one-way communication with JMS - override def oneway = true - } - - class PublisherBridge(uri: String, publisher: ActorRef) extends Actor with Consumer { - def endpointUri = uri - - def receive = { - case msg: CamelMessage => { - publisher ! msg.bodyAs[String] - sender() ! ("message published") - } - } - } - - // Add below to a Boot class - // Setup publish/subscribe example - val system = ActorSystem("some-system") - val jmsUri = "jms:topic:test" - val jmsSubscriber1 = system.actorOf(Props(classOf[Subscriber], "jms-subscriber-1", jmsUri)) - val jmsSubscriber2 = system.actorOf(Props(classOf[Subscriber], "jms-subscriber-2", jmsUri)) - val jmsPublisher = system.actorOf(Props(classOf[Publisher], "jms-publisher", jmsUri)) - val jmsPublisherBridge = - system.actorOf(Props(classOf[PublisherBridge], "jetty:http://0.0.0.0:8877/camel/pub/jms", jmsPublisher)) - //#PubSub -} diff --git a/build.sbt b/build.sbt index 2efd9bc062..e85cd33c99 100644 --- a/build.sbt +++ b/build.sbt @@ -43,7 +43,6 @@ lazy val aggregatedProjects: Seq[ProjectReference] = List[ProjectReference]( agent, benchJmh, benchJmhTyped, - camel, cluster, clusterMetrics, clusterSharding, @@ -125,12 +124,6 @@ lazy val benchJmhTyped = akkaModule("akka-bench-jmh-typed") .enablePlugins(JmhPlugin, ScaladocNoVerificationOfDiagrams, NoPublish, CopyrightHeader) .disablePlugins(MimaPlugin, WhiteSourcePlugin, ValidatePullRequest, CopyrightHeaderInPr) -lazy val camel = akkaModule("akka-camel") - .dependsOn(actor, slf4j, testkit % "test->test") - .settings(Dependencies.camel) - .settings(AutomaticModuleName.settings("akka.camel")) - .settings(OSGi.camel) - lazy val cluster = akkaModule("akka-cluster") .dependsOn(remote, remoteTests % "test->test", testkit % "test->test") .settings(Dependencies.cluster) @@ -220,7 +213,6 @@ lazy val docs = akkaModule("akka-docs") distributedData, stream, actorTyped, - camel % "compile->compile;test->test", clusterTools % "compile->compile;test->test", clusterSharding % "compile->compile;test->test", testkit % "compile->compile;test->test", diff --git a/project/Dependencies.scala b/project/Dependencies.scala index ace0150425..a23d69e3dd 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -36,8 +36,6 @@ object Dependencies { object Compile { // Compile - val camelCore = ("org.apache.camel" % "camel-core" % "2.17.7").exclude("org.slf4j", "slf4j-api") // ApacheV2 - // when updating config version, update links ActorSystem ScalaDoc to link to the updated version val config = "com.typesafe" % "config" % "1.3.3" // ApacheV2 val netty = "io.netty" % "netty" % "3.10.6.Final" // ApacheV2 @@ -118,8 +116,6 @@ object Dependencies { // If changed, update akka-docs/build.sbt as well val sigarLoader = "io.kamon" % "sigar-loader" % "1.6.6-rev002" % "optional;provided;test" // ApacheV2 - // Non-default module in Java9, removed in Java11. For Camel. - val jaxb = "javax.xml.bind" % "jaxb-api" % "2.3.0" % "provided;test" val activation = "com.sun.activation" % "javax.activation" % "1.2.0" % "provided;test" val levelDB = "org.iq80.leveldb" % "leveldb" % "0.10" % "optional;provided" // ApacheV2 @@ -207,16 +203,6 @@ object Dependencies { val persistenceShared = l ++= Seq(Provided.levelDB, Provided.levelDBNative) - val camel = l ++= Seq( - camelCore, - Provided.jaxb, - Provided.activation, - Test.scalatest.value, - Test.junit, - Test.mockito, - Test.logback, - Test.commonsIo) - val osgi = l ++= Seq( osgiCore, osgiCompendium, diff --git a/project/OSGi.scala b/project/OSGi.scala index cf6e6b0c2a..fad7a0343e 100644 --- a/project/OSGi.scala +++ b/project/OSGi.scala @@ -48,8 +48,6 @@ object OSGi { val agent = exports(Seq("akka.agent.*")) - val camel = exports(Seq("akka.camel.*")) - val cluster = exports(Seq("akka.cluster.*")) val clusterTools = exports(Seq("akka.cluster.singleton.*", "akka.cluster.client.*", "akka.cluster.pubsub.*"))