Before going through this tutorial please make sure that you have the following jars in classpath. You can create simple Java project or Dynamic Web Project in Eclipse. I will create Java Project here. If you create Dynamic Web Project then you can directly deploy the service to the server and in this case you don’t need to write a class for endpoint pulishing.
Please download the jars and put under WEB-INF/lib directory.

jax-ws webservice example

I am going to give an example on how to implement a simple application level authentication in JAX-WS. In this tutorial I am going to authenticate a client to the endpoint server.

The idea is straight forward. The client who wants to consume the Service, will have to authenticate using sending the credentials like username and password in the HTTP Request Header. Then server retrieves these username and password from header information and validates the client’s identity. In reality password should be encrypted to achieve an acceptable level of security. But in this tutorial I am going to keep things as simple as possible, but you keep in mind that authentication along with session management are hard and crucial issues when developing a secure Web application.

Service Endpoint
First we need to create a Web Service Endpoint Interface. This interface will contain the declarations of all the methods for the Web Service.
Then we have to create a class that actually implements the above interface, which will be our Endpoint implementation.

Web Service Endpoint Interface (SEI)

package com.roytuts.service;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@WebService
@SOAPBinding(style = Style.RPC)
public interface Hello {
	@WebMethod
	public String sayHello(String name);
}

 

Web Service Endpoint Implementation

As discussed previously, the server would have to read the HTTP request header information which the client put, and validate its identity. Service Endpoint Implementation obtains a MessageContext object through a WebServiceContext for accessing the objects of the message. The WebServiceContext interface enables a web service endpoint implementation class to access message contexts and security information of the requester. The service runtime will inject the WebServiceContext on any field marked with @Resource annotation. We will call the WebServiceContext‘s getMessageContext() method to get MessageContext instance.

The HTTP Request Header will be retrieved using MessageContext’s get method with MessageContext.HTTP_REQUEST_HEADERS as a parameter which nominates the kind of context we need from the message. The Header will be retrieved as a Map which is very convenient because you can specify (key,value) pairs directy. Thus, we retrieve the corespoding credentials.

package com.roytuts.service;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

@WebService(endpointInterface = "in.webtuts.service.Hello")
public class HelloImpl implements Hello {

    @Resource
    WebServiceContext context;

    @Override
    public String sayHello(String name) {

        MessageContext messageContext = context.getMessageContext();

        /**
         * get http header information
         */
        Map<?, ?> httpHeaders = (Map<?, ?>) messageContext
                .get(MessageContext.HTTP_REQUEST_HEADERS);
        List<?> users = (List<?>) httpHeaders.get("username");
        List<?> passwords = (List<?>) httpHeaders.get("password");

        /**
         * retrieve username and password information from http headers
         */
        String username = "";
        String password = "";

        if (users != null && !users.isEmpty()) {
            username = users.get(0).toString();
        }

        if (passwords != null && !passwords.isEmpty()) {
            password = passwords.get(0).toString();
        }

        /**
         * verify the user
         */
        if (username.equalsIgnoreCase("user") && password.equals("pass")) {
            return "Hello " + name;
        } else {
            return "Authentication faild! Please provide correct credentials";
        }

    }

}

 

Web Service Endpoint Publisher

package com.roytuts.service.test;

import com.roytuts.service.HelloImpl;

import javax.xml.ws.Endpoint;

public class HelloPublisher {

    public static void main(String[] args) {
        Endpoint.publish("http://localhost:8888/jax-ws-auth/hello",
                new HelloImpl());
    }

}

 

Once we run the above publisher class the Web Service will be available to the clients, deployed in the URL:
http://localhost:8888/jax-ws-auth/hello

And this is the wsdl file that automatically created and
published at: http://localhost:8888/jax-ws-auth/hello?WSDL

WSDL:

<?xml version='1.0' encoding='UTF-8'?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net.
    RI's version is JAX-WS RI 2.2-b05-. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net.
    RI's version is JAX-WS RI 2.2-b05-. -->
<definitions targetNamespace="http://service.roytuts.com/" name="HelloImplService">
    <types>
        <xsd:schema>
            <xsd:import namespace="http://service.roytuts.com/" schemaLocation="http://localhost:8888/jax-ws-auth/hello?xsd=1"/>
        </xsd:schema>
    </types>
    <message name="sayHello">
        <part name="parameters" element="tns:sayHello"/>
    </message>
    <message name="sayHelloResponse">
        <part name="parameters" element="tns:sayHelloResponse"/>
    </message>
    <portType name="Hello">
        <operation name="sayHello">
            <input wsam:Action="http://service.roytuts.com/Hello/sayHelloRequest" message="tns:sayHello"/>
            <output wsam:Action="http://service.roytuts.com/Hello/sayHelloResponse" message="tns:sayHelloResponse"/>
        </operation>
    </portType>
    <binding name="HelloImplPortBinding" type="tns:Hello">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
        <operation name="sayHello">
            <soap:operation soapAction=""/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
        </operation>
    </binding>
    <service name="HelloImplService">
        <port name="HelloImplPort" binding="tns:HelloImplPortBinding">
            <soap:address location="http://localhost:8888/jax-ws-auth/hello"/>
        </port>
    </service>
</definitions>

 

Java Web Service Client

The client will consume the web service so the client has to make a new HTTP Request Header containing its username and password. To access and manupulate the request contexts of the message the client has to get a BindingProvider from the service port using getRequestContext() method. The BindingProvider interface enables the client to access and manipulate the associated context objects for request and response messages. The Request Context is retrieved as a Map object. MessageContext.ENDPOINT_ADDRESS_PROPERTY is used to nominate the target service endpoint address. Now we need to add two properties username and password to the Map object. Then we put this Map object in MessageContext.HTTP_REQUEST_HEADERS.

package com.roytuts.service.test;

import com.roytuts.service.Hello;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import javax.xml.ws.handler.MessageContext;

public class HelloClient {

    public static void main(String[] args) {

        try {

            URL url = new URL("http://localhost:8888/jax-ws-auth/hello?wsdl");

            QName qName = new QName("http://service.roytuts.com/",
                    "HelloImplService");

            Service service = Service.create(url, qName);

            Hello hello = service.getPort(Hello.class);

            /******************* Username & Password ******************************/
            Map<String, Object> reqContext = ((BindingProvider) hello)
                    .getRequestContext();
            reqContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
                    "http://localhost:8888/jax-ws-auth/hello?wsdl");

            Map<String, List<String>> headers = new HashMap<String, List<String>>();
            headers.put("username", Collections.singletonList("user1"));
            headers.put("password", Collections.singletonList("pass"));
            reqContext.put(MessageContext.HTTP_REQUEST_HEADERS, headers);
            /**********************************************************************/

            String response = hello.sayHello("Soumitra");
            System.out.println("response: " + response);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

    }

}

 

The output will be:

if username – user and password – pass

response: Hello Soumitra

 

if username – other than user or password – other than pass

response: Authentication faild! Please provide correct credentials

 

That’s all. Thank you for your patience. Please do not forget to leave a comment.

Tags:

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials | TwitterFacebook Google PlusLinkedin | Reddit

Leave a Reply

Your email address will not be published. Required fields are marked *