JBoss Fuse - 

Error Handling Lab

Christina Lin

This time we are going to introduce error handling in the lab. First we are going to create a route that reads file from folder “orderdata” and then validate the data using the xml schema provided. 


 

Before we start, we know there will be data that are not going to pass the validation. We want to know what's wrong and then dump these files somewhere. So, we are going to surround the validation process with a try 'n catch clause just like what we will normally do in Java. 

try{

   ...

}catch(SomeException e){

   ...

}finally{

   ....

}

Create a Fuse project, choose the blueprint archetype.

Open up /errordemo/src/main/resources/OSGI-INF/blueprint/blueprint.xml and remove the demo route, so you are left with a blank canvas.

Remove the hellobean registry in the xml file. And delete all the java files.

<bean id="helloBean" class="com.mycompany.camel.blueprint.HelloBean">
      <property name="say" value="Hi from Camel"/>
  </bean>

Create the first route 

  • File Endpoint
    • Directory Name: orderdata
    • Try (under "Control Flow")
      • Validator Endpoint (Use "Generic component")
        • uri: validator:file:schema/singletrade.xsd
      • Camel direct Endpoint
        • uri: direct://randomProcess
      • Catch
        • exception: org.apache.camel.processor.validation.SchemaValidationException
  • ..
    • s
      • d
        • Log Endpoint
          • message: We have a problem!! ${exception.message}
        • File Endpoint
          • uri: file://garbage
        • Finally
          • Log Endpoint
            • message: Validation Done!

Inside the first route we see it's calling another route "direct://randomProcess" now we are going to create it. 

 

Create the random processor, this random processor randomly throws 2 different exceptions IOException and FileNotFoundExceptions. (See Next page)

 

Register the processor in the camel context by placing  

<bean id="randomProcessor" class="org.blogdemo.errordemo.RandomProcessor"/>
package org.blogdemo.errordemo;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
public class RandomProcessor implements Processor {
    @Override
    public void process(Exchange exchange) throws Exception {
        int random = (int )(Math.random() * 100 + 1);
        if(random< 30){
            System.out.println("random number:["+random+"] IOExceotion");
            throw new IOException();
        }else if(random< 90){
            System.out.println("random number:["+random+"] FileNotFoundException");
            throw new FileNotFoundException();
        }else{System.out.println("random number:["+random+"] PASS"); }
    }
}

Next we are going to create the route that calls the random processor

  • Camel direct Endpoint
    • uri: direct://randomProcess
  • Log Endpoint
    • message: Processing file :${header.CamelFileName}
  • Bean 
    • ref: randomProcessor
  • File Endpoint
    • uri: file://data

For this route, we want to resend the data if it's fails, and move it to a folder if it reties for too many times. 
First we want to catch the FileNotFound Exception, and set it to retry for maximum 3 time, with a 3 seconds gap. So add the following content in your camel context.

<camelContext>
  <onException>
    <exception>java.io.FileNotFoundException</exception>
    <redeliveryPolicy redeliveryDelay="3000" maximumRedeliveries="2"/>
  </onException>
  <route>…</route>
</camelContext>

 

And then we want to create a base error handler that moves the messages to another folder. And for error that are not specified, we will try to redelivery it once. So add the following content in your camel context.

<camelContext>
  <errorHandler deadLetterUri="file://DLQ" type="DeadLetterChannel" id="myErrorHandler">
    <redeliveryPolicy redeliveryDelay="5000" maximumRedeliveries="1"/>
  </errorHandler>
  <onException>…<onException>
  …
</camelContext>

Now for your 2nd route, reference it to use the error handler you just create by adding "myErrorHandler" in your route.

Make sure you have a xml schema names singletrade.xsd in your project schema folder. 

Run test, 

And place the problem xml with error content into orderdata folder, and you will see the log printing out the validation result and find your problem xml in the garbage folder.

Place an order xml file into orderdata folder, because the process throws exception randomly, you will either find your data has successfully processed and was send back to a data folder or it failed all redeliveries and sent to the DLQ folder.

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="stocktrading">
    <xs:complexType>
      <xs:sequence>
        <xs:element type="xs:string" name="name"/>
        <xs:element type="xs:string" name="custId"/>
        <xs:element type="xs:byte" name="vip"/>
        <xs:element type="xs:string" name="stockId"/>
        <xs:element type="xs:byte" name="shares"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

APPENDIX - singletrade.xsd

APPENDIX - order01.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- Red Hat Stock Exchange and Trading Systems-->
<stocktrading>
    <name>Christina Lin</name>
    <custId>A123456789</custId>
    <vip>1</vip>
    <stockId>XYZ</stockId>
    <shares>11</shares>        

</stocktrading>

APPENDIX - problem.xml

<?xml version="1.0" encoding="UTF-8"?>

<!-- Red Hat Stock Exchange and Trading Systems-->

<stocktrading>

    <name>Christina Lin</name>

    <custId>A123456789</custId>

     <vip>1</vip>

   <stockId>XYZ</stockId>

</stocktrading>

Error Handling Lab Completed!

Error Handling Lab

By weimeilin

Error Handling Lab

  • 5,326