Saturday, December 20, 2008

Let Spring load service class for JAX-WS

During deployment JAX-WS RI by default creates an instance (singleton) of web service implementation class and uses that to serve requests. At times we may want to customize the instantiation of the web service implementation class e.g. let Spring configure and load the object.

JAX-WS Commons has an extension for Spring integration, which delegates total configuration to Spring and makes RI specific files (sun-jaxws.xml) redundant. Currently I am happy with the way JAX-WS RI exposes web services and do not want everything to move to Spring or something else. I was just looking for a way to load the service implementation class by my code instead of RI doing so. JAX-WS RI has a poorly documented (or may be I am not able find it easily) feature called InstanceResolver, which lets developers to customize the way service implementation class is loaded. The code snippets below demostrate how to so-

public class MyResolver extends InstanceResolver<Object> {

    private final Object serviceImpl;

    /**
     * @param clazz
     */
    public MyResolver(Class<?> clazz) {
        serviceImpl= . . . load the class here or get it from Spring or somewhere else . . .;
    }

    /**
     * @see com.sun.xml.ws.api.server.InstanceResolver#resolve(com.sun.xml.ws.api.message.Packet)
     */
    @Override
    public Object resolve(Packet request) {
        return serviceImpl;
    }

}

// Now create an Annotation, which has @InstanceResolverAnnotation with MyResolver.class
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@InstanceResolverAnnotation(MyResolver.class)
public @interface MyWs {
}

// Now annotate the service class with above-mentioned annotation
@WebService(endpointInterface = "com.vinodsingh.Address")
@MyWs
public class AddressImpl implements Address {
    . . .
}

During deployment (WSServletContextListener) JAX-WS RI iterates through all annotations on the service class and sees if there is any annotation annotated with @InstanceResolverAnnotation. On finding one it will delegate the task of creating instance of the service class to the user defined InstanceResolver. With this I am able to load service classes using Spring.

1 Comment: