Multiple Camel Proxys in same camel context - apache-camel

I am trying to invoke a direct endpoint using camel proxy and a Java Interface. I exposed this interface as OSGI service to another bundle and accessing the interface in that bundle. Everything worked fine and now i got a requirement to invoke another direct endpoint based on certain conditions in same camel context using same interface. How can i do this?
Camel routes:
<camelContext id="cContext" trace="false" xmlns="http://camel.apache.org/schema/blueprint">
<proxy id="camelProxyService"
serviceInterface="com.xxx.CamelProxyService"
serviceUrl="direct:endpoint1" />
<route id="route1">
<from uri="direct:endpoint1" />
<to uri="seda:a" />
</route>
<route id="route2">
<from uri="direct:endpoint2" />
<to uri="seda:b" />
</route>
</camelContext>
<service ref="camelProxyService" interface="com.xxx.CamelProxyService"/>
public interface CamelProxyService {
public void method1(String str);
public void method2(String str);
}
How can i define the interface as camel proxy in camel context and mention method names to call different direct endpoints? Any help is appreciated.

<proxy id="camelProxyService"
serviceInterface="com.uday.camel.proxy.CamelProxyService"
serviceUrl="direct:endpoint1" />
<camel:route>
<camel:from uri="direct:endpoint1"/>
<camel:process ref="conditionProcess"/>
<camel:choice>
<camel:when>
<camel:header>${condition}=method1</camel:header>
<camel:to uri="seda:a"/>
</camel:when>
<camel:otherwise>
<camel:to uri="seda:b"/>
</camel:otherwise>
</camel:choice>
<camel:stop/>
</camel:route>
public class ConditionProcess implements Processor {
#Override
public void process(Exchange exchange) throws Exception {
BeanInvocation invocation = exchange.getIn().getBody(BeanInvocation.class);
String methodName = invocation.getMethod().getName();
exchange.getIn().setHeader("condition", methodName);
System.out.println("Method "+methodName);
}
}

Related

Ordering of responses from endpoints in RecipientList

