Java TM API for XML Web Services
(JAX-WS)

Stateful Web Service with JAX-WS RI

Specification Version: 2.1
Implementation Version: 2.1.7

Contents

  1. 1. Introduction
    1. 2. Usage
      1. 3. Things To Consider

        1. Introduction

        JAX-WS RI has a vendor extension that allows developers to bring back object state to the web service world. Normally, JAX-WS RI only creates one instance of a service class, and have it serve all incoming requests concurrently. This makes it essentially impossible to use instance fields of the service class for any meaningful purpose.

        Because of this, people end up coding like C, in anti-OO fashion. Either that or you end up with writing boiler-plate code to dispatch a request to the right instance of your real domain object.

        The stateful web service support in JAX-WS RI resolves this problem by having JAX-WS RI maintain multiple instances of a service. By using WS-Addressing behind the scene, it provides a standard-based on-the-wire protocol and easy-to-use programming model.

        2. Usage

        Application service implementation classes (or providers) who'd like to use the stateful web service support must declare @Stateful annotation on a class. It should also have a public static method/field that takes StatefulWebServiceManager.

        @Stateful @WebService @Addressing
        class BankAccount {
            protected final int id;
            private int balance;
            
            Account(int id) { this.id = id; }
            
            @WebMethod
            public synchronized void deposit(int amount) { balance+=amount; }
        
            // either via a public static field
            
            public static StatefulWebServiceManager<BankAccount> manager;
            
            // ... or  via a public static method (the method name could be anything)
            
            public static void setManager(StatefulWebServiceManager<BankAccount> manager) {
               ...
            }
            
        }
        

        After your service is deployed but before you receive a first request, the resource injection occurs on the field or the method.

        A stateful web service class does not need to have a default constructor. In fact, most of the time you want to define a constructor that takes some arguments, so that each instance carries certain state (as illustrated in the above example.)

        Each instance of a stateful web service class is identified by an unique EndpointReference. Your application creates an instance of a class, then you'll have JAX-WS RI assign this unique EPR for the instance as follows:

        @WebService
        class Bank { // this is ordinary stateless service
            @WebMethod
            public synchronized W3CEndpointReference login(int accountId, int pin) {
                if(!checkPin(pin))
                    throw new AuthenticationFailedException("invalid pin");
                BankAccount acc = new BankAccount(accountId);
                return BankAccount.manager.export(acc);
            }
        }
        

        Typically you then pass this EPR to remote systems. When they send messages to this EPR, JAX-WS RI makes sure that the particular exported instance associated with that EPR will receive a service invocation.

        3. Things To Consider

        When you no longer need to tie an instance to the EPR, use {@link #unexport(Object)} so that the object can be GC-ed (or else you'll leak memory.) You may choose to do so explicitly, or you can rely on the time out by using {@link #setTimeout(long, Callback)}. *

        {@link StatefulWebServiceManager} is thread-safe. It can be safely invoked from multiple threads concurrently.