2012-01-19 14:38:44 +00:00
/* *
* Copyright ( C ) 2009 - 2012 Typesafe Inc . < http : //www.typesafe.com>
*/
2011-05-23 11:37:56 -04:00
package akka.camel
import org.apache.camel. { Exchange , Processor }
import org.apache.camel.builder.RouteBuilder
import org.apache.camel.component.mock.MockEndpoint
import org.scalatest. { GivenWhenThen , BeforeAndAfterEach , BeforeAndAfterAll , FeatureSpec }
2012-01-19 14:38:44 +00:00
import akka.actor._
import akka.pattern._
import akka.dispatch.Await
import akka.util.duration._
import akka.camel.TestSupport.SharedCamelSystem
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
/* *
* Tests the features of the Camel Producer .
*/
class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with BeforeAndAfterEach with SharedCamelSystem with GivenWhenThen {
2011-05-23 11:37:56 -04:00
import ProducerFeatureTest._
2012-01-19 14:38:44 +00:00
val camelContext = camel . context
// to make testing equality of messages easier, otherwise the breadcrumb shows up in the result.
camelContext . setUseBreadcrumb ( false )
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
val timeout = 1 second
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
override protected def beforeAll { camelContext . addRoutes ( new TestRoute ( system ) ) }
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
override protected def afterEach { mockEndpoint . reset ( ) }
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
feature ( "Producer on a sync Camel route" ) {
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
scenario ( "produces a message and receives normal response" ) {
given ( "a registered two-way producer" )
val producer = system . actorOf ( Props ( new TestProducer ( "direct:producer-test-2" , true ) ) )
2011-06-28 16:53:11 +02:00
when ( "a test message is sent to the producer with ?" )
2011-05-23 11:37:56 -04:00
val message = Message ( "test" , Map ( Message . MessageExchangeId -> "123" ) )
2012-01-19 14:38:44 +00:00
val future = producer . ask ( message ) ( timeout )
then ( "a normal response must have been returned by the producer" )
2011-05-23 11:37:56 -04:00
val expected = Message ( "received TEST" , Map ( Message . MessageExchangeId -> "123" ) )
2012-01-19 14:38:44 +00:00
Await . result ( future , timeout ) match {
case result : Message ⇒ assert ( result === expected )
case unexpected ⇒ fail ( "Actor responded with unexpected message:" + unexpected )
}
2011-05-23 11:37:56 -04:00
}
2012-01-19 14:38:44 +00:00
scenario ( "produces a message and receives failure response" ) {
2011-05-23 11:37:56 -04:00
given ( "a registered two-way producer" )
2012-01-19 14:38:44 +00:00
val producer = system . actorOf ( Props ( new TestProducer ( "direct:producer-test-2" ) ) )
2011-05-23 11:37:56 -04:00
2011-06-28 16:53:11 +02:00
when ( "a test message causing an exception is sent to the producer with ?" )
2011-05-23 11:37:56 -04:00
val message = Message ( "fail" , Map ( Message . MessageExchangeId -> "123" ) )
2012-01-19 14:38:44 +00:00
val future = producer . ask ( message ) ( timeout )
Await . result ( future , timeout ) match {
case result : Failure ⇒ {
then ( "a failure response must have been returned by the producer" )
val expectedFailureText = result . cause . getMessage
val expectedHeaders = result . headers
assert ( expectedFailureText === "failure" )
assert ( expectedHeaders === Map ( Message . MessageExchangeId -> "123" ) )
}
case unexpected ⇒ fail ( "Actor responded with unexpected message:" + unexpected )
}
2011-05-23 11:37:56 -04:00
}
2012-01-19 14:38:44 +00:00
scenario ( "produces message oneway" ) {
2011-05-23 11:37:56 -04:00
given ( "a registered one-way producer" )
2012-01-19 14:38:44 +00:00
val producer = system . actorOf ( Props ( new TestProducer ( "direct:producer-test-1" , true ) with Oneway ) )
2011-05-23 11:37:56 -04:00
when ( "a test message is sent to the producer with !" )
mockEndpoint . expectedBodiesReceived ( "TEST" )
2012-01-19 14:38:44 +00:00
producer ! Message ( "test" , Map ( ) )
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
then ( "the test message must have been sent to mock:mock" )
mockEndpoint . assertIsSatisfied ( )
2011-05-23 11:37:56 -04:00
}
2012-01-19 14:38:44 +00:00
scenario ( "produces message twoway without sender reference" ) {
2011-05-23 11:37:56 -04:00
given ( "a registered two-way producer" )
2012-01-19 14:38:44 +00:00
val producer = system . actorOf ( Props ( new TestProducer ( "direct:producer-test-1" ) ) )
2011-05-23 11:37:56 -04:00
when ( "a test message is sent to the producer with !" )
mockEndpoint . expectedBodiesReceived ( "test" )
2012-01-19 14:38:44 +00:00
producer ! Message ( "test" , Map ( ) )
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
then ( "there must be only a warning that there's no sender reference" )
mockEndpoint . assertIsSatisfied ( )
2011-05-23 11:37:56 -04:00
}
}
2012-01-19 14:38:44 +00:00
feature ( "Producer on an async Camel route" ) {
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
scenario ( "produces message to direct:producer-test-3 and receives normal response" ) {
2011-05-23 11:37:56 -04:00
given ( "a registered two-way producer" )
2012-01-19 14:38:44 +00:00
val producer = system . actorOf ( Props ( new TestProducer ( "direct:producer-test-3" ) ) )
2011-05-23 11:37:56 -04:00
2011-06-28 16:53:11 +02:00
when ( "a test message is sent to the producer with ?" )
2011-05-23 11:37:56 -04:00
val message = Message ( "test" , Map ( Message . MessageExchangeId -> "123" ) )
2012-01-19 14:38:44 +00:00
val future = producer . ask ( message ) ( timeout )
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
Await . result ( future , timeout ) match {
case result : Message ⇒ {
then ( "a normal response must have been returned by the producer" )
val expected = Message ( "received test" , Map ( Message . MessageExchangeId -> "123" ) )
assert ( result === expected )
}
case unexpected ⇒ fail ( "Actor responded with unexpected message:" + unexpected )
}
2011-05-23 11:37:56 -04:00
}
2012-01-19 14:38:44 +00:00
scenario ( "produces message to direct:producer-test-3 and receives failure response" ) {
2011-05-23 11:37:56 -04:00
given ( "a registered two-way producer" )
2012-01-19 14:38:44 +00:00
val producer = system . actorOf ( Props ( new TestProducer ( "direct:producer-test-3" ) ) )
2011-05-23 11:37:56 -04:00
2011-06-28 16:53:11 +02:00
when ( "a test message causing an exception is sent to the producer with ?" )
2011-05-23 11:37:56 -04:00
val message = Message ( "fail" , Map ( Message . MessageExchangeId -> "123" ) )
2012-01-19 14:38:44 +00:00
val future = producer . ask ( message ) ( timeout )
Await . result ( future , timeout ) match {
case result : Failure ⇒ {
then ( "a failure response must have been returned by the producer" )
val expectedFailureText = result . cause . getMessage
val expectedHeaders = result . headers
assert ( expectedFailureText === "failure" )
assert ( expectedHeaders === Map ( Message . MessageExchangeId -> "123" ) )
}
case unexpected ⇒ fail ( "Actor responded with unexpected message:" + unexpected )
}
2011-05-23 11:37:56 -04:00
}
2012-01-19 14:38:44 +00:00
scenario ( "produces message, forwards normal response of direct:producer-test-2 to a replying target actor and receives response" ) {
2011-05-23 11:37:56 -04:00
given ( "a registered two-way producer configured with a forward target" )
2012-01-19 14:38:44 +00:00
val target = system . actorOf ( Props [ ReplyingForwardTarget ] )
val producer = system . actorOf ( Props ( new TestForwarder ( "direct:producer-test-2" , target ) ) )
2011-05-23 11:37:56 -04:00
2011-06-28 16:53:11 +02:00
when ( "a test message is sent to the producer with ?" )
2011-05-23 11:37:56 -04:00
val message = Message ( "test" , Map ( Message . MessageExchangeId -> "123" ) )
2012-01-19 14:38:44 +00:00
val future = producer . ask ( message ) ( timeout )
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
Await . result ( future , timeout ) match {
case result : Message ⇒ {
then ( "a normal response must have been returned by the forward target" )
val expected = Message ( "received test" , Map ( Message . MessageExchangeId -> "123" , "test" -> "result" ) )
assert ( result === expected )
}
case unexpected ⇒ fail ( "Actor responded with unexpected message:" + unexpected )
}
2011-05-23 11:37:56 -04:00
}
2012-01-19 14:38:44 +00:00
scenario ( "produces message, forwards failure response of direct:producer-test-2 to a replying target actor and receives response" ) {
2011-05-23 11:37:56 -04:00
given ( "a registered two-way producer configured with a forward target" )
2012-01-19 14:38:44 +00:00
val target = system . actorOf ( Props [ ReplyingForwardTarget ] )
val producer = system . actorOf ( Props ( new TestForwarder ( "direct:producer-test-2" , target ) ) )
2011-05-23 11:37:56 -04:00
2011-06-28 16:53:11 +02:00
when ( "a test message causing an exception is sent to the producer with ?" )
2011-05-23 11:37:56 -04:00
val message = Message ( "fail" , Map ( Message . MessageExchangeId -> "123" ) )
2012-01-19 14:38:44 +00:00
val future = producer . ask ( message ) ( timeout )
Await . result ( future , timeout ) match {
case failure : Failure ⇒ {
then ( "a failure response must have been returned by the forward target" )
val expectedFailureText = failure . cause . getMessage
val expectedHeaders = failure . headers
assert ( expectedFailureText === "failure" )
assert ( expectedHeaders === Map ( Message . MessageExchangeId -> "123" , "test" -> "failure" ) )
}
case unexpected ⇒ fail ( "Actor responded with unexpected message:" + unexpected )
}
2011-05-23 11:37:56 -04:00
}
2012-01-19 14:38:44 +00:00
scenario ( "produces message, forwards normal response to a producing target actor and produces response to direct:forward-test-1" ) {
2011-05-23 11:37:56 -04:00
given ( "a registered one-way producer configured with a forward target" )
2012-01-19 14:38:44 +00:00
val target = system . actorOf ( Props [ ProducingForwardTarget ] )
val producer = system . actorOf ( Props ( new TestForwarder ( "direct:producer-test-2" , target ) ) )
2011-05-23 11:37:56 -04:00
when ( "a test message is sent to the producer with !" )
mockEndpoint . expectedBodiesReceived ( "received test" )
2012-01-19 14:38:44 +00:00
producer . tell ( Message ( "test" , Map ( ) ) , producer )
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
then ( "a normal response must have been produced by the forward target" )
mockEndpoint . assertIsSatisfied ( )
2011-05-23 11:37:56 -04:00
}
2012-01-19 14:38:44 +00:00
scenario ( "produces message, forwards failure response to a producing target actor and produces response to direct:forward-test-1" ) {
2011-05-23 11:37:56 -04:00
given ( "a registered one-way producer configured with a forward target" )
2012-01-19 14:38:44 +00:00
val target = system . actorOf ( Props [ ProducingForwardTarget ] )
val producer = system . actorOf ( Props ( new TestForwarder ( "direct:producer-test-2" , target ) ) )
2011-05-23 11:37:56 -04:00
when ( "a test message causing an exception is sent to the producer with !" )
mockEndpoint . expectedMessageCount ( 1 )
mockEndpoint . message ( 0 ) . body ( ) . isInstanceOf ( classOf [ Failure ] )
2012-01-19 14:38:44 +00:00
producer . tell ( Message ( "fail" , Map ( ) ) , producer )
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
then ( "a failure response must have been produced by the forward target" )
mockEndpoint . assertIsSatisfied ( )
2011-05-23 11:37:56 -04:00
}
2012-01-19 14:38:44 +00:00
scenario ( "produces message, forwards normal response from direct:producer-test-3 to a replying target actor and receives response" ) {
2011-05-23 11:37:56 -04:00
given ( "a registered two-way producer configured with a forward target" )
2012-01-19 14:38:44 +00:00
val target = system . actorOf ( Props [ ReplyingForwardTarget ] )
val producer = system . actorOf ( Props ( new TestForwarder ( "direct:producer-test-3" , target ) ) )
2011-05-23 11:37:56 -04:00
2011-06-28 16:53:11 +02:00
when ( "a test message is sent to the producer with ?" )
2011-05-23 11:37:56 -04:00
val message = Message ( "test" , Map ( Message . MessageExchangeId -> "123" ) )
2012-01-19 14:38:44 +00:00
val future = producer . ask ( message ) ( timeout )
then ( "a normal response must have been returned by the forward target" )
Await . result ( future , timeout ) match {
case message : Message ⇒ {
val expected = Message ( "received test" , Map ( Message . MessageExchangeId -> "123" , "test" -> "result" ) )
assert ( message === expected )
}
case unexpected ⇒ fail ( "Actor responded with unexpected message:" + unexpected )
}
2011-05-23 11:37:56 -04:00
}
2012-01-19 14:38:44 +00:00
scenario ( "produces message, forwards failure response from direct:producer-test-3 to a replying target actor and receives response" ) {
2011-05-23 11:37:56 -04:00
given ( "a registered two-way producer configured with a forward target" )
2012-01-19 14:38:44 +00:00
val target = system . actorOf ( Props [ ReplyingForwardTarget ] )
val producer = system . actorOf ( Props ( new TestForwarder ( "direct:producer-test-3" , target ) ) )
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
when ( "a test message causing an exception is sent to the producer with !!" )
2011-05-23 11:37:56 -04:00
val message = Message ( "fail" , Map ( Message . MessageExchangeId -> "123" ) )
2012-01-19 14:38:44 +00:00
val future = producer . ask ( message ) ( timeout )
Await . result ( future , timeout ) match {
case failure : Failure ⇒ {
then ( "a failure response must have been returned by the forward target" )
val expectedFailureText = failure . cause . getMessage
val expectedHeaders = failure . headers
assert ( expectedFailureText === "failure" )
assert ( expectedHeaders === Map ( Message . MessageExchangeId -> "123" , "test" -> "failure" ) )
}
case unexpected ⇒ fail ( "Actor responded with unexpected message:" + unexpected )
}
2011-05-23 11:37:56 -04:00
}
2012-01-19 14:38:44 +00:00
scenario ( "produces message, forwards normal response from direct:producer-test-3 to a producing target actor and produces response to direct:forward-test-1" ) {
2011-05-23 11:37:56 -04:00
given ( "a registered one-way producer configured with a forward target" )
2012-01-19 14:38:44 +00:00
val target = system . actorOf ( Props [ ProducingForwardTarget ] )
val producer = system . actorOf ( Props ( new TestForwarder ( "direct:producer-test-3" , target ) ) )
2011-05-23 11:37:56 -04:00
when ( "a test message is sent to the producer with !" )
mockEndpoint . expectedBodiesReceived ( "received test" )
2012-01-19 14:38:44 +00:00
producer . tell ( Message ( "test" , Map ( ) ) , producer )
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
then ( "a normal response must have been produced by the forward target" )
mockEndpoint . assertIsSatisfied ( )
2011-05-23 11:37:56 -04:00
}
2012-01-19 14:38:44 +00:00
scenario ( "produces message, forwards failure response from direct:producer-test-3 to a producing target actor and produces response to direct:forward-test-1" ) {
2011-05-23 11:37:56 -04:00
given ( "a registered one-way producer configured with a forward target" )
2012-01-19 14:38:44 +00:00
val target = system . actorOf ( Props [ ProducingForwardTarget ] )
val producer = system . actorOf ( Props ( new TestForwarder ( "direct:producer-test-3" , target ) ) )
2011-05-23 11:37:56 -04:00
when ( "a test message causing an exception is sent to the producer with !" )
mockEndpoint . expectedMessageCount ( 1 )
mockEndpoint . message ( 0 ) . body ( ) . isInstanceOf ( classOf [ Failure ] )
2012-01-19 14:38:44 +00:00
producer . tell ( Message ( "fail" , Map ( ) ) , producer )
2011-05-23 11:37:56 -04:00
2012-01-19 14:38:44 +00:00
then ( "a failure response must have been produced by the forward target" )
mockEndpoint . assertIsSatisfied ( )
2011-05-23 11:37:56 -04:00
}
}
2012-01-19 14:38:44 +00:00
private def mockEndpoint = camel . context . getEndpoint ( "mock:mock" , classOf [ MockEndpoint ] )
2011-05-23 11:37:56 -04:00
}
object ProducerFeatureTest {
2012-01-19 14:38:44 +00:00
2011-05-23 11:37:56 -04:00
class TestProducer ( uri : String , upper : Boolean = false ) extends Actor with Producer {
def endpointUri = uri
2012-01-19 14:38:44 +00:00
2011-05-23 11:37:56 -04:00
override protected def receiveBeforeProduce = {
2012-01-19 14:38:44 +00:00
case msg : Message ⇒ if ( upper ) msg . mapBody {
body : String ⇒ body . toUpperCase
}
else msg
2011-05-23 11:37:56 -04:00
}
}
class TestForwarder ( uri : String , target : ActorRef ) extends Actor with Producer {
def endpointUri = uri
2012-01-19 14:38:44 +00:00
2011-05-23 11:37:56 -04:00
override protected def receiveAfterProduce = {
case msg ⇒ target forward msg
}
}
class TestResponder extends Actor {
protected def receive = {
case msg : Message ⇒ msg . body match {
2012-01-19 14:38:44 +00:00
case "fail" ⇒ {
context . sender ! ( Failure ( new Exception ( "failure" ) , msg . headers ) )
}
case bod : Any ⇒ {
context . sender ! ( msg . mapBody {
body : String ⇒ "received %s" format body
} )
}
2011-05-23 11:37:56 -04:00
}
}
}
class ReplyingForwardTarget extends Actor {
protected def receive = {
2012-01-19 14:38:44 +00:00
case msg : Message ⇒
context . sender ! ( msg . plusHeader ( "test" -> "result" ) )
case msg : Failure ⇒
context . sender ! ( Failure ( msg . cause , msg . headers + ( "test" -> "failure" ) ) )
2011-05-23 11:37:56 -04:00
}
}
class ProducingForwardTarget extends Actor with Producer with Oneway {
def endpointUri = "direct:forward-test-1"
}
2012-01-19 14:38:44 +00:00
class TestRoute ( system : ActorSystem ) extends RouteBuilder {
val responder = system . actorOf ( Props [ TestResponder ] , name = "TestResponder" )
2011-05-23 11:37:56 -04:00
def configure {
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)
2012-01-19 14:38:44 +00:00
from ( "direct:producer-test-3" ) . to ( responder )
2011-05-23 11:37:56 -04:00
// 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 )
}
}
} )
}
}
2012-01-19 14:38:44 +00:00
2011-05-23 11:37:56 -04:00
}