Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between javax.inject.Singleton and javax.ejb.Singleton

im little confused. What is the exact difference between javax.inject.Singleton and javax.ejb.Singleton?

like image 860
Hakan Kiyar Avatar asked Apr 12 '16 08:04

Hakan Kiyar


People also ask

What is javax inject singleton?

javax.ejb.Singleton is an annotation used to create an @Singleton EJB (as opposed to @Sateless EJB or @Stateful EJB) On the other hand, javax.inject.Singleton is an annotation used to create a CDI with singleton scope. So basically, one creates a singleton EJB while the other creates a CDI with singleton scope.

What is javax inject inject?

Package javax. inject. This package specifies a means for obtaining objects in such a way as to maximize reusability, testability and maintainability compared to traditional approaches such as constructors, factories, and service locators (e.g., JNDI).

What is singleton ejb?

ejb. Singleton annotation is used to specify that the enterprise bean implementation class is a singleton session bean: @Singleton public class SingletonBean { ... }

What is @named in Java?

We are going to use @Inject alongside @Named annotations from CDI of Java EE. @Named annotation is used for giving names for classes which implements the interface, and it is optional. Otherwise, we can specify alternatives and a default bean by @Alternative , and @Default annotations.


2 Answers

I found a plausible explanation here:

By default, javax.ejb.Singleton session beans are transactional (section 13.3.7 of the EJB 3.1 specification) and require acquisition of an exclusive lock for every business method invocation (sections 4.8.5.4 and 4.8.5.5).

In contrast, a javax.inject.Singleton is not transactional and does not support container-managed concurrency (the major consequence being that no locking scheme is implemented by the container). [...]

If you don't need EJB features, stick with @ApplicationScoped (javax.inject.Singleton is not defined by CDI, and its semantics are therefore not governed by that specification).

To reduce future confusion, I use this small unit test (first level package name needs to be replaced):

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;  import com.tngtech.archunit.core.domain.JavaClasses; import com.tngtech.archunit.core.importer.ClassFileImporter;  import org.junit.Test;  public class SingletonTest {      /** requires com.tngtech.archunit:archunit-junit:0.4.0 */     @Test     public void detectWrongSingletonAnnotation() {          final ClassFileImporter importer = new ClassFileImporter();         final JavaClasses classes = importer.importPackages("first_level_package");          noClasses().should().beAnnotatedWith("javax.inject.Singleton")                 .as("Please use javax.ejb.Singleton instead of javax.inject.Singleton.")                 .check(classes);     } } 
like image 153
Jens Piegsa Avatar answered Sep 19 '22 16:09

Jens Piegsa


Since accepted answer didn't solve my problem I post my own answer. It won't be as good as article by Adam Bien but definitely will be more practical:

Consider following code:

import javax.annotation.PostConstruct; import javax.ejb.Singleton;  @Singleton public class DatabaseConnection {      @PostConstruct     public void init() {         System.out.println("init");     }      public ChampionComp getFirstRecord() {         return new ChampionComp("Ashe", "Teemo", "Warwick",                  "Blitzcrank", "Syndra", "Anivia", "Brand", "Rammus", "Xin Zhao", "Irelia");     }  } 

And this REST service:

import javax.inject.Inject; import javax.ws.rs.GET; import javax.ws.rs.Produces; import javax.ws.rs.Path;  @Path("/champions") public class ChampionsAPI {      @Inject     private DatabaseConnection db;      @GET     @Produces("text/plain")     public String getClichedMessage() {         ChampionComp comp = db.getFirstRecord();         return comp.toString();     } } 

Using javax.ejb.Singleton this code works just fine. The DatabaseConnection instance is created once and injected to REST service. However when replacing ejb in import with inject you would receive NPE in ChampionsAPI class while accessing db field - that's because your Singleton was not created (for some reason, maybe because one need to make use of interfaces while using javax.inject.Singleton ? ).

like image 45
kukis Avatar answered Sep 20 '22 16:09

kukis