Camel doesn't recognize faults as exceptions - cxf

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

Related

Limit netty4 tcp endpoint to a single instance

I have a mock endpoint at 8001 that will echo anything provided to it.
I have an http endpoint that will submit the end of the URL to the mock endpoint, and provide a response from the endpoint's response.
That works fine.
The challenge is, I want the http route to use only 1 tcp connection to the 8001 endpoint.
I created a worker group as explained elsewhere, and set the worker count to 1. Looking through the source code, I'm thinking this approach should work.
However, when I do this bash command:
for a in {1..5}; do curl "http://localhost:8080/upstream/REQUESTNUM$a" > $a.txt & done;
I see multiple connections to 8001. I would have expected the http endpoint requests would have to share a single pool worker, but that doesn't seem to be the case.
Perhaps I am missing something, or perhaps there is another way to accomplish my goal of using only 1 back-end tcp connection for all the http requests.
How do I accomplish it?
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<camelContext
xmlns="http://camel.apache.org/schema/spring">
<route id="mockUpstream">
<from
uri="netty4:tcp://localhost:8001?sync=true&textline=true&keepAlive=true&disconnect=false&reuseChannel=true" />
<log message="Incoming to upstream: ${body}" />
<transform>
<simple>${body}</simple>
</transform>
</route>
<route id="httpServer">
<from
uri="netty4-http:http://0.0.0.0:8080/upstream?matchOnUriPrefix=true" />
<!-- optional just use CamelHttpQuery from header, for full query -->
<log
message="Incoming http command: ${in.headers[CamelHttpPath]}" />
<transform>
<simple>${in.headers[CamelHttpPath]}</simple>
</transform>
<to
uri="netty4:tcp://localhost:8001?workerGroup=#sharedPool&sync=true&textline=true&keepAlive=true&disconnect=false&reuseChannel=true" />
<transform>
<simple>${body}</simple>
</transform>
</route>
</camelContext>
<bean id="poolBuilder"
class="org.apache.camel.component.netty4.NettyWorkerPoolBuilder">
<property name="workerCount" value="1" />
</bean>
<bean id="sharedPool" class="io.netty.channel.EventLoopGroup"
factory-bean="poolBuilder" factory-method="build"
destroy-method="shutdown">
</bean>
</beans>
Looking at the logs, with TRACE level logging, I saw the NettyProducer's pool was indeed set to use 1 max active connection, but the NettyProducer was allowed 100 idle connections. I changed the following line and it is now behaving as expected:
<to
uri="netty4:tcp://localhost:8001?workerGroup=#sharedPool&sync=true&textline=true&keepAlive=true&disconnect=false&reuseChannel=true&producerPoolMaxActive=1&producerPoolMaxIdle=1" />
I assumed the "producer" settings were only good for the producer side (netty in mock host route) of the connection, but it looks like they can be used by the consumer end (netty in http route), too.
edit: I confused the terms producer and consumer and got that backwards above. Seeing that the "to" element is producing a request for something to consume, the producer* parameters make sense for (netty in http route). The (netty in mock host route) is the consumer of requests.

If we browse context path, Internal jaxws endpoint should not visible with context path on the browser

