java - patron - Datos de ámbito de aplicaciones LOAD y CACHE con @Singleton y @Stateless
singleton c# (1)
Bueno, hice algunas pruebas y también probé el modo @Decorator
. Este todavía parece ser el mejor.
@Entity bean y @Stateless bean son lo mismo de la pregunta, mientras que he cambiado el @Singleton bean de la siguiente manera, agregando también el clásico caché temporizado:
@Singleton
public class RoomsCached {
@Inject
Rooms rooms;
private List<Room> cachedRooms;
private long timeout = 86400000L; // reload once a day
private long lastUpdate;
public List<Room> getCachedRooms() {
initCache();
return cachedRooms;
}
public void initCache() {
if (cachedRooms == null || expired()) {
cachedRooms = Collections.unmodifiableList(rooms.findAll());
lastUpdate = System.currentTimeMillis();
}
}
private boolean expired() {
return System.currentTimeMillis() > lastUpdate + timeout;
}
}
No es necesario @PostConstruct, ni a @EJB, no hay problemas de sincronización con el bean subyacente, @ inject-ed @Stateless.
Está funcionando bien.
Estoy buscando soluciones elegantes al viejo problema de cargar y almacenar en caché datos estáticos y compartidos al inicio de la aplicación (con una vida útil infinita).
Mi antigua forma era Spring Singleton Bean, pero ahora estoy tratando de lograrlo con JAVA EE 6 (JPA2, EJB3.1, CDI).
Tengo un @Entity
, y un @Stateless
EJB lo carga la entidad desde la base de datos. Mi idea era agregar un @Singleton
EJB para almacenar en caché los datos; También decidí mantener el EJB original separado, para evitar la violación de SRP (y porque en el futuro podría ser usado pasando el caché, por otros actores).
Por favor, eche un vistazo a esta prueba de concepto simplificada:
Entidad
@NamedQuery(name="Room.findAll", query="SELECT r FROM Room r")
@Entity
public class Room {
@Id
private Integer id; // GETTER, SETTER
private String description; // GETTER, SETTER
}
Cargador
@Stateless
public class Rooms {
@PersistenceContext
EntityManager em;
public List<Room> findAll() {
return em.createNamedQuery("Room.findAll",Room.class).getResultList();
}
}
Cacher
@Singleton
public class RoomsCached {
@EJB
Rooms rooms;
private List<Room> cachedRooms; // GETTER
@PostConstruct
public void initCache(){
this.cachedRooms = Collections.unmodifiableList(rooms.findAll());
}
}
¿Puedes ver grandes problemas, errores conceptuales o algo en este ejemplo?
Mis principales preocupaciones fueron
Si ambos fueran
@Singleton
(mehh), podría haber agregado@DependsOn("Rooms")
en el bean cacher, para asegurar que Rooms ya esté cargado antes de ser utilizado, pero con@Singleton
y@Stateless
no puedo ... will@Stateless
bean siempre se carga antes de que CDI lo inyecte en@Singleton
?@Singleton
llamando a@Stateless
parece extraño (he visto ejemplos de lo contrario); ¿Debo cambiar el diseño colocando la instancia de@Singleton
dentro del@Stateless
EJB?¿Es correcto cargar y almacenar en caché el método
@PostConstruct
?