Apache Camel CXF Transport - Adding interceptors to JaxWs Client - apache-camel

We are invoking a soap service through RabbitMQ using Camel transport JaxWS client as given below (Ref: http://camel.apache.org/better-jms-transport-for-cxf-webservice-using-apache-camel.html , and used camel-cxf-transport version 2.15.2).
Service invoked successfully, but could not add interceptors to the JaxWS client proxy. Tried the following:
<client id="TestService" xmlns="http://cxf.apache.org/jaxws"
xmlns:testsvc="http://mytest.com/services/test/v2"
serviceName="testsvc:Test_v2_0_service" endpointName="testsvc:HttpTestPort"
address="camel://direct:TestService" serviceClass="test.v2.TestSVCV20" >
<outInterceptors>
<ref bean="wss4jOutInterceptor" />
</outInterceptors>
<features>
<logging xmlns="http://cxf.apache.org/core"/>
</features>
</client>
<bean id="wss4jOutInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
<constructor-arg>
<map>
<entry key="action" value="testToken" />
<entry key="user" value="dummy" />
<entry key="passwordType" value="PasswordTestTxt" />
<entry key="passwordCallbackClass" value="test.PwdCallbackclass" />
</map>
</constructor-arg>
</bean>
When interceptor tag with bean ref is added it is showing the following error:
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Cannot locate BeanDefinitionParser for element [ref]
Can anyone please help with a sample on how to correctly add the interceptors in camel transport cxf client?
Thanks.

The problem is resolved. Added namespace declaration for spring elements to solve the issue.
Please see the link for more details :
http://camel.465427.n5.nabble.com/Apache-Camel-CXF-Transport-Adding-interceptors-to-JaxWs-Client-td5770596.html
Thanks.

Related

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>

camel cxf giving error when sending large xml

When calling a SOAP service I am getting response 302 when the XML message size is large but works when the message size is small.
Though when I post the same message on a SoapUI I am getting a correct response for both small and large messages.
Is there a limit to message length in camel cxf, if yes?
How can I change the limit?
Camel 2.10
JBoss Fuse 6.0.0
This the extract of my cxfEndpoint
<cxf:cxfEndpoint id="remindaWsEndpoint" address="https://example.service.abc.com/BasicService"
serviceName="s:ABCService"
endpointName="s:ABCHttpBinding_ABCService"
wsdlURL="/META-INF/wsdl/ABCService.wsdl"
xmlns:s="http://www.example.com">
<cxf:outInterceptors>
<ref bean="loggingOutInterceptor" />
</cxf:outInterceptors>
<cxf:inInterceptors>
<ref bean="loggingInInterceptor"/>
</cxf:inInterceptors>
<cxf:properties>
<entry key="dataFormat" value="PAYLOAD" />
<entry key="allowStreaming" value="true" />
<entry key="defaultOperationName" value="ABCOperations"/>
<entry key="defaultOperationNamespace" value="http://www.example.com"/>
</cxf:properties>
</cxf:cxfEndpoint>
HTTP 302 is not an error. It means the server is trying to redirect you to another url. Ensure your route configuration can handle that.
https://en.wikipedia.org/wiki/HTTP_302

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>

CXF OutInterceptor uses the wrong SoapPartImpl class resulting in a org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR exception

I have a J2EE app that (for legacy reasons) has both the Axis2 and CXF libraries used for different provider end-points both used by the application.
I have implemented a new client end-point that connects to a third party provider via CXF. The end points requires that authentication details are to to be placed into the SoapHeaders (and not HTTP headers).
The spring config is as below:
<jaxws:client id="fareSearchServicePort" serviceClass="org.openaxisgroup.axisschemadocs.v1r1_va.AxisPort"
address="${endpoint}faresearch">
<jaxws:features>
<ref bean="gzipFeature"/>
<ref bean="fastInfosetFeature"/>
<!--<ref bean="loggingFeature"/>-->
</jaxws:features>
<jaxws:properties>
<entry key="org.apache.cxf.binding.soap.messageFactoryClassName" value="com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl" />
</jaxws:properties>
<jaxws:outInterceptors>
<ref bean="outPasswordInterceptor" />
</jaxws:outInterceptors>
</jaxws:client>
<bean id="outPasswordInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
<entry key="signaturePropFile" value="..."/>
<entry key="passwordCallbackRef" value-ref="myPasswordCallback"/>
</map>
</constructor-arg>
</bean>
Without the outInterceptors, the connection work's fine and simply fails to authenticate.
With the inclusion of the interceptor, somewhere along the line, the code is delegated to the Axis2 libraries resulting in "org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR". The is even before the password callback method is touched. The stacktrace:
org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
at org.apache.axiom.om.impl.dom.ParentNode.insertBefore(ParentNode.java:224)
at org.apache.axiom.om.impl.dom.NodeImpl.appendChild(NodeImpl.java:240)
at org.apache.axis2.saaj.SOAPPartImpl.appendChild(SOAPPartImpl.java:979)
at org.apache.cxf.staxutils.W3CDOMStreamWriter.setChild(W3CDOMStreamWriter.java:114)
at org.apache.cxf.staxutils.W3CDOMStreamWriter.newChild(W3CDOMStreamWriter.java:104)
at org.apache.cxf.staxutils.W3CDOMStreamWriter.writeStartElement(W3CDOMStreamWriter.java:132)
at org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor.writeSoapEnvelopeStart(SoapOutInterceptor.java:122)
at org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor.handleMessage(SoapOutInterceptor.java:81)
at org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor.handleMessage(SoapOutInterceptor.java:61)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:244)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:516)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:313)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:265)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:73)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:124)
at $Proxy144.axisTransaction(Unknown Source)
How do I specify the SOAPPartImpl to use? (ie. com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl)
You don't mention the version of CXF used. Definitely try using the latest version (2.6.2 right now, although 2.6.3 is being voted on now). There has been some work recently on getting the various older SAAJ implementations usable. Just updating to the latest CXF might fix it.
If that doesn't help, you can set a system property of "org.apache.cxf.binding.soap.messageFactoryClassName" and/or "org.apache.cxf.binding.soap.soapFactoryClassName" to the appropriate Sun class name and the should work.

