Advanced Apache Camel tutorial
This is an extension to the last two Apache Camel tutorials:
This advanced tutorial extends part-2. The first route (consumer) polls for csv files and once a file is found in the c:/temp/adv folder, a sequential route is created by placing the info to two in memory queues via the "direct" component. Firstly, direct:email consumes the exchange data and generates an email with empty body to notify user that a file has arrived. The second consummer direct:transfer receives the exchange, and transforms the document to another csv using the PersonMapper class depending on if the conversion succeeded or not, the file is written to either converted or rejected sub folder. The key thing to make note is that how body and header information are passed back and forth between a n XML based routing in Spring and Java beans.
Step 1: The adv_file_converter.properties contains the name/value pairs
adv.in.dir=c:/temp/adv adv.in.file.pattern=.*\.csv adv.out.dir=c:/temp/adv adv.converted.filename=Accepted_File_adv adv.rejected.filename=Rejected_File_adv adv.email.to=peter.smith@mycompany.com adv.email.from=john.smith@mycompany.com common.mail.host=mailhost.mycompany.net common.mail.port=25 poll.delay=60000 initial.delay=10000
Step 2: Add the camel-mail component to send email via smtp endpoints. Make sure that you have the following in the pom.xml.
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-core</artifactId> <version>2.10.4</version> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-spring</artifactId> <version>2.10.4</version> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-csv</artifactId> <version>2.10.4</version> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-mail</artifactId> <version>2.10.4</version> </dependency>
Step 3: The adv_file_route.xml file with the relevant routes defined.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/spring" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> <routeContext id="advFileRoute" xmlns="http://camel.apache.org/schema/spring"> <route id="advFileConversion"> <from uri="file://{{adv.in.dir}}?include={{adv.in.file.pattern}}&delay={{poll.delay}}&initialDelay={{initial.delay}}&move=archive/" /> <multicast stopOnException="false"> <to uri="direct:email" /> <to uri="direct:transfer" /> </multicast> </route> <route id="inMemory"> <from uri="direct:email" /> <camel:setHeader headerName="subject"> <camel:simple>${file:name} has been received</camel:simple> </camel:setHeader> <!-- reset body to null otherwise file content will be sent via email body--> <camel:setBody> <constant></constant> </camel:setBody> <to uri="smtp://{{common.mail.host}}?contentType=text/html&to={{adv.email.to}}&from={{adv.email.from}}" /> </route> <route> <from uri="direct:transfer" /> <unmarshal> <csv skipFirstLine="true" /> </unmarshal> <to uri="bean:personMapper" /> <marshal> <csv delimiter="," /> </marshal> <convertBodyTo type="java.lang.String" /> <choice> <when> <simple>${headers.status} == 'accepted'</simple> <to uri="file://{{adv.out.dir}}/converted?fileName={{adv.converted.filename}}_${headers.dest_file_suffix}" /> </when> <when> <simple>${headers.status} == 'rejected'</simple> <to uri="file://{{adv.out.dir}}/rejected?fileName={{adv.rejected.filename}}_${headers.dest_file_suffix}" /> </when> </choice> </route> </routeContext> </beans>
Step 4: The PersonMapper class that transforms the input file.
package com.mycompany.app5; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.apache.camel.Exchange; import org.springframework.stereotype.Component; @Component("personMapper") public class PersonMapper { private static final String HEADER_STATUS = "status"; private static final String HEADER_DEST_FILE_SUFFIX = "dest_file_suffix"; enum Status { accepted, rejected }; public Object service(List<List<String>> data, Exchange exchange) { List<Map<String, String>> results = new ArrayList<Map<String, String>>(); Map<String, String> headerLine = new LinkedHashMap<String, String>(); headerLine.put("surname", "surname"); headerLine.put("firstname", "firstname"); headerLine.put("age", "age"); results.add(headerLine); boolean accepted = true; for (List<String> line : data) { Map<String, String> resultLine = new LinkedHashMap<String, String>(); resultLine.put("surname", line.get(1)); resultLine.put("firstname", line.get(0)); resultLine.put("age", line.get(2)); results.add(resultLine); if (line.get(1) == null || line.get(2) == null) { accepted = false; } } if (accepted) { exchange.getIn().setHeader(HEADER_STATUS, Status.accepted.name()); } else { exchange.getIn().setHeader(HEADER_STATUS, Status.rejected.name()); } String srcFileName = (String) exchange.getIn().getHeader("CamelFileNameOnly"); exchange.getIn().setHeader(HEADER_DEST_FILE_SUFFIX, srcFileName); return results; } }
Step 5: The main class that kicks off the standalone route.
package com.mycompany.app5; import org.apache.camel.spring.Main; public class StandAloneCamelWithSpring { private Main main; public static void main(String[] args) throws Exception { StandAloneCamelWithSpring example = new StandAloneCamelWithSpring(); example.boot(); } private void boot() throws Exception { // create a Main instance main = new Main(); // enable hangup support so you can press ctrl + c to terminate the JVM main.enableHangupSupport(); main.setApplicationContextUri("applicationContext.xml"); // run until you terminate the JVM System.out.println("Starting Camel. Use ctrl + c to terminate the JVM.\n"); main.run(); } }
Step 6: The other relevant file "applicationContext.xml"
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"> <context:component-scan base-package="com.mycompany.app5" /> <context:annotation-config /> <context:spring-configured /> <task:annotation-driven /> <bean id="bridgePropertyPlaceholder" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:*.properties</value> </list> </property> </bean> <import resource="classpath*:route.xml" /> </beans>
Step 7: Finally, the route.xml file.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xmlns:camel="http://camel.apache.org/schema/spring" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> <import resource="classpath*:adv_file_route.xml" /> <camel:errorHandler id="defaultErrorHandler" type="DefaultErrorHandler" /> <camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="defaultErrorHandler"> <routeContextRef ref="advFileRoute" /> </camelContext> </beans>
The route definition file "adv_file_route.xml" is covered in Step 3.
Labels: Apache Camel
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home