I am using camel 2.17 and Fuse 6.3. I have a scenario wherein I need to send my message to multiple endpoints which are doing some dB logging each.
I am using "recipientList" to send my message to these endpoints but here I face an issue that, my DB entries are not in order of the endpoint calls.
Suppose, I have 3 endpoints A,B,C and they log 1 message each in DB after some processing MessageA, MessageB and MessageC but when I run my route RL(a,b,c) I do not see the DB mesages in same order although these are direct endpoints.
Is there a way my route can wait for first endpoint to complete and then process the second endpoint?
Here is my route Sample
<route id="RouteStart">
<from id="_from1" uri="file:.../>
<bean id="_bean1" method="hasReadWriteAccess" ref="fileAccessValidator"/>
<log id="_log1" message=${body}"/>
<recipientList id="_recipientList1">
<simple>FirstStepInsert, MessageDirQueue, Step1Queue</simple>
</recipientList>
</route>
<!-- This route picks the file from queue, encodes the file in to UTF-8 BOM and validates file against XSD -->
<route id="Step1Route">
<from id="_from2" uri="Step1Queue"/>
<log id="_log2" message=${body}"/>
<setProperty id="_setProperty4" propertyName="stepName">
<simple>File Validation</simple>
</setProperty>
<doTry id="_doTry1">
<to id="_to1" uri="Step2Queue"/>
<doCatch id="_doCatch1">
<exception>org.apache.camel.ValidationException</exception>
<to id="_to2" uri="file:..?autoCreate=true"/>
<log id="_log7" message="Moved Invalid file ${file:name}"/>
</doCatch>
<doCatch id="_doCatch2">
<exception>java.io.IOException</exception>
<to id="_to3" uri="file:..?autoCreate=true"/>
<log id="_log8" message="Moved XML file ${file:name} with Incorrect access"/>
</doCatch>
<doFinally id="_doFinally1">
<to id="_to4" uri="direct:stepInsertLogging"/>
</doFinally>
</doTry>
</route>
<route id="Step2Route">
<from id="_from3" uri="Step2Queue"/>
<log id="_log9" message="${body}"/>
<setProperty id="_setProperty12" propertyName="stepName">
<simple>Data Transformation</simple>
</setProperty>
<recipientList id="_recipientList2">
<simple>direct:stepInsertLogging, ReceiveDirQueue, Step3Queue</simple>
</recipientList>
</route>
<route id="Step3Route">
<from id="_from4" uri="Step3Queue"/>
<setProperty id="_setProperty19" propertyName="stepName">
<simple>File Delivered</simple>
</setProperty>
<to id="_to5" uri="file:..."/>
<onException id="_onException1">
<exception>java.io.IOException</exception>
<redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="0"/>
<recipientList id="_recipientList3">
<simple>direct:stepInsertLogging, direct:flowUpdateLogging</simple>
</recipientList>
</route>
<!-- This route sends a copy of source file to Message Archive folder -->
<route id="MessageDirRoute">
<from id="_from9" uri="MessageDirQueue"/>
<log id="_log23" message="${body}"/>
<setProperty id="_setProperty63" propertyName="stepName">
<simple>Data SourceFile Logging</simple>
</setProperty>
<to id="_to13" uri="file:.."/>
<onException id="_onException4">
<exception>java.io.IOException</exception>
<handled>
<constant>true</constant>
</handled>
<to id="_to14" uri="direct:stepInsertLogging"/>
</route>
<!-- This route sends a copy of destination file to Message Archive folder -->
<route id="receiveDirectory-route">
<from id="_from10" uri="ReceiveDirQueue"/>
<setProperty id="_setProperty77" propertyName="stepName">
<simple>Data DestinationFile Logging</simple>
</setProperty>
<to id="_to15" uri="file:.."/>
<onException id="_onException5">
<exception>java.io.IOException</exception>
<redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="0"/>
<handled>
<constant>true</constant>
</handled>
<to id="_to16" uri="direct:stepInsertLogging"/>
</route>
<!-- Event Logging Routes -->
<route id="startMainLogRoute">
<from id="_from11" uri="FirstStepInsert"/>
<log id="_log25" message="Received File ${file:name} : ${body}"/>
<setProperty id="_setProperty92" propertyName="stepName">
<simple>File Received</simple>
</setProperty>
<log id="_log26" message="${property.flowId}"/>
<recipientList id="_recipientList7" streaming="false">
<simple>direct:flowInsertLogging, direct:stepInsertLogging</simple>
</recipientList>
</route>
<route id="flowInsertLogRoute">
<from id="_from12" uri="direct:flowInsertLogging"/>
<log id="_log27" message="[flowInsertLogRoute] Flow Id is ${property.flowId}"/>
<process id="_process8" ref="flowProcessor"/>
<transform id="_transform1">
<method method="getFlowMap" ref="flowMapper"/>
</transform>
<log id="_log28" message="Executing the query {{sql.insertFlowDetail}}"/>
<to id="_to17" uri="sql:{{sql.insertFlowDetail}}"/>
</route>
<route id="stepInsertLogRoute">
<from id="_from13" uri="direct:stepInsertLogging"/>
<log id="_log29" message="[stepInsertLogRoute] Flow Id is ${property.flowId}"/>
<process id="_process9" ref="stepProcessor"/>
<transform id="_transform2">
<method method="getStepMap" ref="stepMapper"/>
</transform>
<log id="_log30" message="Executing the query {{sql.insertStepDetail}}"/>
<to id="_to18" uri="sql:{{sql.insertStepDetail}}"/>
</route>
<route id="flowUpdateLogRoute">
<from id="_from14" uri="direct:flowUpdateLogging"/>
<log id="_log31" message="[flowUpdateLogRoute] Flow Id is ${property.flowId}"/>
<transform id="_transform3">
<method method="getFlowUpdateMap" ref="flowUpdateMapper"/>
</transform>
<log id="_log32" message="Executing the query {{sql.updateFlowDetail}}"/>
<to id="_to19" uri="sql:{{sql.updateFlowDetail}}"/>
</route>
</camelContext>
Here, I am updating the "stepName" property in my DB which is not following the execution order.
It should be:
File Received
Data SourceFile Logging
File Validation
Data Transformation
Data DestinationFile Logging
File Delivered
But I do not see this order in the DB entries.
Themis and NoMad17 have already said in comments. From the docs:
The recipients will receive a copy of the same Exchange, and Camel will execute them sequentially.
I see in your route that you're chaining other recipient lists. Maybe you are missing something since it's many routes. To validate the sequence from the recipient list, took this unit test as example:
public class RecipientListSequenceAggregateRouteTest extends CamelTestSupport {
EmbeddedDatabase db;
#Before
public void setUp() throws Exception {
db = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.DERBY).addScript("sql/test.sql").build();
super.setUp();
}
#Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
getContext().getComponent("sql", SqlComponent.class).setDataSource(db);
from("direct:start")
.recipientList(constant("direct:a1, direct:a2, direct:a3, direct:select"));
from("direct:a1")
.log("got message in a1: waiting 3s")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
Thread.sleep(3000);
}
})
.setBody(constant("a1"))
.recipientList(constant("direct:db, direct:flow"));
from("direct:a2")
.log("got message in a2: waiting 5s")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
Thread.sleep(5000);
}
})
.setBody(constant("a2"))
.recipientList(constant("direct:db, direct:flow"));
from("direct:a3")
.log("got message in a3: waiting 1s")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
Thread.sleep(1000);
}
});
from("direct:db")
.log("got message in db from ${body}")
.setBody(simple("db_${in.body}"))
.to("sql:insert into log (body_in) values (:#${in.body})");
;
from("direct:flow")
.log("got message in flow from ${body}")
.setBody(simple("flow_${in.body}"))
.to("sql:insert into log (body_in) values (:#${in.body})");
;
from("direct:select")
.to("sql:select * from log order by time_in")
.log("results:\n ${body}")
.to("mock:result");
}
};
}
#Test
public void test() throws InterruptedException {
getMockEndpoint("mock:result").expectedMessageCount(1);
Object results = template.requestBody("direct:start", "");
assertNotNull(results);
assertMockEndpointsSatisfied();
}
}
The results are:
19:23:47.090 [main] INFO route2 - got message in a1: waiting 3s
19:23:50.093 [main] INFO route5 - got message in db from a1
19:23:50.315 [main] INFO route6 - got message in flow from a1
19:23:50.337 [main] INFO route3 - got message in a2: waiting 5s
19:23:55.343 [main] INFO route5 - got message in db from a2
19:23:55.351 [main] INFO route6 - got message in flow from a2
19:23:55.359 [main] INFO route4 - got message in a3: waiting 1s
19:23:56.428 [main] INFO route7 - results:
[{BODY_IN=db_a1, TIME_IN=2017-12-22 19:23:50.301}, {BODY_IN=flow_a1, TIME_IN=2017-12-22 19:23:50.334}, {BODY_IN=db_a2, TIME_IN=2017-12-22 19:23:55.348}, {BODY_IN=flow_a2, TIME_IN=2017-12-22 19:23:55.356}]
As you see, even chaining other recipient lists the messages were delivered sequentially. Could you take apart some samples from your route and see the logs? Try to analyze step by step. Seeing your DSL I couldn't see anything wrong with it.
If you need to manipulate the reply from the recipient list, you may need a custom Aggregator:
An AggregationStrategy that will assemble the replies from recipients into a single outgoing message from the Recipient List. By default Camel will use the last reply as the outgoing message. From Camel 2.12 onwards you can also use a POJO as the AggregationStrategy, see the Aggregator page for more details. If an exception is thrown from the aggregate method in the AggregationStrategy, then by default, that exception is not handled by the error handler. The error handler can be enabled to react if enabling the shareUnitOfWork option.

