In the previous post we saw CXF endpoints could set a soap header in the response. But what if the server needs to process a soap header ? The CXF website recommends using interceptors for reading headers. As I
still do not have a very clear idea about the concept I decided to look
for a different solution.
Accordingly I modified my service:
The definition for the proxy is of the form:
The response generated by the server also includes the header in response:
Accordingly I modified my service:
public GetRandomResponse random(final GetRandomRequest getRandomRequest) { LOG.info("Executing operation random"); System.out.println(getRandomRequest); try { this.verifyHeaderPresent(); final GetRandomResponse _return = new GetRandomResponse(); _return.setValue((int) (Math.random() * 165)); this.addNameHeader(); return _return; } catch (final java.lang.Exception ex) { ex.printStackTrace(); throw new RuntimeException(ex); } } private void verifyHeaderPresent() throws JAXBException { final MessageContext messageContext = this.wsContext.getMessageContext(); final List<Header> headers = (List<Header>) messageContext.get(Header.HEADER_LIST); for (final Header header : headers) { final QName headerQName = header.getName(); if (HEADER_QNAME.equals(headerQName)) { final Object object = header.getObject(); if (object instanceof Node) { final RandomHeader rHeader = (RandomHeader) this.context.createUnmarshaller().unmarshal((Node) object); LOG.info("Header found with value : " + rHeader.getHostName()); } else { throw new WebServiceException("Host name header missing !!!"); } } } } private void addNameHeader() throws JAXBException { final RandomHeader rHeader = new RandomHeader(); rHeader.setHostName("WhoCares !!"); // will be specific to each thread/ request final MessageContext messageContext = this.wsContext.getMessageContext(); final List<Header> headers = new ArrayList<Header>(); headers.add(new Header(HEADER_QNAME, rHeader, new JAXBDataBinding(RandomHeader.class))); messageContext.put(Header.HEADER_LIST, headers); }The code is very similar to our write technique.
- It fetches the list of headers associated with the request.
- It then searches through the list looking for a match.
- The discovered headers value field is actually of type Node. (In this case it was of subtype Element).
- We need to convert marshal this to the Java object needed. as we are using JAXBBinding, the code uses JAXB's Unmarshaler class to convert the object.
private static final QName HEADER_QNAME = new QName("http://ws.com/Service/xsd/random-schema", "RandomHeader"); public static void main(final String[] args) throws JAXBException { final RandomHeader rHeader = new RandomHeader(); rHeader.setHostName("Trial call"); final List<Header> headers = new ArrayList<Header>(); headers.add(new Header(HEADER_QNAME, rHeader, new JAXBDataBinding(RandomHeader.class))); final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("client.xml"); final SampleServiceOperationsPortType client = (SampleServiceOperationsPortType) context.getBean("client"); ((BindingProvider) client).getRequestContext().put(Header.HEADER_LIST, headers); final GetRandomRequest getRandomRequest = new GetRandomRequest(); getRandomRequest.setName("Tom"); final GetRandomResponse getRandomResponse = client.random(getRandomRequest); System.out.println("Response: " + getRandomResponse.getValue()); }How did my client proxy get access to the headers?
The definition for the proxy is of the form:
<jaxws:client id="client" serviceClass="com.ws.service.samplews_ns.SampleServiceOperationsPortType" address="http://localhost:8080/WsdlFirst/services/randomService"> <!-- ... --> </jaxws:client>The cxf client thus created is of type JaxWsClientProxy. It implements the BindingProvider interface. The BindingProvider's getRequestContext returns a map to which we can add the request headers. On executing the same the request generated is:
ID: 1
Address: http://localhost:8080/WsdlFirst/services/randomService
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml
Headers: {Accept=[*/*], SOAPAction=["/Service/random"]}
Payload: <?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<RandomHeader xmlns="http://ws.com/Service/xsd/random-schema">
<hostName>Trial call</hostName>
</RandomHeader>
</soap:Header>
<soap:Body>
<ns1:GetRandomRequest xmlns:ns1="http://ws.com/Service/xsd/random-schema">
<ns1:name>Tom</ns1:name>
</ns1:GetRandomRequest>
</soap:Body>
</soap:Envelope>
As seen the header has been added to the soap message.The response generated by the server also includes the header in response:
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {Content-Length=[350], content-type=[text/xml;charset=UTF-8], Date=[Sun, 16 Jun 2013 04:59:08 GMT], Server=[Apache-Coyote/1.1]}
Payload: <?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<RandomHeader xmlns="http://ws.com/Service/xsd/random-schema">
<hostName>WhoCares !!</hostName>
</RandomHeader>
</soap:Header>
<soap:Body>
<GetRandomResponse xmlns="http://ws.com/Service/xsd/random-schema">
<value>159</value>
</GetRandomResponse>
</soap:Body>
</soap:Envelope>
No comments:
Post a Comment