Thank you in advance.
Can you please give me possible solution to fix below problem.
Problem is internal jaxws endpoint should not visible on the bowser, when we browse context path(ex: http://localhost:8080/cws-finance/services).
 service name is PaymentWs. PaymentWs service has two version’s(1.1,1.2) of wsdls.
 We created two external cxf endpoints and one jaxws internal end point.
 First external endpoint interact with 1.1 version wsdl and second external endpoint interact with 1.2 version wsdl
 Internal jaxws endpoint interact with java code(serviceImpl)
 We are using camel routing to route external endpoints to internal endpoint.
 If I browse context path(ex: http://localhost:8080/cws-finance/services). I can view two are external endpoints and one is internal endpoint on the browser.
 As per requirement , internal endpoint should not view on the browser. Only two external endpoints should be visible.
 I am doing migration from service mix bundle to web application(war) deploying in tomcat. In servicemix ,it was working as per requirement. This requirement was achieved in servicemix by using NMR api with JBI container.
Internal jaxws endpoint configuration:
<jaxws:endpoint id="paymentWS" implementor="#paymentWSImp"
endpointName="tns:PaymentWSPort" address="/nmr/PaymentWS/1.2/Port"
serviceName="tns:PaymentWSService" xmlns:tns="http://www.centurytel.com/PaymentWS">
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature" />
</jaxws:features>
<jaxws:properties>
<entry key="schema-validation-enabled" value="true" />
</jaxws:properties>
</jaxws:endpoint>
External cxf endpoints configurations:
<cxf:cxfEndpoint id="paymentWS_1_1" address="/PaymentWS/1.1/Port"
endpointName="s:PaymentWSPort" serviceName="s:PaymentWSService"
wsdlURL="wsdl/paymentws_1.1.wsdl" xmlns:s="http://www.centurytel.com/PaymentWS">
<cxf:properties>
<entry key="dataFormat" value="MESSAGE" />
</cxf:properties>
</cxf:cxfEndpoint>
<cxf:cxfEndpoint id="paymentWS_1_2" address="/PaymentWS/1.2/Port"
endpointName="s:PaymentWSPort" serviceName="s:PaymentWSService"
wsdlURL="wsdl/paymentws_1.2.wsdl" xmlns:s="http://www.centurytel.com/PaymentWS">
<cxf:properties>
<entry key="dataFormat" value="MESSAGE" />
</cxf:properties>
</cxf:cxfEndpoint>
Camel routing:
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route id="paymentWS_1_1_route">
<from uri="cxf:bean:paymentWS_1_1" />
<setExchangePattern pattern="InOut" />
<convertBodyTo type="javax.xml.transform.stream.StreamSource" />
<to uri=" http://localhost:8080/cws-finance/services /nmr/PaymentWS/1.2/Port"/>
<process ref="PaymentWS_1_1_ProxyOutProc" />
<to uri="log:input" />
</route>
<route id="paymentWS_1_2_route">
<from uri="cxf:bean:paymentWS_1_2" />
<setExchangePattern pattern="InOut" />
<convertBodyTo type="javax.xml.transform.stream.StreamSource" />
<to uri=" http://localhost:8080/cws-finance/services /nmr/PaymentWS/1.2/Port"/>
<to uri="log:input" />
</route>
</camelContext>

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>

Camel and Spring Integration

I want to test camel spring integration example from the apache camel site
http://camel.apache.org/springintegration.html but I am getting the exception
org.apache.camel.RuntimeCamelException: org.springframework.integration.MessageDeliveryException: Dispatcher has no subscribers for channel outputchannel.
my short code is given below:
<channel id="inChannel"/>
<channel id="outputChannel"/>
<beans:bean id="greeting" class="com.javarticles.spring.integration.Greeting"/>
<service-activator input-channel="inChannel" ref="greeting" method="sayHello" output-channel="outputChannel"/>
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="activemq:activemqsource"/>
<to uri="log:input"/>
<to uri="spring-integration:inChannel? inputChannel=outputChannel"/>
<to uri="log:output"/>
</route>
I tried to search related problems but I did not get with camel could any one tell me how to subscribe the outputchannel
According to the Camel documentation mentioned by you, the config should be like this:
<to uri="spring-integration:inputChannel?inOut=true&inputChannel=outputChannel"/>
Your issue is inOut=true:
The exchange pattern that the Spring integration endpoint should use. If inOut=true then a reply channel is expected, either from the Spring Integration Message header or configured on the endpoint.

messages not being consumed by apache camel using servicemix as a broker

So I'm trying to use apache servicemix/camel to aggregate some messages coming through a JMS queue. The logic I have is dead-simple I just want it to use the last message received and only send it through 3 seconds after the last one.
I have servicemix setup as a message broker and I'm able to use it in such a capacity however it doesn't seem to trigger the route. I've never done this before so odds are I'm horribly off-base but here is what I have so far (put this in deploy/fedora-messaging/camel-context.xml)
<?xml version="1.0" encoding="UTF-8"?>
<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-2.5.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="activemq:topic:fedora.apim.update.merge"/>
<aggregate completionTimeout="3000">
<correlationExpression>
<simple>header.pid</simple>
</correlationExpression>
<to uri="log:events"/>
<to uri="activemq:topic:fedora.apim.update"/>
</aggregate>
</route>
</camelContext>
<bean id="activemq"
class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
</beans>
The osgi application appears to start and run without error, and messages are received and queued in the topic:fedora.apim.update.merge however they just sit in the queue and never get consumed or pushed out to the destination queue.
I tested your route as a standalone application (outside of a ServiceMix container) with following broker configuration and everything worked as expected:
<broker xmlns="http://activemq.apache.org/schema/core" useJmx="true"
persistent="false">
<transportConnectors>
<transportConnector uri="tcp://localhost:61616" />
</transportConnectors>
</broker>
So, I guess, we can assume that your Camel route definition is not the problem but the ActiveMQ configuration and/or ServiceMix set-up.
EDIT:
Note, that messages to JMS topic destinations are lost if no active subscriber is connected to the destination. If you need some kind of persistence use durable subscribers or JMS queue destinations.

Resources