Does camel simple language support nested EL? - apache-camel

I am using Spring DSL in camel. I need substring of filename and camel throws error when using nested EL. Below is the code failed at 3rd log.
<setHeader headerName="CamelFileName">
<constant>sarada_chelluboyena_08032018.txt</constant>
</setHeader>
<log message="${header.CamelFileName.indexOf('chelluboye')}" loggingLevel="INFO"/>
<log message="${header.CamelFileName.substring(9,15)}" loggingLevel="INFO"/>
<log message="${header.CamelFileName.substring(${header.CamelFileName.indexOf('chelluboye')},15)}" loggingLevel="INFO"/>

Fixed using Groovy
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-groovy</artifactId>
</dependency>
<setHeader headerName="FileDate"> <groovy>request.headers.get("CamelFileName").substring((request.headers.get("CamelFileName").indexOf("TEST")+7),(request.headers.get("CamelFilName").indexOf("TEST")+13))</groovy>
</setHeader>

Related

Enable XML validation in CXF SOAP endpoint inside Camel route

I am developing a code-first SOAP service inside JBoss Fuse. I defined an interface my.endpoint.Interface with input and output classes. The wsdl is generated fine and the service is working. The endpoint is handled by CXF which invokes my Camel routes.
Versions:
JBoss Fuse 6.2.1
Apache Camel 2.15.1
Apache CXF 3.0.4
This is the configuration of my bundle:
<blueprint>
<cxf:cxfEndpoint id="myEndpoint"
address="/my/"
serviceClass="my.endpoint.Interface">
</cxf:cxfEndpoint>
<camelContext>
<route>
<from uri="cxf:bean:myEndpoint" />
<to uri="bean:doProcess" />
</route>
</camelContext>
</blueprint>
I would like to apply XML validation using an XSD to the incoming payloads.
How do I configure CXF in this particular environment?
I didn't find out where to specify the XSD CxfEndpointConfigurer interface:
<!-- blueprint file -->
<from uri="cxf:bean:myEndpoint?cxfEndpointConfigurer=configurer" />
// java file
#Override
public void configureServer(Server server) {
// where do I set XSD in here?
}
Configuring the cxfEndpoint in blueprint file raises an Exception at runtime
<cxf:cxfEndpoint id="readingsEndpoint"
address="/readings/"
serviceClass="my.endpoint.Interface">
<cxf:schemaLocations>
<schemaLocation>classpath:my/endpoint/schema1.xsd</schemaLocation>
</cxf:schemaLocations>
</cxf:cxfEndpoint>
Does not work, raising the following exception:
Unable to start blueprint container for bundle my.bundle/0.0.0.SNAPSHOT
java.lang.NullPointerException
at org.apache.aries.blueprint.container.RecipeBuilder.getValue(RecipeBuilder.java:355)[23:org.apache.aries.blueprint.core:1.4.4]
at org.apache.aries.blueprint.container.RecipeBuilder.getValue(RecipeBuilder.java:334)[23:org.apache.aries.blueprint.core:1.4.4]
at org.apache.aries.blueprint.container.RecipeBuilder.createBeanRecipe(RecipeBuilder.java:278)[23:org.apache.aries.blueprint.core:1.4.4]
at org.apache.aries.blueprint.container.RecipeBuilder.createRecipe(RecipeBuilder.java:110)[23:org.apache.aries.blueprint.core:1.4.4]
at org.apache.aries.blueprint.container.RecipeBuilder.createRepository(RecipeBuilder.java:93)[23:org.apache.aries.blueprint.core:1.4.4]
at org.apache.aries.blueprint.container.BlueprintContainerImpl.getRepository(BlueprintContainerImpl.java:481)[23:org.apache.aries.blueprint.core:1.4.4]
at org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintContainerImpl.java:328)[23:org.apache.aries.blueprint.core:1.4.4]
at org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintContainerImpl.java:269)[23:org.apache.aries.blueprint.core:1.4.4]
at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:294)[23:org.apache.aries.blueprint.core:1.4.4]
at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:263)[23:org.apache.aries.blueprint.core:1.4.4]
at org.apache.aries.blueprint.container.BlueprintExtender.modifiedBundle(BlueprintExtender.java:253)[23:org.apache.aries.blueprint.core:1.4.4]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:500)[17:org.apache.aries.util:1.1.0]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:433)[17:org.apache.aries.util:1.1.0]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$AbstractTracked.track(BundleHookBundleTracker.java:725)[17:org.apache.aries.util:1.1.0]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.bundleChanged(BundleHookBundleTracker.java:463)[17:org.apache.aries.util:1.1.0]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$BundleEventHook.event(BundleHookBundleTracker.java:422)[17:org.apache.aries.util:1.1.0]
at org.apache.felix.framework.util.SecureAction.invokeBundleEventHook(SecureAction.java:1127)[org.apache.felix.framework-4.4.1.jar:]
at org.apache.felix.framework.util.EventDispatcher.createWhitelistFromHooks(EventDispatcher.java:696)[org.apache.felix.framework-4.4.1.jar:]
at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:484)[org.apache.felix.framework-4.4.1.jar:]
at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4429)[org.apache.felix.framework-4.4.1.jar:]
at org.apache.felix.framework.Felix.startBundle(Felix.java:2100)[org.apache.felix.framework-4.4.1.jar:]
at org.apache.felix.framework.Felix.updateBundle(Felix.java:2412)[org.apache.felix.framework-4.4.1.jar:]
at org.apache.felix.framework.BundleImpl.update(BundleImpl.java:994)[org.apache.felix.framework-4.4.1.jar:]
at org.apache.karaf.shell.dev.watch.BundleWatcher.run(BundleWatcher.java:120)[43:org.apache.karaf.shell.dev:2.4.0.redhat-621084]
at java.lang.Thread.run(Thread.java:745)[:1.8.0_101]
In my contract-first setup I enable schema validation in a blueprint context like so:
<cxf:cxfEndpoint id="cxfEndpoint" address="http://0.0.0.0:${cxf.port}/${application-path}" serviceClass="my.generated.service.Class" >
<cxf:properties>
<entry key="schema-validation-enabled" value="true" />
</cxf:properties>
</cxf:cxfEndpoint>
This should work for code first just as well.
If your XSD is separate from the WSDL, i.e. a different file you can use the validator component.
<camelContext>
<route>
<from uri="cxf:bean:myEndpoint" />
<to uri="validator:my/endpoint/schema1.xsd" />
<to uri="bean:doProcess" />
</route>
</camelContext>
You should probably also enclose that with a doTry/doCatch or add an error handler to your route or context.
To configure the cxf-endpoint to set the Exchange body to the actual soap:body you can to the following:
<cxf:cxfEndpoint id="readingsEndpoint"
address="/readings/"
serviceClass="my.endpoint.Interface">
<cxf:properties>
<entry key="dataFormat" value="PAYLOAD"/>
</cxf:properties>
</cxf:cxfEndpoint>

