Setting up Mock Endpoints in Apache Camel with log:* - unit-testing

I have several routes that end with a log uri such as
<route>
<from uri="someUri" />
<to uri="someProcessor" />
<to uri="log:SOME_LOG?level=INFO" />
</route>
I am using CamelSpringJUnit4ClassRunner to run my unit tests.
I want to be able to mock my log endpoints as MockEndpoint objects. I have tried to use
#MockEndpoints("log:*")
along with
end = MockEndpoint.resolve(camelContext, "log:SOME_LOG?level=INFO");
but that generates a ClassCastException cannot cast InterceptSendToEndpoint to MockEndpoint.
and also tried
#EndpointInject(uri="log:SOME_LOG?level=INFO")
MockEndpoint end;
but that also generates an IllegalArgumentException.
Invalid type: org.apache.camel.component.mock.MockEndpoint which cannot be
injected via #EndpointInject/#Produce for: Endpoint[log:SOME_LOG?level=INFO]
A workaround I've found is by prepending my log uri with "mock:" and using
#EndpointInject(uri="mock:log:SOME_LOG?level=INFO) and defining my route in xml with
<route>
<from uri="someUri" />
<to uri="someProcessor" />
<to uri="mock:log:SOME_LOG?level=INFO" />
</route>
However I would like to get this to work by mocking my log: uris and not having to modify my route definitions in camel.xml.
Is there something that I'm missing?

When you use #MockEndpoints("log:*"), the camel just create the mock endpoint for you, the mock endpoint uri should be mock:log:THE_REMAINED. You should be able to get the mock endpoint with below code:
end = MockEndpoint.resolve(camelContext, "mock:log:SOME_LOG?level=INFO");

Related

Missing SOAPAction header when invoking WS with Camel-CXF

We are trying to a invoke Soap service using Camel-Cxf/Fuse and using Payload dataformat. Some times client is rejecting request saying SOAPAction is missing and this is intermittent. Is there a way for us to set SOAPAction specifically during service invocation? In what cases we fail to send SOAPAction? Here is the configuration we are using for invocation.
<!-- CXF configuration pointing to WSDL URL and service Name -->
<cxf:cxfEndpoint id="abcSOAPCPOutbound"
wsdlURL="wsdl/FooService.wsdl"
endpointName="cNS:FooServiceSoap"
serviceName="cNS:FooService"
address="http://example.com/processRequest.asmx"
xmlns:cNS="http://www.example.com"
loggingFeatureEnabled="false">
<cxf:inInterceptors>
<ref bean="GZIPInInterceptor"/>
</cxf:inInterceptors>
<cxf:outInterceptors>
<ref bean="iuABCSOAPOutboundInterceptor"/>
</cxf:outInterceptors>
</cxf:cxfEndpoint>
<!-- Came route for invoking service with operationName header set -->
<route id="iuFooOutboundRoute">
<from uri="direct-vm:iuOutboundtoFoo"/>
<setHeader headerName="operationName" >
<constant>FooSync</constant>
</setHeader>
<convertBodyTo type="String"/>
<!-- Send to Colibrium -->
<to uri="cxf:bean:abcSOAPCPOutbound?dataFormat=PAYLOAD"/>
<process ref="extractHTTPStatusCode"/>
</route>
Does it cause any problem if we set camel header as SOAPAction before invoking service?
Yes,
The same way as you do operationName:
<setHeader headerName="SOAPAction">
<constant>DummyOperation</constant>
</setHeader>
You can refer here - http://www.javaworld.com/article/2078883/open-source-tools/java-tip-write-an-soa-integration-layer-with-apache-camel.html?page=4

Mule invoking database connector from cxf soap service to call multple stored procedure in each method

Can you please help me and provide any example or scenario in which I can invoke db call using flow from web service operation. if my web service implementation have five operations and each operation has to call a separate query or stored procedure.
I have the other way around by injecting database template using spring injection and call the required query or stored procedure but I want to do it with flows.
Take a look at CXF proxy service:https://docs.mulesoft.com/mule-user-guide/v/3.7/proxying-web-services-with-cxf
It allows to access the raw SOAP message and route it how you wish, such as using a choice router using Xpath on the operation name, or you could extract the SOAPAction header etc.
<flow name="soap-api" doc:name="soap-api-orders">
<https:.... />
<cxf:proxy-service payload="body"
service="MyService-v1c" namespace="http://xmlns.oracle.com/MyService"
wsdlLocation="wsdl/MyService.wsdl" enableMuleSoapHeaders="false"
doc:name="CXF" />
<choice doc:name="Choice">
<when
expression="#[xpath('boolean(//mynamespace:MyOperation1/node()[1])')]">
<flow-ref name="flow1" />
</when>
<when
expression="#[xpath('boolean(//mynamespace:MyOperation2/node()[1])')]">
<flow-ref name="flow2" />
</when>
<otherwise>
</otherwise>
</choice>
</flow>

