Search code examples
jakarta-eeejbjax-rsjava-ee-6java-ee-7

JavaEE & JAX-RS: Resource Class Should Be Declared as Singleton or Stateless?


Looking at listing #1 at the following tutorial,

JAX-RS resource classes can be defined as @Stateless or @Singleton.

I have the following code in my application:

@Stateless
public class VisitDaoImpl implements VisitDao {

    @PersistenceContext(name = "MysqlPU")
    private EntityManager em;

    @Override
    public void persist(Visit vist) {
        em.persist(vist);
    }
}

@ApplicationPath("rest")
public class ApplicationConfig extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new java.util.HashSet<>();
        resources.add(WelcomeResource.class);
        return resources;
    }
}

//@Singleton
@Stateless
@Path("/Welcome")
public class WelcomeResource {

    @EJB
    private VisitDao visitDao;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String wellcomeMessage() {
        visitDao.persist(new Visit())
        return "Welcome";
    }
}

As you can see I do not have state in my resource class except for the Dao bean.

My questions are:

  1. Should I use @Stateless or @Singleton bean here?
  2. When to favor one of them on the other in JAX-RS resource classes?

Thank you.


Solution

  • I think @Stateless if you want to perform write operations to the database or other methods affecting state.

    Multiple threads (clients) would have to wait for the singleton to come available as default Lock is write in singleton-ejbs.

    from java-ee-6 tutorial:

    Annotating a singleton class with @Lock specifies that all the business methods and any timeout methods of the singleton will use the specified lock type unless they explicitly set the lock type with a method-level @Lock annotation. If no @Lock annotation is present on the singleton class, the default lock type, @Lock(WRITE), is applied to all business and timeout methods.

    In the example, there is an ejb-dao in between your @Path-ejb and the database. Which suggests you might be able to change to @Singleton and use @Lock(READ) on your bussiness method (no idea why anyone would wanna try).

    But I don't think that is safe, as the same ejb-dao-instance would be used for all concurrent invocations done by the clients and the EntityManager the DAO is holding is not thread-safe:

    from java-ee-6 tutorial:

    Application-managed entity managers are used when applications need to access a persistence context that is not propagated with the JTA transaction across EntityManager instances in a particular persistence unit. In this case, each EntityManager creates a new, isolated persistence context. The EntityManager and its associated persistence context are created and destroyed explicitly by the application. They are also used when directly injecting EntityManager instances can’t be done because EntityManager instances are not thread-safe. EntityManagerFactory instances are thread-safe.