set endpoint of an OSGI Blueprint file in ServiceMix

I know I can define Camel routes in stand-alone xml file, using the Blueprint syntax. If I move one of this file in the "deploy" folder of ServiceMix, it automatically becomes an OSGI bundle. My question is, can I set an endpoint to this new bundle, accessible from outside?
I would like to do something like this:
blue_route1.xml
<blueprint>
<camelContext>
<route>
<from uri="http:my_servicemix:8181/blue_route1_endpoint" />
<to uri="jetty:http://server1" />
</route>
</camelContext>
</blueprint>
blue_route1 becomes an OSGI bundle once deployed, but where should I define "blue_route1_endpoint" ? Is it doable?
[UPDATE]
summering, I want that an external WS is able to send messages to blue_route1_endpoint, where the blue_route1 bundle will redirect messages according to Camel routes, without the need to create a new WS "Blue_route1" to deploy in ServiceMix
______________________
| ____________ |
external-->(blue_route1_endpoint)==|==-->|blue_route1|--|-->(http://server1)
WS | |___________| |
|____________________|
ServiceMix
Found it! I didn't get that it's so easy. To make ServiceMix listen on a port, I just have to specify the endpoint using the Camel-jetty component.
So, to answer my question, I solved in this way:
install the camel-jetty component in ServiceMix
features:install camel-jetty
Write the camel-route with Blueprint, in blue_route1.xml file
<?xml version="1.0" encoding="UTF-8"?>
<blueprint
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0
http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
<camelContext xmlns="http://camel.apache.org/schema/blueprint">
<route>
<from uri:="jetty:http:my_servicemix:8181/blue_route1_endpoint">
<to uri="http://localhost:8080/user/services/user?bridgeEndpoint=true&throwExceptionOnFailure=false"/>
</route>
<route>
<from uri="jetty:http://0.0.0.0:6969/sp_role?matchOnUriPrefix=true"/>
<setHeader headerName="Content-Type">
<groovy>"text/xml; charset=utf-8"</groovy>
</setHeader>
<to uri="http://server1"/>
</route>
</camelContext>
</blueprint>
I used a random port 8181 to listen to... but I could choose every number, ServiceMix will automatically start a jetty component, listening and consuming on that port/endpoint.
For SOAP messages you need CXF Component and wsdl file of your webservice. You can configure your endpoint outside of the camelContext like this:
<cxf:cxfEndpoint id="yourId" address="/your/address/to/endpoint"
serviceClass="your.java.ServiceClass"
wsdlURL="path/to/your/wsdl/file.wsdl" />
And in your route use tag like this:
<from uri="cxf:bean:yourId"/>
You need to add namespace and schemaLocation to your blueprint to use cxf namespace, use this:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">

Rename file on remote scp failure launched by Camel ssh component

When using ssh component to launch a remote scp command I must set the body. The ssh component is using the body as the command to be executed remotely.
What I want to achieve is this:
Monitor folder for files. The "from" is using delete=true as I don't want to keep files once route is completed.
Copy the file on the DMZ server using sftp.
Launch a scp on the DMZ server using ssh.
In case of failure, scp does return code greater than 0, rename the file with ".failed".
Unfortunately using ssh require that I overwrite the body and I'm loosing the content of my file. I tried to use inOnly, sending to another route, but it does not make a copy of the file but probably a copy of the file pointer. I can't use wireTap because by the time it complete the remote execution, the route is completed and the file removed. I cannot use (I think) a temporary variable because the file can be up to gigabyte in size.
I'm using Camel version 2.12.1 running under Karaf 2.3.2. I'm trying to use blueprint XML only to avoid java coding as much as possible. Below a sample. The result, in case of non-zero exit code from ssh component, is the file contain my remote command.
<route id="RemoteTest1">
<!-- 1. Monitor for incoming files -->
<from uri="file:///data/karaf/tmp/RemoteTest1/?delete=true"/>
<!-- 2. Copy file on DMZ server -->
<to uri="sftp:username#myDmz.com//home/RemoteTest1/?privateKeyFile=myPrivateKey.pk"/>
<!-- 3. Execute scp remotely -->
<setHeader headerName="remoteCommand">
<simple>scp /home/RemoteTest1/${file:name} someuser#acme.com:${file:name}</simple>
</setHeader>
<doTry>
<inOnly uri="direct-vm:remoteExec"/>
<log message="Success"/>
<doCatch>
<exception>java.lang.Exception</exception>
<!-- 4. In case of failure rename the file by adding .failed -->
<to uri="file:?fileName=${file:absolute.path}.failed"/>
<log message="Failed"/>
</doCatch>
</doTry>
</route>
<route id="remoteExec">
<from uri="direct-vm:remoteExec"/>
<setBody>
<simple>${header.remoteCommand}</simple>
</setBody>
<to uri="ssh://username#myDmz.com?certResource=file:resources/keys/myPrivateKey.pk"/>
<!-- Throw exception on remote error -->
<choice>
<when>
<simple>${header.CamelSshExitValue} != '0'</simple>
<throwException ref="remoteExecException"/>
</when>
<otherwise>
<log message="scp completed normally"/>
</otherwise>
</choice>
</route>
<bean id="remoteExecException" class="java.lang.Exception">
<argument value="Failed remote execution" />
</bean>
Is there a solution? Any help or tip would be appreciated.
Thanks

JBOSS FUSE Bundle is waiting for namespace handlers in GracePeriod

I tried to add bean into blueprint.
Added CXF namespace. But, JBOSS FUSE shows
13:10:28,339 | INFO | NAPSHOT-thread-1 | BlueprintContainerImpl | 14 - org.apache.aries.blueprint.core - 1.0.1.redhat-60024 | Bundle camel-basic is waiting for namespace handlers [http://camel.apache.org/schema/cxf]
So, I remove the cxf and added blueprint namespace
http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd
But, still no use, It shows same error for this namespace also.
Do I need to change anything in pom, blueprint.xml r need install anything in jboss fuse?
I have no clue about this.
blueprint.xml
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/blueprint" xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<camelContext id="blueprintContext"
trace="false"
xmlns="http://camel.apache.org/schema/blueprint">
<route id="httpBridge">
<from uri="jetty:http://localhost:8282/service_sample_proxy/services_proxy/WebserviceClassPort?matchOnUriPrefix=true"/>
<process ref="downloadLogger"/>
<to uri="jetty:http://localhost:8080/service_sample/services/WebserviceClassPort?bridgeEndpoint=true&throwExceptionOnFailure=false"/>
<process ref="downloadLogger"/>
<to uri="bean:helloBean"/>
</route>
</camelContext>
<cxf:cxfEndpoint id="webserviceProxy"
address="http://localhost:8383/service_sample_proxy/services_proxy/WebserviceClassPort"
endpointName="tns:WebserviceClassPort"
serviceName="tns:WebserviceClassService"
wsdlURL="wsdl/webserviceclass.wsdl"
xmlns:tns="http://webservice/" />
<bean id="helloBean" class="org.fusesource.example.HelloBean" />
<bean id="downloadLogger" class="org.fusesource.example.DownloadLogger"/>
</blueprint>
I haven't used this bean in any place. First I need to resolve this problem then I need to use it in route.
I check the
Please help me.
Install all needed features into your Fuse container (see here for more information):
features:addUrl mvn:org.apache.camel.karaf/apache-camel/2.9.0/xml/features
features:install war
features:install cxf
features:install camel-jaxb
features:install camel-blueprint
features:install camel-cxf
Well, I went through all the steps stated above to find out it still does not work in blueprint.
Strangely as soon as the route was dropped in the spring xml and taken out of blueprint everything started working like a magic.
Tried camel-cxf instead cxf and worked with blueprint

Camel doesn't recognize faults as exceptions

I've encountered a very strange problem with Fuse ESB 7.1.0: when a cxf endpoint produces a fault, then this fault doesn't look like an exception, so I can't process it using doCatch construction.
The cxf endpoint is defined as follows:
<cxf:cxfEndpoint id="cxf-ep" address="${ws.url}" serviceClass="MyServiceClass">
<cxf:properties>
<entry key="dataFormat" value="POJO" />
</cxf:properties>
</cxf:cxfEndpoint>
And here is a short code snippet where I expect an exception:
<doTry>
<to uri="cxf:bean:cxf-ep" />
<doCatch>
<exception>org.apache.cxf.interceptor.Fault</exception>
<handled>
<constant>true</constant>
</handled>
<to uri="log:exceptions?multiline=true&showCaughtException=true&showStackTrace=true&showBody=true&showProperties=true&showHeaders=true&level=ERROR" />
</doCatch>
</doTry>
I've tried to add handleFault="true" attribute to both a camel context and a route, but without success.
A bundle with a similar parameters and routes has worked as expected on Fuse ESB/ServiceMix 4.4.1, so it looks like a regression or maybe something has changed in camel in the new release?
Another interesting moment is that when a web server is not available, then camel produces org.apache.cxf.interceptor.Fault, so it can't be handled as an exception!
Camel version: 2.10.0.fuse-71-047

Resources