Camel Interceptor conflict with CXF Interceptor

I am Using custom InterceptStrategy and it throws errors after SOAP response is success.
Error : java.lang.IllegalStateException: It is illegal to call getRequest() after complete() or any of the dispatch() methods has been called
at org.apache.catalina.core.AsyncContextImpl.getRequest(AsyncContextImpl.java:224)
at org.apache.catalina.core.AsyncContextImpl.dispatch(AsyncContextImpl.java:153)
at org.springframework.security.web.servletapi.HttpServlet3RequestFactory$SecurityContextAsyncContext.dispatch(HttpServlet3RequestFactory.java:291)
at org.apache.cxf.transport.http.Servlet3ContinuationProvider$Servlet3Continuation.redispatch(Servlet3ContinuationProvider.java:125)
at org.apache.cxf.transport.http.Servlet3ContinuationProvider$Servlet3Continuation.resume(Servlet3ContinuationProvider.java:131)
public class ApplicationLogStrategy implements InterceptStrategy {
#Override
public Processor wrapProcessorInInterceptors(CamelContext context, ProcessorDefinition<?> definition,
Processor target, Processor nextTarget) throws Exception {
return new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
System.out.println("Display" + definition);
if (definition.getId().equalsIgnoreCase(ApplicationConstants.INITIAL_LOG)) {
//setCommonFields(exchange);
//setSpecificFields(exchange);
}
target.process(exchange);
}
};
}
}
My camel route:
<camelContext id="id-por" xmlns="http://camel.apache.org/schema/spring">
<route>
<!-- route starts from the cxf webservice -->
<from uri="cxf:bean:porEndpoint" />
<doTry>
<to uri="bean:soapBean?method=processSOAP"/>
<bean id="soap_success" method="processSuccess" ref="soapBean"/>
<camel:bean id="published_log" method="info('Message - SUCCESS')" ref="logger"/>
<doCatch>
<camel:exception>java.lang.Exception</camel:exception>
<handled>
<constant>true</constant>
</handled>
<to uri="bean:soapBean?method=processGenericError"/>
</doCatch>
</doTry>
</route>
</camelContext>
It throws error after the message "Message - SUCCESS" is logged. :
<camel:bean id="published_log" method="info('Message - SUCCESS')" ref="logger"/>
I added <stop/> but no luck, still throws the error : It is illegal to call getRequest() after complete() or any of the dispatch() methods
Instead of target.process(exchange);
just return target;

