How do I access SOAP headers in a spring soap endpoint? - java

Here is my SOAP request:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:str="http://app.strategyblocks.com/ws/schema/strategyblocks">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="...">
<wsse:Username>admin</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">secret</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<str:updateKpiRequest>
<str:company_id>1</str:company_id>
<str:kpi>
<str:external_id>1134511</str:external_id>
<str:title>title</str:title>
<str:description>description</str:description>
</str:kpi>
</str:updateKpiRequest>
</soapenv:Body>
</soapenv:Envelope>
Here is my Endpoint class:
#Endpoint
public class UpdateKpiEndpoint {
// The namespace of both request and response as declared in the XSD file
public static final String NAMESPACE_URI = "http://app.strategyblocks.com/ws/schema/strategyblocks";
// The local name of the expected request.
public static final String REQUEST_LOCAL_NAME = "updateKpiRequest";
#PayloadRoot(localPart = REQUEST_LOCAL_NAME, namespace = NAMESPACE_URI)
#ResponsePayload
public UpdateKpiResponse processUpdateKpi(#RequestPayload UpdateKpiRequest updateKpiRequest) {
try {
} catch (Exception e) {
UpdateKpiResponse response = new UpdateKpiResponse();
response.setCode("FAILURE");
response.setDescription("Problem with update kpi request");
return response;
}
UpdateKpiResponse response = new UpdateKpiResponse();
response.setCode("SUCCESS");
response.setDescription("Kpi has been updated");
return response;
}
}
At the moment I am passing a UsernameToken for authentication in the soap request, that is all working well and I have no problems with it what so ever. What I want to be able to achieve is to retrieve that username from the header in the body of processUpdateKpi method in my endpoint class, so that I can use it to find existing data for that user, I have tried to find examples of it being done and so far I have been unsuccessful, is it possible to do it? I have thought about also passing the username in the SOAP body as well, but I want to avoid it.

someone in the spring forums had a clear explanation on how to read the header from the endpoint class:
http://forum.springsource.org/showthread.php?109560-Unable-to-read-SoapHeader-in-Endpoint-class

Related

Make response part of body instead of header in SOAP response

I have requirements where I have to add response details in Body tag instead of Header. For now details are added in Header tag of soap response.
#XmlType
public class CheckBalanceResponse {
private String checkBalanceResult;
#XmlElement(name="CheckBalanceResult")
public String getCheckBalanceResult() {
return checkBalanceResult;
}
public void setCheckBalanceResult(String checkBalanceResult) {
this.checkBalanceResult = checkBalanceResult;
}
}
Generated response is below:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<CheckBalanceResponse xmlns="http://charginggw.org/">
<CheckBalanceResult>Incorrect PIN</CheckBalanceResult>
</CheckBalanceResponse>
</soap:Header>
<soap:Body/>
</soap:Envelope>
I want CheckBalanceResponse tag to be in Body instead of Header. Please suggest what should be done?

SOAP Request data is not going to External System in SpringBoot

I am trying to send request data to external soap server but data is going to null in the request to External Soap Server.
Please find the code as below:
UserListResponse response = null;
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "UserList")
#ResponsePayload
public UserListResponse UserListRequest(#RequestPayload UserListRequest request) throws Exception {
System.out.println("Enters into UserList()");
try {
//Client call
UserServicesLocator locator = new UserServicesLocator();
UserServicesSoapStub stub = (UserServicesSoapStub) locator.getUserServicesSoap();
response = stub.userList(request);//here the request data values not mapping at external system side
} catch(Exception e) {
e.printStackTrace();
}
return response;
}
SOAP UI Request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:prim="http://*****/UserServices">
<soapenv:Header/>
<soapenv:Body>
<prim:UserList>
<!--Optional:-->
<prim:XMLRequest>
<!--Optional:-->
<prim:Header>
<!--Optional:-->
<prim:MessageID>1</prim:MessageID>
<!--Optional:-->
<prim:CorrelationID>1</prim:CorrelationID>
<!--Optional:-->
<prim:SystemID>C</prim:SystemID>
<!--Optional:-->
<prim:RequestorID>1</prim:RequestorID>
</prim:Header>
<prim:Reference>Account</prim:Reference>
<!--Optional:-->
<prim:Number>100987600</prim:Number>
</prim:XMLRequest>
</prim:UserList>
</soapenv:Body>
</soapenv:Envelope>
The request is hitting the External Soap server but Soap server getting the all values (both Header & Body data)in the request as null.
I am unable to get why the values are going to null even i am passing the values from SOAP UI.
I am not getting even i am doing anything wrong here.Can anyone please help on this.

