How to access/set property via camel context programatically - apache-camel

I am using properties stored/defined in my blueprint.xml:
<cm:property-placeholder id="props.placeholder" persistent-id="props.blueprint">
<cm:default-properties>
...
<cm:property name="time.daysHistory" value="4" />
</cm:default-properties>
</cm:property-placeholder>
I am using this properties via injection (#PropertyInject) or with this syntax{{time.daysHistory}}.
Is there a way to read and or set those properies from within my Bluprinttests?
I tried context.getProperties() but this returns an empty map.

Like Claus mentioned you need to use the useOverridePropertiesWithConfigAdmin method. However note, you need to return the same pid value as the one configured in your blueprint.
Your blueprint:
<cm:property-placeholder id="props.placeholder" persistent-id="props.blueprint">
<cm:default-properties>
...
<cm:property name="time.daysHistory" value="4" />
</cm:default-properties>
</cm:property-placeholder>
In your test add:
#Override
protected String useOverridePropertiesWithConfigAdmin(Dictionary props) {
props.put("time.daysHistory", "1");
return "props.blueprint";
}
EDIT:
Here is how I have done it:
In my route I have injected properties:
#PropertyInject("DatasetConsumePath")
private String datasetConsumePath;
#PropertyInject("DatasetFileExtension")
private String datasetFileExtension;
My blueprint:
<cm:property-placeholder id="test" persistent-id="test" update-strategy="reload">
<cm:default-properties>
<cm:property name="DatasetConsumePath" value="test"/>
<cm:property name="DatasetFileExtension" value="txt"/>
<cm:property name="DatasetAggregateBatchSize" value="1000"/>
</cm:default-properties>
</cm:property-placeholder>
My test:
#Override
protected String useOverridePropertiesWithConfigAdmin(Dictionary props) {
// add the properties we want to override
props.put("DatasetConsumePath", "src/test/resources/test files/test/");
// return the PID of the config-admin we are using in the blueprint xml file
return "test";
}

See the documentation: http://camel.apache.org/using-propertyplaceholder.html about the loadConfigAdminConfigurationFile and useOverridePropertiesWithConfigAdmin methods you can use from unit tests.

Related

How to externalise sslContextParameters

I'm using Apache Camel 2.20.0 and deploying a REST service using REST DSL with a HTTP scheme.
I'm referencing sslContextParameters with hard coded values and all works just fine.
I can't find a way of externalizing the resource into a properties file. So far I've tried with Camel PropertiesComponent and also Spring PropertyPlaceholderConfigurer and BridgePropertyPlaceholderConfigurer and I want to be able to do the following in the config:
<camel:sslContextParameters camelContextId="camelContext1" id="routeSSLContextParameters">
<camel:keyManagers keyPassword="{{mypassword}}">
<camel:keyStore password="{{mypassword}}"
resource="{{mykeystore}}" type="JKS"/>
</camel:keyManagers>
<camel:trustManagers>
<camel:keyStore password="{{mypassword}}"
resource="{{mykeystore}}" type="JKS"/>
</camel:trustManagers>
</camel:sslContextParameters>
I've also tried putting ${} as per Spring properties, this also does not work.
Would it be possible to tell me where I'm going wrong?
Try adding the BridgePropertyPlaceholderConfigurer to your Spring Context and use the ${} placeholder:
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<!-- bridge spring property placeholder with Camel -->
<!-- you must NOT use the <context:property-placeholder at the same time,
only this bridge bean -->
<bean id="bridgePropertyPlaceholder" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
<property name="location" value="classpath:com/stackoverflow/camel/labs/keys.properties" />
</bean>
<camel:camelContext id="exampleSsl" />
<camel:keyStoreParameters id="ksp" camelContextId="exampleSsl" resource="${keyStoreParameters.resource}" type="${keyStoreParameters.type}" provider="${keyStoreParameters.provider}" password="${keyStoreParamerers.password}" />
</beans>
The properties file:
keyStoreParameters.resource=/users/home/server/keystore.jks
keyStoreParameters.type=jks
keyStoreParameters.provider=jks
keyStoreParamerers.password=test
And the unit test:
public class SSLPlaceholderCamelTest extends CamelSpringTestSupport {
#Test
public void test() {
assertNotNull(super.context);
KeyStoreParameters ksp = (KeyStoreParameters)super.applicationContext.getBean("ksp");
assertThat(ksp.getType(), is("jks"));
assertThat(ksp.getProvider(), is("jks"));
assertThat(ksp.getResource(), is("/users/home/server/keystore.jks"));
assertThat(ksp.getPassword(), is("test"));
}
#Override
protected AbstractApplicationContext createApplicationContext() {
return new ClassPathXmlApplicationContext("com/stackoverflow/camel/labs/SSLPlaceholderCamelTest.xml");
}
}
EDIT:
Yeah, I've tested with camel:sslContextParameters and the properties weren't bidden. You could access it via context and set programmatic (Setting Client Authentication On the Server Side):
KeyStoreParameters ksp = (KeyStoreParameters)context.getBean("keystore");
KeyStoreParameters tsp = (KeyStoreParameters)context.getBean("truststore");
KeyManagersParameters kmp = new KeyManagersParameters();
kmp.setKeyStore(ksp);
kmp.setKeyPassword("keyPassword");
SSLContextServerParameters scsp = new SSLContextServerParameters();
scsp.setClientAuthentication(ClientAuthentication.REQUIRE);
SSLContextParameters scp = (SSLContextParameters)context.getBean("sslContext");
scp.setServerParameters(scsp);
scp.setKeyManagers(kmp);
SSLContext context = scp.createSSLContext();
SSLEngine engine = scp.createSSLEngine();
The context:
<camel:keyStoreParameters id="keystore"
camelContextId="exampleSsl" resource="${keyStoreParameters.resource}"
type="${keyStoreParameters.type}" provider="${keyStoreParameters.provider}"
password="${keyStoreParamerers.password}" />
<camel:keyStoreParameters id="trustsore"
camelContextId="exampleSsl" resource="${keyStoreParameters.resource}"
type="${keyStoreParameters.type}" provider="${keyStoreParameters.provider}"
password="${keyStoreParamerers.password}" />
<camel:sslContextParameters id="sslContext" camelContextId="exampleSsl" />
Just "autowire" it in your Camel Context.
This is what I did in the end:
1.Use Spring/Camel properties bridge:
<bean class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer" id="springProperties">
<property name="location" value="classpath:application.properties"/>
</bean>
2.Set up the SSLContext Parameters from Spring:
<bean class="org.apache.camel.util.jsse.SSLContextParameters" id="routeSSLContextParameters">
<property name="keyManagers" ref="routeKeyManagers"/>
<property name="trustManagers" ref="routeTrustManagers"/>
<property name="serverParameters" ref="routeSSLContextServerParameters"/>
</bean>
<bean class="org.apache.camel.util.jsse.KeyManagersParameters" id="routeKeyManagers">
<property name="keyStore" ref="routeKeystore"/>
<property name="keyPassword" value="${keyStorePassword}"/>
</bean>
<bean class="org.apache.camel.util.jsse.TrustManagersParameters" id="routeTrustManagers">
<property name="keyStore" ref="routeTruststore"/>
</bean>
<bean class="org.apache.camel.util.jsse.SSLContextServerParameters" id="routeSSLContextServerParameters">
<property name="clientAuthentication" value="REQUIRE"/>
</bean>
<keyStoreParameters id="routeKeystore" password="${keyStorePassword}" resource="${keyStoreResource}" type="JKS" xmlns="http://camel.apache.org/schema/spring"/>
<keyStoreParameters id="routeTruststore" password="${trustStorePassword}" resource="${trustStoreResource}" type="JKS" xmlns="http://camel.apache.org/schema/spring"/>
Reference the SSLContext in the restconfiguration
<restConfiguration apiContextPath="api-docs" bindingMode="json" component="restlet" contextPath="/mytest" enableCORS="true"
host="localhost" port="9090" scheme="https">
<endpointProperty key="sslContextParameters" value="#routeSSLContextParameters"/>.....

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.

Multiple Camel Proxys in same camel context

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);
}
}

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>

Injecting CXF JAXRS MessageContext in an "in Interceptor"

I am trying to inject MessageContext in an Interceptor with the Phase as READ as follows
#Context
org.apache.cxf.jaxrs.ext.MessageContext.MessageContext messageContext;
But this is not getting initialized and remains null. Is it possible to inject org.apache.cxf.jaxrs.ext.MessageContext.MessageContext in Interceptor?
Thanks
You might need to add <aop:scoped-proxy/> into the cxf configuration file:
<jaxrs:server id="example" address="/">
<jaxrs:serviceBeans>
<bean class="org.apache.cxf.systest.jaxrs.CustomerService">
<aop:scoped-proxy />
</bean>
</jaxrs:serviceBeans>
</jaxrs:server>
Also you have to create a setter method for your messageContext (this should be in your service class - here it is "org.apache.cxf.systest.jaxrs.CustomerService"):
private MessageContext messageContext;
#Context
public void setMessageContext(MessageContext messageContext) {
this.messageContext = messageContext;
}
Consider also this documentation link:
http://cxf.apache.org/docs/jaxrs-services-configuration.html#JAXRSServicesConfiguration-FromSpring

Resources