Dato che si utilizza la funzione di gestione bean JSF (e quindi non CDI, che richiederebbe una risposta completamente diversa), è possibile ottenere ciò con @CustomScoped
. Il valore @CustomScoped
deve fare riferimento a un'implementazione Map
in un ambito più ampio, solitamente esistente.
Qualcosa di simile:
@ManagedBean
@CustomScoped("#{timeoutScope}")
public class TimeoutBean {}
Come l'annotazione @CustomScoped
non supporta il passaggio di argomenti aggiuntivi, impostando il timeout può essere fatto solo attraverso un'annotazione personalizzato aggiuntivo come di seguito:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Timeout {
/** Minutes. */
int value();
}
@ManagedBean
@CustomScoped("#{timeoutScope}")
@Timeout(5) // Expires after 5 minutes.
public class TimeoutBean {}
Ora, ecco un esempio di kickoff di come è il #{timeoutScope}
, incluso @PostConstruct
supporto (automaticamente) e @PreDestroy
supporto (manualmente):
@ManagedBean
@SessionScoped
public class TimeoutScope extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
@Override
public Object put(String name, Object bean) {
Timeout timeout = bean.getClass().getAnnotation(Timeout.class);
if (timeout == null) {
throw new IllegalArgumentException("@Timeout annotation is required on bean " + name);
}
Long endtime = System.nanoTime() + (timeout.value() * (long) 6e10);
Object[] beanAndEndtime = new Object[] { bean, endtime };
return super.put(name, beanAndEndtime);
}
@Override
public Object get(Object key) {
Object[] beanAndEndtime = (Object[]) super.get(key);
if (beanAndEndtime == null) {
return null;
}
Object bean = beanAndEndtime[0];
Long endtime = (Long) beanAndEndtime[1];
if (System.nanoTime() > endtime) {
String name = (String) key;
ScopeContext scope = new ScopeContext("timeoutScope", Collections.singletonMap(name, bean));
FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().publishEvent(context, PreDestroyCustomScopeEvent.class, scope);
return null;
}
return bean;
}
}
Vedete, è con scope di sessione e implementa Map
. Per quanto riguarda l'ambito, in questo modo è legato a una sessione utente specifica, non all'intera applicazione. Se si desidera effettivamente condividere il bean in tutte le sessioni utente nell'applicazione, quindi impostarlo come ambito ambito. Per quanto riguarda lo Map
, il JSF di henever deve trovare un bean gestito, prima tenta get()
. Se restituisce null
(ad esempio, il bean non esiste ancora), creerà automaticamente l'istanza del bean gestito ed eseguirà uno put()
.
All'interno dello put()
, si tratta di estrarre e calcolare il timeout e memorizzarlo nella mappa. All'interno di get()
, è sufficiente controllare il timeout e restituire null
per indicare a JSF che il bean non esiste più. JSF sarà poi semplicemente auto-crearlo e tornare a put()
, ecc
si noti che sto usando al posto del System#nanoTime()
System#currentTimeMillis()
in quanto quest'ultimo è legata a OS tempo (sistema operativo), non il tempo di hardware (e è quindi sensibile ad ao DST e cambiamenti controllati dall'utente nel tempo).
Non puoi farlo se il contenitore gestisce i tuoi fagioli – Dummy
@Dummy sono JSF/gestiscono bean ** not ** ejbs !! Sto gestendo gli ambiti dei fagioli JSF !! – Junaid
Beh, non hai detto esplicitamente, puoi usare i bean di sessione come bean di supporto jsf tecnicamente. Se sì, non hai pensato al servizio di timer? – Dummy