Search code examples
javajersey-2.0tomcat8

Jersey Singleton instantiated multiple time


I have to make a very small REST app and even if i'm used to Spring, Jersey seems lighter than Spring (maybe I'm wrong?).

I use Jersey 2.25 on a Tomcat 8.0.39.

I have a DAO class that currently access a text file (will be upgrade to a jdbc connection). Those read/write operations must be synchronized, hence I want my DAO instance to be a singleton.

@Singleton
public class ModelDao extends IModelDao
    public ModelDao() {
        System.out.println("init ModelDao");
    }

    @Override
    public MyModel read(int id){...}
}

This singleton is injected in a service:

@Path("/Model/")
public class ModelService {

    @Inject
    private IModelDao modelDao;

    @Path("{id}")
    @GET
    @Produces("application/json")
    public MyModel getModel(@PathParam("id") Integer id) {
        return modelDao.read(id);
    }
}

Through a binder

public class DaoBinder extends AbstractBinder {
    @Override
    protected void configure() {
        bind(ModelDao.class).to(IModelDao.class);
    }
}

In a ResourceConfig, I register the binder and my packages. When I use my service, I get the correct data but the ModelDao constructor is called on each request. So the read/write operations are not synchronized.

I understood a class annotated @Singleton was supposed to be instantiated only once in my app. Does I get it wrong?


Solution

  • Binding a service through the AbstractBinder with Jersey, the @Singleton annotation is not supported. You need to use the bind().to().in(Scope) syntax, where Scope would be e.g. Singleton.class, RequestScoped.class. The default scope is PerLookup, which is causing the behavior you are currently experiencing.

    Also instead of bind(Class).to(Class), you could use bind(Instance).to(Class), which would auto atically make it a singleton, without needing g to specify the scope.