0

I have the following RouteBuilder:

MyRouteBuilder.java

@Component
public class MyRouteBuilder extends SpringRouteBuilder {

@Autowired
private MQConnectionProperties mqConnectionProperties;

@Override
public void configure() {
    setupExceptionHandler();
    setupTransformerReceiveChannel();
    setupOrchestrationChannel();
}

private void setupExceptionHandler() {
    onException(Exception.class).handled(true).to("direct:error");
}

private void setupTransformerReceiveChannel() {
    from(mqConnectionProperties.getTransformerReceiveQueue())
    .routeId(TransformerConstants.TRANSFORM_CONSUME_ROUTE)
    .log("Processing transform request.")
    .setHeader(TransformerConstants.TRANSFORM_HEADER_STATUS, simple("SUCCESS"))
    .to("direct:cosTransform")
    .end();
}

private void setupOrchestrationChannel() {
    from("direct:cosTransform")
    .routeId(TransformerConstants.TRANSFORM_XSLT_ROUTE)
    .process(new XSLTConfigurationProcessor())
    .log("Executing an xsl transform for Market=${header.market} and LOB=${header.lineOfBusiness}")
    .choice().id("transformBranch")
    .when(header("market").isEqualTo("NI"))
        .process(new TransformerNIProcessor()).id("NITransform")
    .endChoice()
    .otherwise()
        .recipientList(simple("xslt:./xsl/${header.market}/${header.lineOfBusiness}.xsl?saxon=true&contentCache=false")).id("BITransform")
    .end();
}

}

Note: Exception handler is defined as a separate routeBuilder class. I have the following unit test for MyRouteBuilder.

MyRouteBuilderTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MyRouteTestConfiguration.class)
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public class TransformerRouteBuilderUnitTest extends CamelTestSupport{

@Autowired
MQConnectionProperties mqConnectionProperties;

@Autowired
MyRouteBuilder myRouteBuilder;

MockEndpoint mockOutput;
MockEndpoint mockError;
MockEndpoint mockProcessor;


@Override
public boolean isUseAdviceWith() {
    return true;
}

@Override
protected RoutesBuilder createRouteBuilder() {
    return myRouteBuilder;
}
@Before
public void setup() throws Exception {
    super.setUp();
}

@Override
public String isMockEndpoints() {
    return "direct:cosTransform";
}


@Test
public void test_transformerReceiveChannel_happyPath_transformStatusHeaderSet() throws Exception {
    startCamelContext();

    mockOutput = getMockEndpoint("mock:direct:cosTransform", false);

    mockOutput.expectedHeaderReceived("TransformStatus", "fail");

    template.requestBody(mqConnectionProperties.getTransformerReceiveQueue(), new DefaultExchange(context));

    MockEndpoint.assertIsSatisfied(context);

    stopCamelContext();
}

stack trace

org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[ID-LIBP03P-QK70A9V-57085-1490361963523-1-2]
at org.apache.camel.util.ObjectHelper.wrapCamelExecutionException(ObjectHelper.java:1706)
at org.apache.camel.util.ExchangeHelper.extractResultBody(ExchangeHelper.java:660)
at org.apache.camel.impl.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:471)
at org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:133)
at org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:149)
at org.apache.camel.impl.DefaultProducerTemplate.requestBody(DefaultProducerTemplate.java:301)
at com.transformer.routing.MyRouteBuilderUnitTest.test_transformerReceiveChannel_happyPath_transformStatusHeaderSet(TransformerRouteBuilderUnitTest.java:89)
.....
Caused by: org.apache.camel.component.direct.DirectConsumerNotAvailableException: No consumers available on endpoint: Endpoint[direct://error]. Exchange[ID-LIBP03P-QK70A9V-57085-1490361963523-1-4]
....

I've read a few solutions to this and most answers revolve around failing to start the camel context, or having a second context that is being used rather than the context with the modified route etc., but I don't think that's the case here; debugging shows only 1 context which definately gets started, which only contains a route definition for MyRouteBuilder(as opposed to the route + the exception handling route).

jbailie1991
  • 1,305
  • 2
  • 21
  • 42
  • here `onException(Exception.class).handled(true).to("direct:error");` you send to the route "direct:error" but nowhere did you define that route - and no it's not a default route. – Japu_D_Cret Mar 24 '17 at 14:00
  • you might wanna use a Dead Letter Channel http://camel.apache.org/dead-letter-channel.html – Japu_D_Cret Mar 24 '17 at 14:01
  • @Japu_D_Cret The exception route is shared by several other routes, so it was extracted to its own routeBuilder class. Im testing this route in isolation, I want to check the exchange would be sent to the exception route. – jbailie1991 Mar 24 '17 at 14:05
  • do you test it with JUnit or a similar UnitTest Framework? - because you have to replicate the situation in a real scenario(i.e. with the `direct:error` route). if you use JUnit you could create one before using your `MyRouteBuilderTest.java` by creating a static initialization method with the annotation @BeforeClass, which will be executed before any test is run of that class. Inside that method you should create the `direct:error` route so it exists, while you're in your testing context – Japu_D_Cret Mar 24 '17 at 14:10
  • Yes I'm using JUnit 4 for testing. I've been trying to follow some test conventions in that unit tests should not use actual endpoints, hence the mocking for the direct:cosTransform, would creating a stub route for the exception handler for testing still fit within guidelines for a unit test?If so then that sounds like the simplest solution – jbailie1991 Mar 24 '17 at 14:14
  • also, correction on previous comments; this test isn't a check n the exchange being routed correctly, in this test i just want to check the correct header is set once the exchange reaches direct:cosTransform, but it fails around the direct:error endpoint. I pasted the right test but gave the wrong explanation of its intent. Offending paragraph removed from question – jbailie1991 Mar 24 '17 at 14:16
  • yes it would be conform to the guidelines. To test some situations you first have to make sure your starting point is the same(i.e. having the same number of endpoints). and yes if you don't want to check what will be send to the `direct:error` route, then just use a plain mock endpoint – Japu_D_Cret Mar 24 '17 at 14:22
  • took your advice but in a different manner; changed createRouteBuilder to the version that takies a list and created the onException route within that method. Test now passes – jbailie1991 Mar 24 '17 at 15:07

0 Answers0