WCF 4 routing service throws handler error

I am trying to use WCF 4 routing declaratively to redirect one branch of my (REST) web services to an alternate server. I configured WCF's System.ServiceModel.Routing.RoutingService to route http://oldserver:81/FileService/ calls to http://newserver:82/FileService/, but when I try to access the redirected service, all it does is throw the error
Handler "HttpLogging" has a bad module "HttpLoggingModule" in its module list
I can enter URLs to the new service in my browser and they work fine, but URLs to the old service (to be re-routed) fail.
I have added the following routing configuration into my web service application:
<configuration>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<behaviors>
<serviceBehaviors>
<behavior name="routingConfig">
<!-- Specify the routing table to use. -->
<routing filterTableName="routingTable1" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<!-- WCF routing table -->
<routing>
<filters>
<filter name="FileFilter1" filterType="EndpointName" filterData="FileService"/>
</filters>
<filterTables>
<filterTable name="routingTable1">
<add filterName="FileFilter1" endpointName="FileService" />
</filterTable>
</filterTables>
</routing>
<client>
<!-- Destination endpoint defining the base URL where File messages will be routed. -->
<endpoint name="FileService"
address="http://newserver:82/FileService/"
binding="webHttpBinding"
contract="*" />
</client>
<services>
<!-- WCF routing service. -->
<service name="System.ServiceModel.Routing.RoutingService" behaviorConfiguration="routingConfig" >
<host>
<baseAddresses>
<!-- The service endpoint to be redirected. -->
<add baseAddress="http://oldserver:81/FileService" />
</baseAddresses>
</host>
<!-- Define the endpoints of the service to receive messages. -->
<endpoint name="reqReplyEndpoint" binding="webHttpBinding" contract="System.ServiceModel.Routing.IRequestReplyRouter" address="" />
</service>
</services>
There is no longer a FileService service in the application, except the one that should be exposed by the routing service.
I've tried:
filter types of MatchAll, EndpointAddress, and PrefixEndpointAddress;
various forms of the old service addresses;
different names for filters, routing tables, services;
renaming contracts.
None of it gets my client to call the redirected service, much less even any indication that the routing service is operational or even configured at all.
How do I make the routing actually work? Failing that, how would I debug it so I can determine what to fix?
The general problem I see is that you are trying to route REST calls with Routing Service, which is not supported. MSDN reference:
https://msdn.microsoft.com/en-us/library/ee517423.aspx
The Routing Service does not currently support routing of WCF REST
services. To route REST calls, consider using System.Web.Routing or
Application Request Routing
(http://go.microsoft.com/fwlink/?LinkId=164589).
Blockquote

Unmarshal a REST response without using #XMLRootElement annotation

Ok, I've searched everywhere for an answer to this. It is driving me nuts.
All I need to do is unmarshal a very simple webservice response. The only problem is, I am using a generated source file without the #XmlRootElement annotation. I am unable to edit this generated source file to add #XmlRootElement, either. I need to use it "as is".
This is the current code that I have, but it is resulting in an error shown at the bottom of this post. I have tried to use a JAXBElement wrapper but to no avail. Could somebody please give me the code I need? I have no idea how to use "QName"s etc.
This code below works great with classes that have #XmlRootElement:
MyGeneratedClass response = restTemplate.getForObject("url to webservice!"),
MyGeneratedClass.class);
return response
Sadly, it is producing this error in this case. Please help me to unmarshal the REST response!
Could not extract response: no suitable HttpMessageConverter found for response
type [MyGeneratedClass] and content type [application/xml;version=1]
I forgot about posting this many months ago and I should probably follow it up with the solution.
This solution also adds a cookie to the request headers, but you can ignore that.
In the case that a generated source file does not have #XmlRootElement annotation, you can unmarshal as follows:
// Cookie setting
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("Cookie", "myCookie=value");
HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);
HttpEntity<String> response = restTemplate.exchange("web service url"),
HttpMethod.GET, requestEntity, String.class);
// Unmarshalling
JAXBElement<MyGeneratedClass> result =
(JAXBElement<MyGeneratedClass>) unmarshaller.unmarshal(
new StreamSource(new ByteArrayInputStream(response.getBody().getBytes())));
return result.getValue();
Spring's RestTemplate relies on HttpMessageConverter to unmarshal an object to XML. More specifically the Jaxb2RootElementHttpMessageConverter.canWrite method is responsible for the error you are seeing. Even if you were to override the canWrite method to not care whether the XmlRootElement annotation was present, JAXB would be unable to unmarshal the object.
One way around this limitation is to override Jaxb2RootElementHttpMessageConverter.canWrite to not check for the presence of the XmlRootElement annotation AND use EclipseLink's Moxy JAXB implementation with a mapping file. In the mapping file you can specify the equivalent of the XmlRootElement annotation, allowing you to use JAXB without using annotation's in your Java class.
Spring's RestTemplate is typically used together with org.springframework.oxm.jaxb.Jaxb2Marshaller. Unfortunately, that class has a property supportJaxbElementClass set to false by default :(
Spring nowhere documents this property, and numerous questions about RestTemplate/ JAXBELement on the Spring Forums have been unanswered :((((
Fortunately, you can configure Jaxb2Marshaller setting its property supportJaxbElementClass to true!
The following example configuration of RestTemplate will correctly marshall and unmarshall objects of type JAXBElement
<beans>
<bean id="httpClient" class="org.apache.http.impl.client.DefaultHttpClient">
<constructor-arg>
<bean class="org.apache.http.impl.conn.PoolingClientConnectionManager" />
</constructor-arg>
</bean>
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg>
<bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<constructor-arg ref="httpClient" />
</bean>
</constructor-arg>
<!-- Configure the Rest template to translate between XML and JAXB -->
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<property name="marshaller" ref="jaxbMarshaller" />
<property name="unmarshaller" ref="jaxbMarshaller" />
</bean>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
</list>
</property>
</bean>
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="supportJaxbElementClass" value = "true"/>
<property name="packagesToScan">
<list>
<value>com.myorg.path.to.JAXB.classes</value>
</list>
</property>
</bean>
</beans>

copy complexType to message in BPEL

I am using Apache ODE to write some simple BPEL's to connect 2 web services.
One of the WSDL files of my two services contains this complex type:
<types>
<t:schema targetNamespace="http://ws.panos.com/" version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<t:complexType name="myObject">
<t:sequence>
<t:element minOccurs="0" name="str" type="t:string" />
</t:sequence>
</t:complexType>
</t:schema>
How do I make a copy from a service return message (which is just a xsd:string) to the input of a message (inside "str" of type "myObject"?
I have tried to do this, but doesnt seem to work:
<assign name="assign_2">
<copy>
<from variable="wsA_output" part="return"/>
<to variable="wsC_input" part="arg0" query="/arg0/str"/>
</copy>
I always get a null string transfered. Help much appreciated.
The to-spec <to variable="..." part="..." query="..."/> is not valid in BPEL 1.1 nor BPEL 2.0. The correct equivalent expression is: <to>$wsC_input.arg0/arg0/str</to> or <to variable="wsC_input" part="arg0"><query>/arg0/str</query></to>. Please make also sure that you initialize the variable before assigning values to nested structures.
Just found the mistake. You are right, we need to query in order to find the field like this:
<assign name="assign_2">
<copy>
<from variable="wsA_output" part="return"/>
<to>$wsC_input.message/arg0/str</to>
</copy>
</assign>
Also, we need to initialize the variable like this:
<assign name="assign_init">
<copy>
<from>
<literal><arg0><str xmlns="">nothing</str></arg0></literal>
</from>
<to variable="wsC_input" part="arg0"></to>
</copy>
</assign>
The xmlns="" is needed when the default namespace in your bpel is different that the namespace in the receiving web service.
I am just writing these down for future reference :)
Again, thanks for you your answer.
Some links that could also help other people:
http://ode.apache.org/faq.html
http://jee-bpel-soa.blogspot.com/2009/08/manipulating-ws-bpel-variables-and.html