Header Values are coming as null in Apache camel Exchange

Below are my web-service request, Route and Request-Validator,
Web-service request:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<stlh:SabreHeader xmlns:stlh="http://services.sabre.com/STL_Header/v02_01">
<stlh:Service version="1.0.0">GetHotelMediaRQ</stlh:Service>
<stlh:Identification>
<stlh:CustomerID>CID12345</stlh:CustomerID>
<stlh:CustomerAppID>AppTest</stlh:CustomerAppID>
<stlh:ConversationID>05EFPElI2A4KudU75863JIxqAhQJtAx0</stlh:ConversationID>
<stlh:MessageID>4DTTQaHGSifFUtmSoMHAiq</stlh:MessageID>
<stlh:TimeStamp>2014-11-07T14:45:42.725-06:00</stlh:TimeStamp>
</stlh:Identification>
</stlh:SabreHeader>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" wsu:Id="athId">${athId}</wsse:BinarySecurityToken>
</wsse:Security>
</soap:Header>
<soap:Body>
<GetHotelMediaRQ xmlns="http://services.sabre.com/hotel/media/v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0.0" xsi:schemaLocation="http://services.sabre.com/hotel/media/v1 GetHotelMediaRQ.xsd">
<HotelRefs>
<HotelRef HotelCode="184769" CodeContext="Sabre">
<ImageRef MaxImages="1">
<Images>
<Image Type="ORI"/>
</Images>
<AdditionalInfo>
<Info Type="CAPTION">true</Info>
</AdditionalInfo>
<Languages>
<Language Code="EN"/>
</Languages>
</ImageRef>
</HotelRef>
</HotelRefs>
</GetHotelMediaRQ>
</soap:Body>
</soap:Envelope>
RequestValidator:
public void validate(GetHotelMediaRQ request, Exchange exchange) throws Exception {
TransactionContext context = BusExtensions.getTransactionContext(exchange);
Collection<HotelRef> hotelRefList = getInstance().convert(request, Collection.class);
Set<Property> properties = new HashSet<>();
String customerAppId = exchange.getIn().getHeader("customerAppID", String.class);
String customerId = exchange.getIn().getHeader("customerID", String.class);
But customerAppId(AppTest) and CustomerId(CI12345) is coming as null when I try to access via Exchange object.
"Custom" Soap headers are not copied to camel header . you have to manually add soap header into camel exchange header .
Approach 1 )
CamelCxfMessage - you can extract/process custom soap header camel cxf message which is present in camel exchange header
in camel -
SoapMessage soapMessage = (SoapMessage)exchange.getIn().getHeader("CamelCxfMessage");
this will give you soap message and its soapMessage.getExchange and try to get soap headers from soap message and process it .
Approach 2)
Camel Cxf Binding -you can use camel cxf binding feature in endpoint definition like cxfBinding=#bindingName .
Create a class and extend with org.apache.camel.component.cxf.DefaultCxfBinding and bean name should be bindingName .
it has one method which you have to overwrite - propagateHeadersFromCxfToCamel(camelmessage ,cxfmessage ,exchage ).
Here get your soap header and put it in camel header with identifier and access header in camel exchange header in processor or routes with same identifier.
Set logging for org.apache.camel to DEBUG and the header values will be logged, and you can determine if the component is dropping them or not.
Also, it looks like you might be using the cxf soap endpoint. Look into the [Description of relayHeaders option] section of the docs here:
http://camel.apache.org/cxf.html
i had to extract header information but got null in the object at the first attempt. then after a while i could fish it out. here is how (in a processor):
#Override
public void process(Exchange exc) throws Exception {
#SuppressWarnings("unchecked")
List<SoapHeader> headers = exc.getIn().getHeader(Header.HEADER_LIST, List.class);
for (int i=0; i < headers.size(); i++) {
if (headers.get(i).getObject() instanceof ElementNSImpl) {
ElementNSImpl elementNSImpl = (ElementNSImpl) headers.get(i).getObject();
Node firstChild = elementNSImpl.getFirstChild();
log.trace("header: name=" + elementNSImpl.getLocalName() + ", value=" + firstChild.getNodeValue());
}
}

Spring WS: Add custom SOAP header

What's my goal?
I'm rather new to Spring WS, I got a WSDL (and along some XSDs, ofcourse) and i want to add some custom header elements to the SOAP response.
I've been searching the web, tried various code pieces, but it's all without any luck... nothing seems to work properly .
What's the problem?
The response SOAP message has a body what spring calls a Payload and my SOAP client (SOAPUI) receives the response rather well.
But here it comes: how should I add new (custom) SOAP headers to the response message?
What's the response xml expected?
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<aud:HeaderInfo xmlns:bd="http://www.myws.com/">
<bd:ID>123</bd:ID>
<bd:Type>text</bd:Type>
</aud:HeaderInfo>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ne:myWS xmlns:ne="http://www.iways.com/">
<ne:INFO>
<ne:NAME>JOHN</ne:NAME>
<ne:DESIGNATION>ITA</ne:DESIGNATION>
<ne:MOBILE>9841011113</ne:MOBILE>
</ne:INFO>
</ne:myWS>
My payload
#PayloadRoot(localPart = "myWSRequest", namespace = TARGET_NAMESPACE)
public #ResponsePayload myWSResponse getInfo(#RequestPayload myWSRequest request)
{
myWSResponse response = new myWSResponse();
Person person = personService_i.getAccountDetails(request.getID());
response.setPersonDetails(person);
return response;
}
Any side info?
i use xsd which generates a load of classes based upon the XSDs I don't know how to add those custom headers to the response message,
You could implement a endpointInterceptorAdapter and do the following:
public final class MyEndpointInterceptorAdapter extends EndpointInterceptorAdapter {
#Override
public boolean handleResponse(MessageContext messageContext_, Object endpoint_)
throws IOException {
WebServiceMessage _webServiceMessage = messageContext_.getResponse();
SoapMessage _soapMessage = (SoapMessage) _webServiceMessage;
if (_soapMessage != null) {
SoapEnvelope _soapEnvelope = _soapMessage.getEnvelope();
// create your qname object
QName _myQName = ....
// adding your quname to the header
_soapEnvelope.getHeader().addHeaderElement(myQName );
}
}
}
and in your spring configuration file, just add the interceptor:
<sws:interceptors>
<ref bean="myEndpointInterceptorAdapter"/>
</sws:interceptors>

Spring WS Endpoint extract SOAP info

After reading doc on the Spring web site, still confused about how to extract information from a SOAP request.
For example, the SOAP request sent to server is like:
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:user="http://www.mysite.com/user/schemas">
<soapenv:Header/>
<soapenv:Body>
<user:UserRequest>
<!--You may enter the following 4 items in any order-->
<user:Key>key</user:Key>
<user:UserName>username</user:UserName>
<user:RequesterName>reqname</user:RequesterName>
<user:RequesterPassword>repw</user:RequesterPassword>
</user:UserRequest>
</soapenv:Body>
</soapenv:Envelope>
On my server side I create an Endpoint like:
#Endpoint
public class UserEndpoint {
private static final String NAMESPACE_URI = "http://www.mysite.com/user/schemas";
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "UserRequest")
public void handleGetUserRequest() {
//Extract here...
}
}
How should I write extraction code here?
I would suggest having a look at the Spring WS samples for code ideas, depending on what else you are using in your application. For example: the HolidayEndpoint source code.
#Endpoint("myEndpoint")
public class MyEndpoint {
/**
* Spring-WS Endpoint
* #param submitSomethingRequest
* #param header
* #return SubmitSomethingResponse
*/
#PayloadRoot(namespace="http://my.namespace.org/spec/1.0.1", localPart="submitSomethingRequest")
#ResponsePayload
public SubmitSomethingResponse submitSomethingRequest(#RequestPayload SubmitSomethingRequest submitSomethingRequest, **SoapHeader header**) {
LOG.info("Received SOAP HEADER: " + header);
if(header != null) {
Iterator<SoapHeaderElement> hdrs = header.examineAllHeaderElements();
while(hdrs.hasNext()) {
SoapHeaderElement hdrEle = hdrs.next();
System.out.prinltn(hdrEle.getName().getPrefix() + ":" + hdrEle.getName().getLocalPart());
... //Do something here to parse DOM and extract headers you care about
}
}
...

Categories

Resources