I am experiencing an interesting dilemma with Apache Camel and CXF.
I try to build following routes.
from("servlet://proxy?matchOnUriPrefix=true")
.to("cxf:/incident?wsdlURL=wsdl/OrderInfoService.wsdl&dataFormat=MESSAGE");
`from("cxf:/incident?wsdlURL=wsdl/OrderInfoService.wsdl&dataFormat=MESSAGE").to("file:/META-INF/data/test.xml");`
My wish actually is to receive the request with Servlet Component, do something with (processor, transform, etc but I excluded here for simplicity reasons) redirect this to my WebService implementation and the file component return the content of a file as a result to WebService.
The problem is, if I make from Endpoint 'from("servlet://proxy?matchOnUriPrefix=true")' routing to Endpoint 'to("cxf:/incident?wsdlURL=wsdl/OrderInfoService.wsdl&dataFormat=MESSAGE")' Camel thinks this should be CXF Consumer but I want it to be a Producer.
So I actually I like to route from from("servlet://proxy?matchOnUriPrefix=true") to 'from("cxf:/incident?wsdlURL=wsdl/OrderInfoService.wsdl&dataFormat=MESSAGE")' but I could not figure out a way to do it.
If I configure as the first configuration, the servlet component receives the request, routes to CXF:consumer then it starts a TCP call to CXF:Producer defined in 'from("cxf:/incident?wsdlURL=wsdl/OrderInfoService.wsdl&dataFormat=MESSAGE")' it works but it is weird, I don't want to start a TCP call, I just want that the message goes to 'from("cxf:/incident?wsdlURL=wsdl/OrderInfoService.wsdl&dataFormat=MESSAGE")'.
Is there a way to achieve what I want? Can I define a CXF Consumer or Provider other then using 'from', 'to'?
Funnily I did something similar with ServiceMix/Fuse.
<?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:osgiRouter="http://osgi.salgar.org/osgirouter"
xmlns:http="http://servicemix.apache.org/http/1.0"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://servicemix.apache.org/http/1.0 http://servicemix.apache.org/http/1.0/servicemix-http.xsd">
<http:consumer service="http:FindOrders" endpoint="httpEndpoint" locationURI="http://localhost:8088/MockB2BService"
defaultMep="http://www.w3.org/2004/08/wsdl/in-out" targetService="osgiRouter:mediation" />
<bean class="org.apache.servicemix.common.osgi.EndpointExporter" />
</beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:eip="http://servicemix.apache.org/eip/1.0"
xmlns:osgiRouter="http://osgi.salgar.org/osgirouter"
xmlns:orderProvider_v1="http://v1.salgar.org/B2BService"
xmlns:orderProvider_v2="http://v2.salgar.org/B2BService"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://servicemix.apache.org/eip/1.0 http://servicemix.apache.org/eip/1.0/servicemix-eip.xsd">
<eip:content-based-router endpoint="osgiRouterMediation"
service="osgiRouter:mediation">
<eip:rules>
<eip:routing-rule>
<eip:predicate>
<eip:xpath-predicate id="wsdl_version_predicate_v1"
xpath="(//namespace::*[.='http://v1.salgar.org/B2BService']) = 'http://v1.salgar.org/B2BService'" />
</eip:predicate>
<eip:target>
<eip:exchange-target service="orderProvider_v1:findOrders" />
</eip:target>
</eip:routing-rule>
<eip:routing-rule>
<eip:predicate>
<eip:xpath-predicate id="wsdl_version_predicate_v2"
xpath="(//namespace::*[.='http://v2.salgar.org/B2BService']) = 'http://v2.salgar.org/B2BService'" />
</eip:predicate>
<eip:target>
<eip:exchange-target service="orderProvider_v2:findOrders" />
</eip:target>
</eip:routing-rule>
</eip:rules>
</eip:content-based-router>
<bean class="org.apache.servicemix.common.osgi.EndpointExporter" />
</beans>
<?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:cxfbc="http://servicemix.apache.org/cxfbc/1.0"
xmlns:orderProvider_v1="http://v1.salgar.org/B2BService"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://servicemix.apache.org/cxfbc/1.0 http://servicemix.apache.org/cxfbc/1.0/servicemix-cxf-bc.xsd">
<cxfbc:provider endpoint="findOrdersProviderEndpoint"
useJBIWrapper="false" wsdl="classpath:v1/B2BService.wsdl" service="orderProvider_v1:findOrders"
locationURI="http://localhost:8989/MockB2BService" />
<bean class="org.apache.servicemix.common.osgi.EndpointExporter" />
</beans>
Which works as expected but there I could define the endpoint explicitly as CXF provider, do I have the same possibility here?
If I understand your problem right, this will work (and ideal solution in camel)
Route A
from("servlet://proxy?matchOnUriPrefix=true")
.to("direct:webservice-business-logic")
.to("direct:process-to-file");
Route B
from("direct:webservice-business-logic")
.to("actual-processors-to-do-webservice-business-logic");
Route C
from("cxf:/incident?wsdlURL=wsdl/OrderInfoService.wsdl&dataFormat=MESSAGE")
.to("direct:webservice-business-logic);
Basically, Route C will be used only by external parties who wants to use the webservice.
Route B will be used only by Route A, So Route B is meant for Internal camel processing. Because there is no point in calling a webservice , where the webservice logic also sits in the camel route.
Hope this helps !
Related
I'm trying to use Apache Camel's Http4 component to connect to a HTTP URL that needs Basic authentication. I'm setting credentials from a camel processor through Exchange.HTTP_QUERY header. I configure my route like this:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint ...>
<bean id="myProcessor"
class="com.myCompany.Bean"
factory-method="myProcessorBean">
</bean>
<camelContext id="myContext" xmlns="http://camel.apache.org/schema/blueprint">
<route id="myRoute>
<from uri="activemq:queue:myQueue" />
<process ref="myProcessor" />
<to uri="http4://oldhost"/>
</route>
</camelContext>
</blueprint>
and my processor looks like:
public void process(Exchange exchange) throws Exception {
String user = getUserFromDB();
String pwd = getPasswordFromDB();
String queryParameters = "authMethod=Basic&authPassword="+pwd+"authUsername="+user;
exchange.getIn().setHeader(Exchange.HTTP_QUERY, queryParameters);
exchange.getIn().setHeader(Exchange.HTTP_URI, "api.abc_company.com/service/to/consume");
....
}
It results in:
Error myContext: org.apache.camel.http.common.HttpOperationFailedException: HTTP operation failed invoking https://api.abc_company.com/service/to/consume?authMethod=Basic&authPassword=xxxxxx&authUsername=test with statusCode: 401
It seems that password was changed to xxxxxx but I'm not sure.
When I try hardcoding user and password in the URI it works well, however I need a way to set these values programmatically due to user and password are stored it the DB.
"authMethod=Basic&authPassword="+pwd+"authUsername="+user;
You'll need to at & between each uri parameter. You're missing one after password.
Try:
String queryParameters = "authMethod=Basic&authPassword="+pwd+"&authUsername="+user;
Also you should define credentials in producer endpoint URI http4://oldhost?authMethod=Basic&authPassword="+pwd+"&authUsername="+user instead of header: Exchange.HTTP_QUERY.
If you want to do this in your processor you can try to set Authorization header manually with value basic <credentials> where <credentials> is base64 encoded username:password.
Failed invoking https://api.abc_company.com/service/to/consume?
If you want to connect to https site use https4://
I am trying to throw exception on camel. I am on version 2.2.170.redhat-000013. When I use below code in spring DSL
<throwException id="_throwException1" exceptionType="org.mycompany.MyException" message="Test Exception"/>
Gives
Multiple annotations found at this line:
- cvc-complex-type.4: Attribute 'ref' must appear on element 'throwException'.
- cvc-complex-type.3.2.2: Attribute 'exceptionType' is not allowed to appear in element
'throwException'.
- cvc-complex-type.3.2.2: Attribute 'message' is not allowed to appear in element
'throwException'.
Schema location in my project is as below
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:camel="http://camel.apache.org/schema/spring" 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" >
throwException syntax should work as per documentation, please help to find mistake.
In my application, I have 2 bundles. Both are using cxf to create Restful server.
In those bundles I load cxf via blueprint. I define cxf:bus on those bundles with the same id to expect that two bundle will share the same bus instance then I can configure a Authentication interceptor on one bundle and It will apply for the other bundle also.
They looks like below.
Bundle 1:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
xmlns:cxf="http://cxf.apache.org/blueprint/core"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
">
<bean id="authInterceptor" class="com.dasannetworks.vn.rest.impl.AuthInterceptorImpl"></bean>
<cxf:bus id="my-app-bus" name="tutorial">
<cxf:inInterceptors>
<ref component-id="authInterceptor"/>
</cxf:inInterceptors>
</cxf:bus>
<bean id="Rest1ServiceImpl"class="com.dasannetworks.vn.rest.impl.Rest1ServiceImpl"></bean>
<bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.json.JSONProvider">
<property name="serializeAsArray" value="true"/>
<property name="dropRootElement" value="true"/>
<property name="supportUnwrapped" value="true"/>
</bean>
<jaxrs:server id="custom1Service" address="/rest1">
<jaxrs:serviceBeans>
<ref component-id="rest1ServiceImpl"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref component-id="jsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
Bundle 2:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
xmlns:cxf="http://cxf.apache.org/blueprint/core"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
">
<cxf:bus id="my-app-bus" bus="tutorial"></cxf:bus>
<bean id="rest2Service" class="com.dasannetworks.vn.rest2.impl.Rest2ServiceImpl" />
<jaxrs:server id="custom2Service" address="/rest2">
<jaxrs:serviceBeans>
<ref component-id="rest2Service"/>
</jaxrs:serviceBeans>
After installing and run:
The outcome:
all rests request to "/cxf/rest1/" will run into authInterceptor whereas all rests request to "cxf/rest2" are not.
Could anyone give me some advice about how to share the same cxf:bus on both bundles ?
Thank you in advance.
Since I cannot solve this problem with blueprint, I changed the way to fix it.
Instead of blueprint, I initiated CXF Bus Rest Server with Activator.
Bundle 1 Activator:
In bundle 1, I get the default bus and add authentication interceptor on it then register a Rest Server endpoint on it.
public void start(BundleContext bundleContext) throws Exception {
Bus defaultBus = BusFactory.getDefaultBus();
defaultBus.setId("my-app-bus");
BusFactory.clearDefaultBusForAnyThread(defaultBus);
System.out.println(this.getClass().getName());
System.out.println(defaultBus.getId());
defaultBus.getInInterceptors().clear();
defaultBus.getInInterceptors().add(new AuthInterceptorImpl());
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setBus(defaultBus);
sf.setAddress("/tutorial");
sf.setServiceClass(HelloRestServiceImpl.class);
sf.create();
}
In bundle 2,
Bundle 2 Activator
I get the default bus, register and set that bus for Rest Server.
#Override
public void start(BundleContext bundleContext) throws Exception {
Bus defaultBus = BusFactory.getDefaultBus();
List<Interceptor<? extends Message>> inInterceptors = defaultBus.getInInterceptors();
for(Interceptor interceptor: inInterceptors) {
System.out.println( interceptor.getClass().getName());
}
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setBus(defaultBus);
sf.setAddress("/Rest2");
sf.setServiceClass(Rest2ServiceImpl.class);
sf.create();
}
==> The result : both bundles are now use the same bus, and bundle 2 can run into authentication interceptor which I registered on bundle 1 also. !!!
I'm trying to expose a JAX-WS Webservice (an annotated Java class) using Camel. When using a single parameter the Web service replies correctly. On the other hand when using as parameter an Object or multiple parameter it does not work.
Here is the blueprint I have deployed on JBoss Fuse:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:camelcxf="http://camel.apache.org/schema/blueprint/cxf" xmlns:cxf="http://cxf.apache.org/blueprint/core" 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 http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<camelcxf:cxfEndpoint id="demo-target-cxf" address="http://localhost:9000/SourceExample/hello" serviceClass="com.sample.SourceExampleWSImpl" endpointName="SourceExamplePort" serviceName="SourceExampleService" />
<camelContext xmlns="http://camel.apache.org/schema/blueprint" id="fuse-demo-route-exmple-cxf">
<route id="demo-target-cxf">
<from uri="cxf:bean:demo-target-cxf" />
<transform>
<simple>${in.body}</simple>
</transform>
<log message="Message input: ${in.body}" />
<removeHeaders pattern="CamelHttp*" />
</route>
</camelContext>
</blueprint>
Here is the Web Service implementation class:
#WebService
public class SourceExampleWSImpl {
#WebMethod
public int getTotal(int x, int y) {
return x+y;
}
}
The bundle ic correctly deployed on JBoss Fuse. When invoking the Web service, only the first parameter is evaluated. So for example, invoking with arguments 1 and 4:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sam="http://sample.com/">
<soapenv:Header/>
<soapenv:Body>
<sam:getTotal>
<arg0>1</arg0>
<arg1>4</arg1>
</sam:getTotal>
</soapenv:Body>
</soapenv:Envelope>
returns:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:getTotalResponse xmlns:ns2="http://sample.com/">
<return>1</return>
</ns2:getTotalResponse>
</soap:Body>
</soap:Envelope>
Any idea how to fix it ?
Thanks
Do you mean the expected output should be
1 + 4 = 5 because the following code should be called?
public int getTotal(int x, int y) {
return x+y;
}
If so that does not happen, when you use camel-cxf as a bean then the bean only defines the contract, the code in the implementation is not in use.
If you just want a standard SOAP-WS and write java code that builds and process the SOAP requests/response then just use plain CXF.
I am Ashish from Mumbai and very new to Apache Camel.
Currently I am building a route in XML which will scan the SOAP request and will redirect the request to appropriate URI.
My Soap request isn as follows:
<service xmlns="http://ws.madcomum.comprova.com">
<request>
<keysValues>
<item>
<bytesValue
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<dateValue
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<doubleValue
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<key>validatesOriginIntegrity</key>
<longValue
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<stringValue>z4x/FOOR+EPQ0vD9+itPSCBeNR4=</stringValue>
</item>
</keysValues>
<actionId>1</actionId>
<clientId>ARGO</clientId>
</request>
</service>
From this SOAP envelope, I want to parse out value of actionId tag using Camel Route.
If actionId has value of 1 then route must be redirected to callService else to another service.
I developed logic of route as folows:
<route>
<from uri="cxf:bean:comprovaWS?dataFormat=MESSAGE" />
<when>
<xpath>//actionId=1</xpath>
<to uri="log:input" />
<to ref="callService" />
<to uri="log:output" />
</when>
<otherwise>
<to uri="log:input" />
<to ref="otherService"/>
<to uri="log:output" />
</otherwise>
</choice>
</route>
But this logic is not working.
Is there any error in my route?
Though I am Java guy, I don't want to use Java here. I want to rely on Camel itself.
Please help me ASAP.
Regards,
Ashish
When you use xpath then 95% of the times when people have trouble its often due to namespaces. Your SOAP message is defined using a namespace - "http://ws.madcomum.comprova.com". The xpath expression must use this namespace to make it work.
See more details at: http://camel.apache.org/xpath, there is an example at the section Using XML configuration
Also as you use CXF in MESSAGE mode, then read about stream caching as the message is stream based: http://camel.apache.org/stream-caching.html