IllegalStateException on camel cxf route in FUSE (servicemix) ESB

I try to set up a camel (Ver. 2.4.0) route in a FUSE (Ver. 4.3.0) ESB/OSGi container.
It should be a simple cxf-proxy to route a WebService call from a 'proxy' address to a real service.
I read several documentation:
CXF Proxy Example
camel cxf component
and set up the following spring configuration:
<?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"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xmlns:cxf="http://camel.apache.org/schema/cxf"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://camel.apache.org/schema/osgi
http://camel.apache.org/schema/osgi/camel-osgi.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd
http://camel.apache.org/schema/cxf
http://camel.apache.org/schema/cxf/camel-cxf.xsd">
<import
resource="classpath:META-INF/cxf/cxf.xml" />
<import
resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import
resource="classpath:META-INF/cxf/cxf-extension-http.xml" />
<import
resource="classpath:META-INF/cxf/osgi/cxf-extension-osgi.xml" />
<!-- the proxy service -->
<cxf:cxfEndpoint
id="myServiceProxy"
address="http://localhost:9003/cxf/myService"
serviceClass="foo.bar.iface.MyServiceInterface" />
<!-- my real existing cxf soap service -->
<cxf:cxfEndpoint
id="myService"
address="http://foo.bar/services/myService"
wsdlURL="http://foo.bar/services/myService?wsdl"
serviceClass="foo.bar.iface.MyServiceInterface"
serviceName="s:MyService"
endpointName="s:MyServiceEndpoint"
xmlns:s="http://foo.bar/iface/" />
<!-- route -->
<camel:camelContext>
<camel:route>
<camel:from
uri="cxf:bean:myServiceProxy" />
<camel:to
uri="cxf:bean:myService" />
</camel:route>
</camel:camelContext>
</beans>
Trying to start the bundle in FUSE leads to this exception
karaf#root> Exception in thread "SpringOsgiExtenderThread-22" org.apache.camel.RuntimeCamelException: java.lang.IllegalStateException: Endpoint address should be a relative URI wrt to the servlet address (use '/xxx' for example)
at org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException(ObjectHelper.java:1126)
at org.apache.camel.spring.SpringCamelContext.onApplicationEvent(SpringCamelContext.java:103)
at org.apache.camel.spring.CamelContextFactoryBean.onApplicationEvent(CamelContextFactoryBean.java:231)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:97)
I do not know what's wrong. I doubt that my Endpoint address is wrong and I do not know what my servlet address is (there is no cxf:cxfEndoint servelt address attribute).
Any help to lead me in the right direction to solve this problem would be appreciated.
Thanks
Klaus
I finally found out what's wrong.
Instead
<!-- the proxy service -->
<cxf:cxfEndpoint
id="myServiceProxy"
address="http://localhost:9003/cxf/myService"
serviceClass="foo.bar.iface.MyServiceInterface" />
it has to be
<!-- the proxy service -->
<cxf:cxfEndpoint
id="myServiceProxy"
address="/myService"
serviceClass="foo.bar.iface.MyServiceInterface" />
As the first approach worked well running the camel project outside FUSE (in this case a the http server will be started to provide the service) it has to be a relative address inside FUSE.
Inside FUSE the embedded HTTP server which runs on (localhost:8181) will be used and the service url will be extended to http://localhost:8181/cxf/myService.

Resources