Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Guice 3 with JAX-WS in Java 6 outside web container

We have a situation where we use JSR-330 based injections to configure our stand-alone Java 6 applications, which works very well for getting configuration parameters across all the layers.

We have also used JAX-WS web services for quite a while by using first stand-alone Metro distribution with Java 5 inside a web container, but with Java 6 we just use the Endpoint class to get a smaller footprint.

So now I have a situation where I have

  • A stand-alone Java 6 application - no servlet container (Jetty, Tomcat)
  • A Guice 3 Injector set up as I like it.
  • An Endpoint handling my @javax.jws.WebService annotated class which expose my methods as web services.

I would like the web service methods to either have their @Inject fields handled transparently, or to get access to the injector. I can grab it as a static field from the main method, but I'd like a cleaner solution.

Any suggestions?

(I understand from JAX-WS and Guice 3 that the http://jax-ws-commons.java.net/guice/ module does not work with Guice 3, and the workaround suggested is Tomcat specific)

Would JSR-250 @Resource annotations be useful here?

like image 587
Thorbjørn Ravn Andersen Avatar asked Oct 07 '11 12:10

Thorbjørn Ravn Andersen


1 Answers

I'm not sure that I've understood every bit of the question. It looks to too easy for +500 bounty. Please post some code if that's not what you're searching for.

Anyway, a simple solution which creates a web service with dependency injection:

final Module module = new HelloModule();
final Injector injector = Guice.createInjector(module);
final HelloService helloService = injector.getInstance(HelloService.class);

Endpoint.publish("http://localhost:8080/helloService", helloService);

Below a more sophisticated solution with classpath scanning (Reflections) based on Marcus Eriksson's code from JAX-WS Guice integration. It publishes all classes which is annotated with @GuiceManaged as a webservice with Endpoint.publish().

private void initGuicedWebservices(final String packageNamePrefix) 
        throws Exception {
    final Reflections reflections = new Reflections(packageNamePrefix);
    final Set<Class<?>> guiceManaged = 
        reflections.getTypesAnnotatedWith(GuiceManaged.class);
    for (final Class<?> clazz : guiceManaged) {
        doGuice(clazz);
    }
}

private void doGuice(final Class<?> clazz) throws Exception {
    final GuiceManaged guiceManagedAnnotation = 
        clazz.getAnnotation(GuiceManaged.class);

    final Injector injector = createInjector(guiceManagedAnnotation);

    final Object serviceObject = clazz.newInstance();
    injector.injectMembers(serviceObject);

    final String address = guiceManagedAnnotation.address();

    Endpoint.publish(address, serviceObject);
}

private Injector createInjector(final GuiceManaged guiceManagedAnnotation) 
        throws Exception {
    final Class<? extends Module>[] moduleClasses = 
        guiceManagedAnnotation.module();

    final List<Module> moduleInstances = new ArrayList<Module>();
    for (final Class<? extends Module> moduleClass : moduleClasses) {
        moduleInstances.add(moduleClass.newInstance());
    }

    return Guice.createInjector(moduleInstances);
}

The GuiceManaged annotation:

@Retention(RUNTIME)
@Target(TYPE)
@Documented
public @interface GuiceManaged {
    public Class<? extends Module>[] module();
    public String address();
}

And the HelloServiceImpl snippet:

@GuiceManaged(module = HelloModule.class, 
    address = "http://localhost:8080/helloService")
@WebService
public class HelloServiceImpl implements HelloService {

    @Inject // bound in HelloModule
    public GreetingsService greetingsService;

    @Override
    @WebMethod
    public String sayHello(final String name) {
        return greetingsService.sayHello(name);
    }
}
like image 155
palacsint Avatar answered Nov 04 '22 15:11

palacsint