Apache CXF JMS - SOAP - apache

I need to use the same SOAP request to be able to call the same implementation of a method but which is exposed by 2 different service endpoints:
Endpoint A - would be for synchronous access via SOAP
Endpoint B - would be for asynchronous access via JMS
Now what am seeing is that the SOAP request Message which works on the JMS and the SOAP webservice endpoint are structurally different.
I wanted to know whether with ApacheCXF it is possible to call the SOAP or JMS endpoints using the same SOAP request ?
In my case I was able to call both endpoints but the requests used is not the same for each
Below is an example of the SOAP message which works on Asynch Endpoint B but which does not work on Synch Endpoint A .. note that I've obtained the Asynch message by executing a Junit test and intercepted the generate message on ActiveMQ queue:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns1:create xmlns:ns1="http://service.ws.example/">
<CustomPartyModel>
<ns2:customerModel
xmlns:ns2="http://party.beans.commons.example">
<ns2:person>
<ns2:budgetPlanNumber>131484</ns2:budgetPlanNumber>
<ns2:clientSituationCode
xmlns:ns3="http://www.w3.org/2001/XMLSchema-instance" ns3:nil="true" />
<ns2:employeeReduction>J</ns2:employeeReduction>
<ns2:employeeNumber></ns2:employeeNumber>
<ns2:packageNumber>5</ns2:packageNumber>
<ns2:planIndicator xmlns:ns3="http://www.w3.org/2001/XMLSchema-instance"
ns3:nil="true" />
<ns2:privateRelationNumber
xmlns:ns3="http://www.w3.org/2001/XMLSchema-instance" ns3:nil="true" />
</ns2:person>
</ns2:customerModel>
</CustomPartyModel>
</ns1:create>
</soap:Body>
Here is the SOAP Request which works on Synchronous endpoint but not on the Asynch one .. this request was obtained from creating a request from the WSDL :
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.ws.example/" xmlns:par="http://party.beans.commons.example">
<soapenv:Body>
<ser:CustomPartyModel>
<par:customerModel>
<par:person>
<par:budgetPlanNumber>131484</par:budgetPlanNumber>
<par:employeeReduction>J</par:employeeReduction>
<par:employeeNumber></par:employeeNumber>
<par:packageNumber>5</par:packageNumber>
<par:professionCodePartner></par:professionCodePartner>
<par:professionDescriptionPartner></par:professionDescriptionPartner>
</par:person>
</par:customerModel>
</ser:CustomPartyModel>
In both cases am using Aegis for data binding , I did try JAXB as well but with no futher success.
Given that its the same method with same method signature you would expect that the same request could be used in both asynch and synch but this does not seem to be the case .
Anybody has had similar issues or could possibly shed some light in regards to this ?
Note that am using the following dependencies:
cxf-api-2.2.2.jar ,
cxf-common-utilities-2.2.2.jar,
cxf-rt-databinding-aegis-2.2.2.jar,
XmlSchema-1.4.5.jar,
cxf-rt-transports-jms-2.2.2.jar,
spring-jms-2.5.5.jar,
acegi-security-1.0.7.jar

