如何更新@Produces @ApplicationScoped的集合?

时间:2013-09-12 20:46:46

标签: jsf-2 cdi

我目前正在远离Seam的@Factory注释。结合@Observer,我可以这样做:

@Factory(value = "optionsList", scope = ScopeType.APPLICATION)
@Observer("entity.modified")
public List<MyBean> produceEntityOptions() {
    List l = getEm().createQuery('select e from entity e').getResultList();
    Contexts.getApplicationContext().set("optionsList", l);
    return l;
}

哪个会缓存可能的选项列表,例如用于<f:selectItems>(实际计算可能更复杂)。

我已将其翻译为与CDI一起使用

@Produces @Named("optionsList") @ApplicationScoped
public List<MyBean> produceEntityOptions() {
    return getEm().createQuery('select e from entity e').getResultList();
}

但是当外部事件表明缓存已经过时时,这就失去了重新创建缓存的能力。我该怎么办呢?

1 个答案:

答案 0 :(得分:3)

以下是您可以做的事情:

@ApplicationScoped
public class MyListProducer {

    // the current list
    private List<MyBean> listOfBeans;

    // resets / reloads/ refreshes list
    private void loadList() {
        this.listOfBeans = getEm().createQuery('select e from entity e').getResultList();
    }

    // initialize the list
    @PostConstruct
    protected void postConstruct() {
        loadList();
    }

    // listen for the stale event - you'll have to create a type (maybe even qualifiers) yourself
    private void resetList(@Observes MyCustomListIsStaleEvent evt) {
        loadList();
    }

    // the producer - to ensure that the producer is called after you refresh the list, make the list of scope @Dependent instead of @ApplicationScoped
    @Produces @Named("optionsList")
    protected List<MyBean> getList() {
        return this.listOfBeans;
    }
}

我认为实际上,这就是你想要的。但我不排除可能存在差异的可能性 - 不太了解Seam。

附注:您应该考虑使用普通的旧同步或通过使上面的有状态会话bean和利用EJB同步机制来同步观察者和生成器方法。