[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2447
  • Last Modified:

Axis2 - Handlers for SOAP headers

I have a service created using contract first approach in Axis2.

Now the client, needs to pass header information to this service with the user credentials. Only if the user is valid the service call should succeed. Otherwise a fault should be raised.
To add information to header (in the request), I have created the following handler-chain.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<javaee:handler-chains
     xmlns:javaee="http://java.sun.com/xml/ns/javaee"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <javaee:handler-chain>
    <javaee:handler>
      <javaee:handler-class>com.examples.www.wsdl.resumeservice_wsdl.ClientCredentialsHandler</javaee:handler-class>
    </javaee:handler>
  </javaee:handler-chain>
</javaee:handler-chains>

and the following handler on the client side

package com.examples.www.wsdl.resumeservice_wsdl;

import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPConstants;
import java.io.IOException;

public class ClientCredentialsHandler implements SOAPHandler<SOAPMessageContext> {

    public boolean handleMessage(SOAPMessageContext ctx) {
       Boolean request_p = (Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
       if (request_p) {
           try {
             SOAPMessage msg = ctx.getMessage();
             SOAPEnvelope env = msg.getSOAPPart().getEnvelope();
             SOAPHeader hdr = env.getHeader();
             if (hdr == null) hdr = env.addHeader();
             QName qname = new QName("http://localhost:8080/axis2/services/ResumeService", "ResumeService");
             SOAPHeaderElement helem = hdr.addHeaderElement(qname);
             helem.setActor(SOAPConstants.URI_SOAP_ACTOR_NEXT); // default
             helem.addTextNode("user1");
             helem.addTextNode("mypassword");
             msg.saveChanges();
             msg.writeTo(System.out);
          }
          catch(SOAPException e) { System.err.println(e); }
          catch(IOException e) { System.err.println(e); }
       }
        return true; // continue down the chain
    }
   
    public boolean handleFault(SOAPMessageContext ctx) {
     
       try {
          ctx.getMessage().writeTo(System.out);
       }
       catch(SOAPException e) { System.err.println(e); }
       catch(IOException e) { System.err.println(e); }
       return true;
    }
 
    public Set<QName> getHeaders() {
     
       return null;
    }    

    public void close(MessageContext messageContext) {
       
    }
}




but this header is not getting called. Seems it is not able to locate the handler-chain.xml

Can someone please let me know how to correct this.

Thank you       
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
	xmlns:tns="http://www.examples.com/wsdl/ResumeService.wsdl" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ResumeService"
	targetNamespace="http://www.examples.com/wsdl/ResumeService.wsdl">
	<wsdl:types>
		<xsd:schema targetNamespace="http://www.examples.com/wsdl/ResumeService.wsdl">
			<xsd:element name="getResumeId">
				<xsd:complexType>
					<xsd:sequence>
						<xsd:element name="firstName" type="xsd:string" />
						<xsd:element name="lastName" type="xsd:string"></xsd:element>
					</xsd:sequence>
				</xsd:complexType>
			</xsd:element>
			<xsd:element name="getResumeIdResponse">
				<xsd:complexType>
					<xsd:sequence>
						<xsd:element name="resumeId" type="xsd:string" />
					</xsd:sequence>
				</xsd:complexType>
			</xsd:element>
			<xsd:element name="getResumeDetails">
				<xsd:complexType>
					<xsd:sequence>
						<xsd:element name="resumeId" type="xsd:string"></xsd:element>
					</xsd:sequence>
				</xsd:complexType>
			</xsd:element>
			<xsd:element name="getResumeDetailsResponse">
				<xsd:complexType>
					<xsd:sequence>
						<xsd:element name="firstName" type="xsd:string"></xsd:element>
						<xsd:element name="lastName" type="xsd:string"></xsd:element>
						<xsd:element name="address" type="tns:addressType"></xsd:element>
					</xsd:sequence>
				</xsd:complexType>
			</xsd:element>

			<xsd:complexType name="addressType">
				<xsd:sequence>
					<xsd:element name="city" type="xsd:string" />
					<xsd:element name="state" type="xsd:string" />
					<xsd:element name="country" type="xsd:string" />
					<xsd:element name="mobile" type="xsd:string" />
					<xsd:element name="email" type="xsd:string" />
				</xsd:sequence>
			</xsd:complexType>

			<xsd:element name="getAllResumeIdsResponse">
				<xsd:complexType>
					<xsd:sequence>
						<xsd:element name="allResumeIds" type="xsd:string"
							maxOccurs="unbounded" />
					</xsd:sequence>
				</xsd:complexType>
			</xsd:element>

			<xsd:element name="updateResumeDetails">
				<xsd:complexType>
					<xsd:sequence>
						<xsd:element name="resumeId" type="xsd:string"></xsd:element>
					</xsd:sequence>
				</xsd:complexType>
			</xsd:element>
			<xsd:element name="updateResumeDetailsResponse">
				<xsd:complexType>
					<xsd:sequence>
						<xsd:element name="updateStatus" type="xsd:boolean"></xsd:element>
					</xsd:sequence>
				</xsd:complexType>
			</xsd:element>

			<xsd:element name="getResumeContent">
				<xsd:complexType>
					<xsd:sequence>
						<xsd:element name="resumeId" type="xsd:string">
						</xsd:element>
					</xsd:sequence>
				</xsd:complexType>
			</xsd:element>
			<xsd:element name="getResumeContentResponse">
				<xsd:complexType>
					<xsd:sequence>
						<xsd:element name="content" type="xsd:base64Binary">
						</xsd:element>
					</xsd:sequence>
				</xsd:complexType>
			</xsd:element>
			
			<xsd:element name="updateResumeContent">
				<xsd:complexType>
					<xsd:sequence>
						<xsd:element name="resumeId" type="xsd:string">
						</xsd:element>
					</xsd:sequence>
				</xsd:complexType>
			</xsd:element>
			<xsd:element name="updateResumeContentResponse">
				<xsd:complexType>
					<xsd:sequence>
						<xsd:element name="content" type="xsd:base64Binary">
						</xsd:element>
					</xsd:sequence>
				</xsd:complexType>
			</xsd:element>
		</xsd:schema>
	</wsdl:types>
	<wsdl:message name="getResumeIdRequest">
		<wsdl:part element="tns:getResumeId" name="parameters" />
	</wsdl:message>
	<wsdl:message name="getResumeIdResponse">
		<wsdl:part element="tns:getResumeIdResponse" name="parameters" />
	</wsdl:message>
	<wsdl:message name="getResumeDetailsRequest">
		<wsdl:part name="parameters" element="tns:getResumeDetails"></wsdl:part>
	</wsdl:message>
	<wsdl:message name="getResumeDetailsResponse">
		<wsdl:part name="parameters" element="tns:getResumeDetailsResponse"></wsdl:part>
	</wsdl:message>

	<wsdl:message name="getAllResumeIdsRequest" />
	<wsdl:message name="getAllResumeIdsResponse">
		<wsdl:part name="parameters" element="tns:getAllResumeIdsResponse"></wsdl:part>
	</wsdl:message>

	<wsdl:message name="updateResumeDetailsRequest">
		<wsdl:part name="parameters" element="tns:updateResumeDetails"></wsdl:part>
	</wsdl:message>
	<wsdl:message name="updateResumeDetailsResponse">
		<wsdl:part name="parameters" element="tns:updateResumeDetailsResponse"></wsdl:part>
	</wsdl:message>

	<wsdl:message name="getResumeContentRequest">
		<wsdl:part name="parameters" element="tns:getResumeContent"></wsdl:part>
	</wsdl:message>
	<wsdl:message name="getResumeContentResponse">
		<wsdl:part name="parameters" element="tns:getResumeContentResponse"></wsdl:part>
	</wsdl:message>
	
	<wsdl:message name="updateResumeContentRequest">
		<wsdl:part name="parameters" element="tns:updateResumeContent"></wsdl:part>
	</wsdl:message>
	<wsdl:message name="updateResumeContentResponse">
		<wsdl:part name="parameters" element="tns:updateResumeContentResponse"></wsdl:part>
	</wsdl:message>
	
	<wsdl:portType name="ResumeService">
		<wsdl:operation name="getResumeId">
			<wsdl:input message="tns:getResumeIdRequest" />
			<wsdl:output message="tns:getResumeIdResponse" />
		</wsdl:operation>
		<wsdl:operation name="getResumeDetails">
			<wsdl:input message="tns:getResumeDetailsRequest"></wsdl:input>
			<wsdl:output message="tns:getResumeDetailsResponse"></wsdl:output>
		</wsdl:operation>

		<wsdl:operation name="getAllResumeIds">
			<wsdl:input message="tns:getAllResumeIdsRequest"></wsdl:input>
			<wsdl:output message="tns:getAllResumeIdsResponse"></wsdl:output>
		</wsdl:operation>

		<wsdl:operation name="updateResumeDetails">
			<wsdl:input message="tns:updateResumeDetailsRequest"></wsdl:input>
			<wsdl:output message="tns:updateResumeDetailsResponse"></wsdl:output>
		</wsdl:operation>
		<wsdl:operation name="getResumeContent">
			<wsdl:input message="tns:getResumeContentRequest"></wsdl:input>
			<wsdl:output message="tns:getResumeContentResponse"></wsdl:output>
		</wsdl:operation>
		
		<wsdl:operation name="updateResumeContent">
			<wsdl:input message="tns:updateResumeContentRequest"></wsdl:input>
			<wsdl:output message="tns:updateResumeContentResponse"></wsdl:output>
		</wsdl:operation>
	</wsdl:portType>

	<wsdl:binding name="ResumeServiceSOAP" type="tns:ResumeService">

		<soap:binding style="document"
			transport="http://schemas.xmlsoap.org/soap/http" />
		<wsdl:operation name="getResumeId">

			<soap:operation
				soapAction="http://www.examples.com/wsdl/ResumeService.wsdl/getResumeId" />
			<wsdl:input>

				<soap:body use="literal" />
			</wsdl:input>
			<wsdl:output>

				<soap:body use="literal" />
			</wsdl:output>
		</wsdl:operation>
		<wsdl:operation name="getResumeDetails">

			<soap:operation
				soapAction="http://www.examples.com/wsdl/ResumeService.wsdl/getResumeDetails" />
			<wsdl:input>

				<soap:body use="literal" />
			</wsdl:input>
			<wsdl:output>

				<soap:body use="literal" />
			</wsdl:output>
		</wsdl:operation>

		<wsdl:operation name="getAllResumeIds">

			<soap:operation
				soapAction="http://www.examples.com/wsdl/ResumeService.wsdl/getAllResumeIds" />
			<wsdl:input>
				<soap:body use="literal" />
			</wsdl:input>
			<wsdl:output>

				<soap:body use="literal" />
			</wsdl:output>
		</wsdl:operation>
		<wsdl:operation name="updateResumeDetails">

			<soap:operation
				soapAction="http://www.examples.com/wsdl/ResumeService.wsdl/updateResumeDetails" />
			<wsdl:input>

				<soap:body use="literal" />
			</wsdl:input>
			<wsdl:output>

				<soap:body use="literal" />
			</wsdl:output>
		</wsdl:operation>
		<wsdl:operation name="getResumeContent">
			<soap:operation
				soapAction="http://www.examples.com/wsdl/ResumeService.wsdl/getResumeContent" />
			<wsdl:input>
				<soap:body use="literal" />
			</wsdl:input>
			<wsdl:output>
				<soap:body use="literal" />
			</wsdl:output>
		</wsdl:operation>
		<wsdl:operation name="updateResumeContent">
			<soap:operation
				soapAction="http://www.examples.com/wsdl/ResumeService.wsdl/updateResumeContent" />
			<wsdl:input>
				<soap:body use="literal" />
			</wsdl:input>
			<wsdl:output>
				<soap:body use="literal" />
			</wsdl:output>
		</wsdl:operation>
	</wsdl:binding>
	<wsdl:service name="ResumeService">
		<wsdl:port binding="tns:ResumeServiceSOAP" name="ResumeServiceSOAP">
			<soap:address location="http://www.example.org/" />
		</wsdl:port>
	</wsdl:service>
</wsdl:definitions>

Open in new window

0
ank9
Asked:
ank9
  • 6
  • 4
1 Solution
 
Siva Prasanna KumarPrincipal Solutions ArchitectCommented:
Don't user properitory headers for access control. use standard WS-Security username token.

Check:

http://wso2.org/library/3190

RAMPART is axis implementation of WS-Security.
0
 
ank9Author Commented:
Thank you.
Can you please let me know how to inject the token to the SOAP request from the client handler.
0
 
ank9Author Commented:
This article talks about deplying the service over HTTPS.
I have made all the changes but I can still access the WSDL using
http://localhost:8080/axis2/services/ResumeService?wsdl 
instead of
https://localhost:8080/axis2/services/ResumeService?wsdl 
 
0
[Webinar] Improve your customer journey

A positive customer journey is important in attracting and retaining business. To improve this experience, you can use Google Maps APIs to increase checkout conversions, boost user engagement, and optimize order fulfillment. Learn how in this webinar presented by Dito.

 
ank9Author Commented:
I removed the HTTPS setting. Would like to get it working without HTTP and then move to HTTPS.
I did the following in the handler
Can you please let me know if this is correct?
Also, where do I specify this handlers name? Will it be in services.xml or axis2.xml

ublic class ServiceCredentialsHandler extends AbstractHandler {

	public InvocationResponse invoke(MessageContext msgContext) throws AxisFault {
		HttpServletRequest obj =(HttpServletRequest)msgContext.getProperty("transport.http.servletRequest");
		System.out.println("Acceptable Encoding type: "+obj.getHeader("Accept-Encoding"));
		System.out.println("Acceptable character set: " +obj.getHeader("Accept-Charset"));
		System.out.println("Acceptable Media Type: "+obj.getHeader("Accept"));

	//Write the processing logic here
	return InvocationResponse.CONTINUE;
	}
	}

Open in new window

0
 
ank9Author Commented:
I have installed Rampart. But still when I send the SOAP request soapUI there are no headers in the request.
0
 
Siva Prasanna KumarPrincipal Solutions ArchitectCommented:
Oh sorry i was busy with My Bday. Ok you are getting confused between HTTP headers ans SOAP headers they are two different things, the above code which you have posted is useful only for HTTP headers, what exactly are u trying to achieve soap header or http header?
0
 
ank9Author Commented:
Oh..great... congratulations...Hope you had a great time.
I need to pass authentication information (username and password) in headers.
Then in the handler, I need to authenticate the user. If authentication fails then user should not be allowed to access the service.
 
0
 
Siva Prasanna KumarPrincipal Solutions ArchitectCommented:
ok its like this, when you say headers one way is to use HTTP headers which will as part of HTTP protocol
if you want the header to come as part of SOAP message, like

<Enevelope>
<Headers>
<userName>xxx</userName>
<password>xxx</password>
</Headers>
<Body>
<...>
</Body>
</Enevelope>
0
 
Siva Prasanna KumarPrincipal Solutions ArchitectCommented:
so please decide what you want I suggested rampart because in WS-Security there is a simple version of such thing available in a standard way called WS-UserNameToken, see if that solves your problem.
0
 
ank9Author Commented:
Thank you.
I'll use Rampart to pass SOAP headers.
 
0

Featured Post

Receive 1:1 tech help

Solve your biggest tech problems alongside global tech experts with 1:1 help.

  • 6
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now