spring camel test using multiple contexts

I have two camel contexts (A and B) at different xml using Spring. When I load just one context my junit works, but when a I try to load both contexts the Endpoint inject fail running junit.
So, someone have a sample how to use Test using multiple context with spring camel?
Spring Test
public class BaseSpringTest extends CamelSpringTestSupport
{
protected AbstractXmlApplicationContext createApplicationContext()
{
return new ClassPathXmlApplicationContext("camel-config.xml");
}
}
My file camel-config.xml
<beans>
<context:annotation-config/>
<import resource="classpath:camel-test-dao.xml" />
<import resource="classpath:camel-contextA.xml"/>
<import resource="classpath:camel-contextB.xml"/>
</beans>
My contexts:
<camelContext xmlns="camel.apache.org/schema/spring" id="contextA">
...
</camelContext>
<camelContext xmlns="camel.apache.org/schema/spring" id="contextB">
...
</camelContext>
My unit test, failing at inject Endpoint:
#EndpointInject(uri = "direct:myroute", context="contextB")
private Endpoint eFooTest;
Stacktrace:
org.apache.camel.spring.GenericBeansException: Error post processing bean: com.mycompany.test.FooTest; nested exception is java.lang.NullPointerException
at org.apache.camel.spring.CamelBeanPostProcessor.postProcessBeforeInitialization(CamelBeanPostProcessor.java:154)
at org.apache.camel.test.spring.CamelSpringTestSupport.postProcessTest(CamelSpringTestSupport.java:62)
at org.apache.camel.test.junit4.CamelTestSupport.doSetUp(CamelTestSupport.java:319)
at org.apache.camel.test.junit4.CamelTestSupport.setUp(CamelTestSupport.java:238)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.NullPointerException
at org.apache.camel.impl.CamelPostProcessorHelper.matchContext(CamelPostProcessorHelper.java:84)
at org.apache.camel.impl.DefaultCamelBeanPostProcessor$1.doWith(DefaultCamelBeanPostProcessor.java:181)
at org.apache.camel.util.ReflectionHelper.doWithFields(ReflectionHelper.java:73)
at org.apache.camel.impl.DefaultCamelBeanPostProcessor.injectFields(DefaultCamelBeanPostProcessor.java:168)
at org.apache.camel.impl.DefaultCamelBeanPostProcessor.postProcessBeforeInitialization(DefaultCamelBeanPostProcessor.java:82)
at org.apache.camel.spring.CamelBeanPostProcessor.postProcessBeforeInitialization(CamelBeanPostProcessor.java:148)
... 31 more
Apparently there is a bug at CamelBeanPostProcessor, when there are more one context a null value is returned!
if (contexts != null && contexts.size() == 1) {
#XmlTransient
private final DefaultCamelBeanPostProcessor delegate = new DefaultCamelBeanPostProcessor() {
#Override
public CamelContext getOrLookupCamelContext() {
if (camelContext == null) {
if (camelId != null) {
LOG.trace("Looking up CamelContext by id: {} from Spring ApplicationContext: {}", camelId, applicationContext);
camelContext = applicationContext.getBean(camelId, CamelContext.class);
} else {
// lookup by type and grab the single CamelContext if exists
LOG.trace("Looking up CamelContext by type from Spring ApplicationContext: {}", applicationContext);
Map<String, CamelContext> contexts = applicationContext.getBeansOfType(CamelContext.class);
if (contexts != null && contexts.size() == 1) {
camelContext = contexts.values().iterator().next();
}
}
}
return camelContext;
}
Camel 2.16.2
Spring 4.1.5
JDK 1.7
JDK 1.8
Thanks #Jorge-c, but using routeContext we continuous having just one single CamelContext.
To use multiply contexts at unit test don't use CamelSpringTestSupport, there are a bug.
public class BaseSpringTest extends CamelSpringTestSupport {...}
Use "#RunWith(SpringJUnit4ClassRunner.class)"
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("/camel-my-root-spring-config.xml")
public class BaseSpringJUnit4
{
#EndpointInject(uri = "direct:myroute", context="contextB")
private Endpoint eFooTest;
}
This works! Doesn't forget to put explicitilly context="contextB" in the endpoint annotation
Camel 2.16.2
Spring 4.1.5
JDK 1.7
JDK 1.8
I've been struggling with this for a while as well. Finally I managed a workaround which allows me to use the original routes xml files used in production but combined into a single camel context to be able to use it for testing. This way I'm able to inject mocks for bean endpoints and check the complete process by asserting on the mocks.
There are two different bundles. One from invoicing and another for emailing. The routes orchestrate the process.
First I externalized the routes on the production xml files. Spring context (invoicing-spring-context.xml) and routes (invoicing-routes.xml) file for invoicing bundle:
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
...
<camelContext id="invoicingCamelContext"
xmlns="http://camel.apache.org/schema/spring">
<routeContextRef ref="invoicingRoutes"/>
</camelContext>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<routeContext id="invoicingRoutes" xmlns="http://camel.apache.org/schema/spring">
<route id="planner" autoStartup="true">
<from uri="quartz://planner?cron=0+0+23+16+*+?" />
<to uri="direct:invoicing" />
</route>
<route id="invoicing" autoStartup="true">
<from uri="direct:invoicing?exchangePattern=InOut" />
<to uri="bean:invoicer?method=generateInvoices" />
<to uri="direct-vm:emailing" />
</route>
</routeContext>
</beans>
Spring context (emailing-spring-context.xml) and routes (emailing-routes.xml) for emailing bundle:
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
...
<camelContext id="emailingCamelContext"
xmlns="http://camel.apache.org/schema/spring">
<routeContextRef ref="emailingRoutes"/>
</camelContext>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<routeContext id="emailingRoutes" xmlns="http://camel.apache.org/schema/spring">
<route id="emailing" autoStartup="true">
<from uri="direct-vm:emailing" />
<to uri="bean:emailer?method=createEmails" />
<to uri="bean:emailer?method=sendEmails" />
</route>
</routeContext>
</beans>
Then for testing purposes I created another spring context (complete-process-test-spring-context.xml) which imports both routes files:
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
...
<camelContext id="completeProcessTestCamelContext"
xmlns="http://camel.apache.org/schema/spring">
<routeContextRef ref="invoicingRoutes"/>
<routeContextRef ref="emailingRoutes"/>
</camelContext>
</beans>
And the test class looks like:
public class CompleteProcessTest extends CamelSpringTestSupport {
#Test
public void completeProcess() {
...
invoicerMock.generateInvoices(EasyMock.isA(Exchange.class));
emailerMock.createEmails(EasyMock.isA(Exchange.class));
emailerMock.sendEmails(EasyMock.isA(Exchange.class));
EasyMock.replay(invoicerMock);
EasyMock.replay(emailerMock);
this.template.requestBody(this.context.getEndpoint("direct://invoicing"), "");
EasyMock.verify(invoicerMock);
EasyMock.verify(emailerMock);
}
#Override
protected AbstractApplicationContext createApplicationContext() {
return new ClassPathXmlApplicationContext("classpath:/META-INF/spring/invoicing-routes.xml",
"classpath:/META-INF/spring/emailing-routes.xml",
"classpath:/META-INF/spring/complete-process-test-spring-context.xml");
}
...
}

Apache camel how to insert map value to data base using sql component

Apache camel how to insert map value to data base using SQL component
My Class file:
public class PolluxDataController {
List<PolluxData> stationsMasterList=new ArrayList<PolluxData>();
List<PolluxData> stationProccessedList=new ArrayList<PolluxData>();
Map<String,Object> stationMap=new HashMap<String,Object>();
#SuppressWarnings("unchecked")
public Map<String, Object> processPolluxData(Exchange exchange) throws Exception {
stationsMasterList= (List<PolluxData>) exchange.getIn().getBody();
for (PolluxData value:stationsMasterList){
System.out.println(value.getStationCode() +","+value.getStationShortDescription());
stationMap.put("id",value.getStationCode());
stationMap.put("ltr", value.getStationShortDescription());
}
return stationMap;
}
sql.properties file is:
sql.insertNewRecord=INSERT INTO GSI_DEVL.POLLUX_DATA(STID,CLLTR) VALUES(:#id,#ltr)
Context.xml is
<!-- configure the Camel SQL component to use the JDBC data source -->
<bean id="sqlComponent" class="org.apache.camel.component.sql.SqlComponent">
<property name="dataSource" ref="dataSource" />
</bean>
<bean name="polluxDataController" id="polluxDataController" class="com.nielsen.polluxloadspring.controller.PolluxDataController" />
<camelContext trace="false" xmlns="http://camel.apache.org/schema/spring">
<!-- use Camel property placeholder loaded from the given file -->
<propertyPlaceholder id="placeholder" location="classpath:sql.properties" />
<camel:route id="bindy-csv-marhalling-unmarshalling-exmaple" autoStartup="true">
<camel:from uri="file://D://cameltest//input?noop=true&delay=10" />
<camel:log message="CAMEL BINDY CSV MARSHALLING UNMARSHALLING EXAMPLE" loggingLevel="WARN"/>
<camel:unmarshal ref="bindyDataformat" >
<camel:bindy type="Csv" classType="com.nielsen.polluxloadspring.model.PolluxData" />
</camel:unmarshal>
<camel:log message="Station Details are ${body}" loggingLevel="WARN" />
<camel:bean ref="polluxDataController" method="processPolluxData" />
<camel:log message="Station Details after bean process ${body}" loggingLevel="WARN" />
<to uri="sqlComponent:{{sql.insertNewRecord}}" />
<log message="Inserted new NewTopic ${body[id]}" />
<log message="Inserted new NewTopic ${body[ltr]}" />
<camel:log message="COMPLETED BINDY SIMPLE CSV EXAMPLE" loggingLevel="WARN" />
</camel:route>
</camelContext>
Problem is this will insert only one row to database, but the file contains 2000 rows how can I acheive this
Change the Bean method as below
public class PolluxDataController {
List<PolluxData> stationsMasterList=new ArrayList<PolluxData>();
Map<String,Object> stationMap=null;
List<Map<String,Object>> stationProccessedList=new ArrayList<Map<String,Object>>();
#SuppressWarnings("unchecked")
public List<Map<String,Object>> processPolluxData(Exchange exchange) throws Exception {
stationsMasterList= (List<PolluxData>) exchange.getIn().getBody();
for (PolluxData value:stationsMasterList){
System.out.println(value.getStationCode() +","+value.getStationShortDescription());
stationMap=new HashMap<String,Object>();
stationMap.put("id",value.getStationCode());
stationMap.put("ltr", value.getStationShortDescription());
stationProccessedList.add(stationMap);
}
return stationProccessedList;
}
}
change the sql.properties by adding a parameter batch=true , by default this will insert everything in your list to the db not once record. If you want to select and insert only two records at a time then your business logic is wrong.
You map stationMap will contains only two entries. In for (PolluxData value:stationsMasterList) you always reset this two entries for each PolluxData. Only one map with two enties within - only one insert, not 2000. Something wrong in business logic (with algorithm of filling the map stationMap, maybe), I think.

Method with name: sayHi not found on bean - Using apache Camel

I am using apache camel to communicate to a remote EJB which is deployed in Weblogic Server 12c. when i invoke remote EJB it throws me the below exception
org.apache.camel.component.bean.MethodNotFoundException: Method with name: sayHi not found on bean: ClusterableRemoteRef(3961905123449960886S:192.168.1.98:[7001,7001,-1,-1,-1,-1,-1]:weblogic:AdminServer [3961905123449960886S:192.168.1.98:[7001,7001,-1,-1,-1,-1,-1]:weblogic:AdminServer/394])/394 of type: com.iexceed.study.HelloRemoteEJBImpl_6zix6y_IHelloRemoteEJBImpl_12120_WLStub. Exchange[Message: [Body is null]]
My Came-context.xml file is as below
<bean id="ejb" class="org.apache.camel.component.ejb.EjbComponent">
<property name="properties" ref="jndiProperties" />
</bean>
<util:properties id="jndiProperties">
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">t3://IPADDRESS:PORT</prop>
<prop key="java.naming.security.principal">weblogic</prop>
<prop key="java.naming.security.credentials">Weblogic#01</prop>
</util:properties>
<camelContext id="camelclient" xmlns="http://camel.apache.org/schema/spring">
<template id="template" />
<endpoint id="camelejb" uri="ejb:EJBRemoteModule-1_0-SNAPSHOTEJBRemoteModule-1_0-SNAPSHOT_jarHelloRemoteEJBImpl_IHelloRemoteEJB?method=sayHi"/>
<route>
<from uri="direct:start_0" />
<to uri="camelejb" />
</route>
</camelContext>
and the java client class which i am using is
public void postRequest(){
try {
String camelID = "camelejb";
Exchange exchange = null;
Message msg = null;
getCamelContext();
springCamelContext.start();
System.out.println("Starting camel context.....");
getUriMap();
ProducerTemplate template = springCamelContext.createProducerTemplate();
System.out.println("camelejb::::::" + getUriMap().get("camelejb"));
exchange = template.request(getUriMap().get(camelID), new Processor() {
public void process(Exchange exchng) throws Exception {
exchng.getIn().setBody("");
}
});
System.out.println("Exception:" + exchange.getException());
exchange.getException().printStackTrace();
msg = exchange.getOut();
System.out.println("Message:" + msg);
springCamelContext.stop();
System.out.println("Stopping Camel Context....");
} catch (Exception ex) {
ex.printStackTrace();
}
}
EJB :
#Remote
public interface IHelloRemoteEJB {
public void sayHello(String name);
public void sayHi();
}
Having no clue why this error is thrown when the method is available in my EJB.
Will be really grateful from heart because i am already in soup.
What's the result of below code?
getUriMap().get("camelejb")
If you want to reference an endpoint in the camel route, you should do like this
<endpoint id="endpoint1" uri="direct:start"/>
<endpoint id="endpoint2" uri="mock:end"/>
<route>
<from ref="endpoint1"/>
<to uri="ref:endpoint2"/>
</route>

Resources