Ok I found the solution basically to be able to send Request through JMS and Synchronous SOAP as Document Literal the following is required to be defined on the interface
#WebService
#SOAPBinding(style=Style.DOCUMENT, use=Use.LITERAL,parameterStyle=ParameterStyle.BARE)
public interface ExampleAsyncService {
Without the Document / Literal / Bare configuration JMS will have a tendancy of sending RPC wrapped style request .

Related

Unable to Pull Message off Queue

Let me explain my configuration:
ActiveMQ 5.12.0
AnyPoint Studio 5.2.1
Mule 3.6.1
Flow of application:
I am using FunctionalTestCase to post and retrieve a message from queue.
MuleClient client = muleContext.getClient();
String productAsJson = "{\"name\":\"Widget\", \"price\":9.99, \"weight\":1.0, \"sku\":\"abcd-12345\"}";
client.dispatch("http://localhost:8081/products", productAsJson, null);
MuleMessage result = client.request("jms://products", RECEIVE_TIMEOUT);
What is happening is the message is getting posted but when I try to retrieve it, I get the string "{NullPayLoad}".
After stepping back through the flow, I have discovered the message payload, when using the Mule Client, is not making the queue. While looking through the admin console for ActiveMQ, I discovered the message details is "{NullPayload}". When I check using the Advance Risk Client, the JSON message is getting posted correctly.
Any suggestions would be greatly appreciated.
Russ
It's NullPayload when using the MuleClient because by default the http operation will be GET and wont be expecting a body to parse.
The MuleClient is more suited to working with Mule transport infrastructure such as the JMS transport or the old http transport. I don't think it plays nice with the new http listener module.
Normally with the transports you can set the method via a property but that doesnt seem to work with the http:listener:
MuleMessage message = getTestMuleMessage();
message.setPayload(productAsJson);
message.setProperty("http.method", "POST", PropertyScope.INBOUND);
client.send("http://localhost:8089/products", message);
I would suggest using a standard HTTP client such as Apache HTTP client etc. and set the method to POST/PUT or whatever method you need to use that expects a body.

How to mock http connectors in munit

We are having our custom http connector and an outbound which refers to that connector as follows
<http:connector name="myConnector">
<!-- config -->
</http:connector>
<http:endpoint name="myEndpoint" ref="myConnector">
<!-- config -->
</http:endpoint>
<http:outbound-endpoint name="myOutbound" ref="myEndpoint">
When I am mocking http outbound without specifying any attributes then its mocking .But if I am using mock while specifying attributes then it is throwing exception saying
"cannot process event as myConnector has stopped working".
By default munit will stop the connector, and if you're seeing that message it means your not hitting the correct mocked endpoint. I would check that the attributes correctly match. Can you post your mock configuration and your endpoint configuration? So a better answer can be provided.
You can mock endpoints the same was as any message processor:
whenMessageProcessor("outbound-endpoint").ofNamespace("http").thenReturnSameEvent()
As a side note if you don't want the connector to be stopped by default you can override haveToMockMuleConnectors from FunctionalMunitSuite:
#Override
public boolean haveToMockMuleConnectors() {
return false;
}
But then you won't hit the mocked endpoint.

Spring Integration: How to send response packet to client in case of exception using error-channel?

I am using Spring Integration in my project.
Endpoints used in application are in-bound gateway, header based router, transformer, spliter, service activator.
In case of success flow(not any exception), in-bound gateway reply-channel getting desired response and client gets that response which is fine but in case of any exception, I want to send customized error response which is not working as per my requirement.
I am using error-channel to accomplish above requirement but not succeeding in that.
Please find my configuration of in-bound gateway, error channel etc.
I have not use any chain in configuration.
<int-http:inbound-gateway id="inboundGateway"
supported-methods="GET, POST" request-channel="requestChannel"
path="/services/tylv/{requestParam}" reply-channel="responseChannel"
error-channel="errorChannel">
</int-http:inbound-gateway>
<int:transformer ref="errorHandler"
input-channel="errorChannel" method="generateErrorResponse"
output-channel="responseChannel" />
<bean id="errorHandler"
class="com.csam.wsc.enabling.integration.transformer.ErrorHandler" />
In case of exception , com.csam.wsc.enabling.integration.transformer.ErrorHandler.generateErrorResponse(ErrorMessage) successfully called.This API handle exceptions, generate Error Response Packet but it is not being sent to client, just only HTTP Status Code 200 sent.
Ideally it should be sent because transformer's output-channel is reply-channel of inbound-gateway which is already sending response packet along with status code 200 in case of success (no any exception).
I think in case of error-channel , in-bound gateway reply-channel is not working, but I am not sure.
Please help me in configuring error-channel.
You should store the message's headers before the error reaches the error channel and then you should create a new message with the stored headers and route that new message to response channel.
MessageBuilder.fromMessage(errorResponseMessage).copyHeadersIfAbsent(storedHeaders).build();

SOAP statement for WCF Service

I asked about consuming a WCF service from RPG here and received this response: Scott Klement has a presentation and examples: http://www.scottklement.com/presentations/#HTTPAPI
I used SoapUI to test my service and also to get he soap statement to be used with HTTAPI. The service returnes data in SoapUI but I have been unsuccessful using it in the RPG program. SoapUI returns the following, but it seems only to work within SoapUI - it also doesn't include the path to my service which is
http://ServerName/COE/CustByNameList.svc
If I navigate to http://ServerName/COE/CustByNameList.svc?wdsl, I get the wsdl.
Statement returned in SoapUI:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Header/>
<soapenv:Body>
<tem:GetCustomerData>
<!--Optional:-->
<tem:CustomerNumber>1688</tem:CustomerNumber>
</tem:GetCustomerData>
</soapenv:Body>
</soapenv:Envelope>
The result looks like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><GetCustomerDataResponse xmlns="http://tempuri.org/"><GetCustomerDataResult xmlns:a="http://schemas.datacontract.org/2004/07/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><a:List xmlns:b="http://schemas.datacontract.org/2004/07/WebOrderEntry.Lists"><b:PartialCSTMS><b:ADR19A>3910 LAKEFIELD DR </b:ADR19A><b:ADR29A>JOHNS CREEK FACILITY </b:ADR29A><b:CITY9A>SUWANEE </b:CITY9A><b:CST_x0023_9A>1688</b:CST_x0023_9A><b:NAME9A>JOHNSON CONTROLS </b:NAME9A><b:PHON9A>770-495-9950 </b:PHON9A><b:STAT9A>GA</b:STAT9A><b:ZIPC9A>30024 </b:ZIPC9A></b:PartialCSTMS></a:List></GetCustomerDataResult></GetCustomerDataResponse></s:Body></s:Envelope>
I keep getting 500 internal server errors. I've tried numerous variations of the SOAP statement based on the examples I have seen, but they date back to 2008. Has anyone been successful with calling a WCF service from RPG?
I asked my Twitter network and #alexeivbaranov responded with the following:
Try to compare request & response from SoapUI and your RPG client using TcpMon. As I understand your SoapUI req works fine but RPG req gets 500, so problem in request. Compare them.
Check your headers. You may be missing the soap action. Here is an example of a request to a WCF service exposed using WsHttp binding with security enabled. wsa:Action is the thing you might need.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<soapenv:Envelope
xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"
xmlns:ns="http://somenamespace">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Action>http://someuri/Get</wsa:Action>
<wsa:To>http://localhost/someapp/SomeService.svc</wsa:To>
</soapenv:Header>
<soapenv:Body>
<ns:GetRequest>
<ns:Body>
<ns:Id>12345</ns:Id>
</ns:Body>
</ns:GetRequest>
</soapenv:Body>
</soapenv:Envelope>
I had to throw the towel in on using HTTPAPI to consume my WCF web service - just could not get past HTTP 400 and 500 errors. Logging wasn't helping. I believe I finally managed to get the SOAP call correct but then started receiving errors that seemed to translate into special character issues.
Instead, I ended up using IBM's IWS and got it working. These two links were of great help:
http://www.ibm.com/developerworks/ibmi/library/i-amrawsdl2rpg/index.html
http://www.iprodeveloper.com/article/rpg-programming/consume-web-services-with-ibms-iws-66209

Possible to send a POX request, but receive a SOAP response from a service?

I want to send something like:
<GetColors>
<Credentials username="test" password="test" />
<GetColors>
Once I receive the request, I want to read in the Credentials, verify it. If it is verified, I will send back a soap response. How can I do this?
With build in stuff you can't. You can turn off the SOAP processing by either using REST service or custom binding with MessageVersion.None and you must build valid SOAP response manually like any other XML document.