2

I am sure this is most probably a silly question but I am not familiar with JAX RS (and Jersey).

We've had a standalone Java application that basically starts a RESTful service. As part of a refactoring, we've moved this application to be just a thread within another application. That other application uses Spring beans that are defined in an application-context.xml. So, I need to inject some of those beans to the resource class (if that's the correct name for it: the one with @Path annotations, etc.). The problem is I don't know what instantiates this particular class. There is a main class of the legacy app that is creating a (jetty) Server instance with ServletContexthandler to which a ServletHolder is added to which a ResourceConfig is set. Something like that.

So, I can inject my stuff from Spring to this main class but can't see how exactly I can pass those objects to the JAX RS resource?

I am sure I miss something pretty simple.

Edit: I have added a better explanation to my problem and a solution I found below.

Evgeni
  • 331
  • 2
  • 6

2 Answers2

4

Jersey has integration with Spring support. For this case, there are really only two things you need to do:

  1. Make sure you have the integration dependency. You'll also need to the commons logging, so it doesn't complain

    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-spring4</artifactId>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.1</version>
        <exclusions>
            <exclusion>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
  2. Just add a ContextLoaderListener along with a WebApplicationContext containing your Spring context configuration.

    ServletContextHandler context
            = new ServletContextHandler(ServletContextHandler.SESSIONS);
    AnnotationConfigWebApplicationContext wac
            = new AnnotationConfigWebApplicationContext();
    wac.register(SpringConfig.class);
    context.addEventListener(new ContextLoaderListener(wac));
    

    Here the SpringConfig is just a "Java config" Spring configuration class. If you wanted you could use an XML application context, but the example I used in the below link uses a Java config class, but also show how to easily import an XML into the class if you just want to use your XML config. You can combine two.

That's pretty much it. Once you have this configured, you should be able to @Autowired your Spring beans into your Jersey resources.

For a complete example, check out this GitHub repo

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • Thanks, that seems to be a nice solution! I managed to solve my problem in another (simpler) way (which is most probably due to me not explaining my problem properly at the very beginning). I'll post my my solution below. – Evgeni Jul 19 '17 at 17:45
0

Maybe I wasn't able to explain well my problem, so basically it was a problem of how to inject beans into JAX-RS resource classes when the actual JAX-RS app is not being instantiated through its own DI-mechanism but from somewhere else. In my case I already had a Spring container that creates those beans and there was no easy way to link the Spring's own bean application context to the JAX-RS's one. A better solution would have been the one already answered but additional problem is that our existing Spring solution is XML-based, whereas the @Injected annotation in JAX-RS won't work with it (at least that's what I've read in their documentation).

So, JAX-RS supports @Injected annotations and in order for it to know where to get bean definitions from, I had to go to the class that defines the ResourceConfig and add the following lines to it:

.register(new AbstractBinder() {
    @Override
    protected void configure() {
        bind(beanImpl1).to(BeanInterface1.class);
        bind(beanImpl2).to(BeanInterface2.class);
    }
})

The actual beanImpl1 and beanImpl2 bean instances were coming through the constructor of that class, which in turn was instantiated from our Spring through the XML configuration.

Evgeni
  • 331
  • 2
  • 6