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