ejemplo java singleton ejb java-ee-7 inject

java - ejemplo - ejb singleton load on startup



Diferencia entre javax.inject.Singleton y javax.ejb.Singleton (3)

Estoy poco confundido. ¿Cuál es la diferencia exacta entre javax.inject.Singleton y javax.ejb.Singleton ?


He encontrado una explicación plausible here :

De forma predeterminada, los beans de sesión javax.ejb.Singleton son transaccionales (sección 13.3.7 de la especificación EJB 3.1) y requieren la adquisición de un bloqueo exclusivo para cada invocación de método empresarial (secciones 4.8.5.4 y 4.8.5.5).

En contraste, un javax.inject.Singleton no es transaccional y no admite la concurrencia administrada por contenedor (la consecuencia principal es que el contenedor no implementa ningún esquema de bloqueo). [...]

Si no necesita las funciones EJB, @ApplicationScoped con @ApplicationScoped ( javax.inject.Singleton no está definido por CDI y, por lo tanto, su semántica no está regida por esa especificación).

Para reducir futuras confusiones, uso esta prueba de unidad pequeña (el nombre del paquete de primer nivel debe reemplazarse):

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); } }


Una buena explicación de los conceptos detrás se da en este Article por Adam Bien.


Ya que la respuesta aceptada no resolvió mi problema, publico mi propia respuesta. No será tan bueno como el artículo de Adam Bien, pero definitivamente será más práctico:

Considere el siguiente código:

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"); } }

Y este servicio REST:

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(); } }

Usar javax.ejb.Singleton este código funciona bien. La instancia de DatabaseConnection se crea una vez y se inyecta al servicio REST. Sin embargo, al reemplazar ejb en importación con inject , recibiría NPE en la clase ChampionsAPI al acceder al campo db. .