如何在JSF 2.0 / 2.1更换@ManagedBean / @ViewScope通过CDI(H

2019-07-18 08:59发布

我目前正在评估的Java EE 6 / JSF 2.1 RichFaces的。

该声明为一个bean

@ManagedBean
@ViewScoped
  1. 获取的ID集(以制备例如删除操作)。
  2. 通过JSF将显示确认弹出。
  3. 如果用户确认,删除方法被调用并删除该ID存储在第1步中的行。

由于CDI豆没有ViewScope我试图豆声明如下:

@Named
@ConversationScoped

现在的处理在步骤3中失败,因为这是在步骤1中(检查到)设置的值是不再可用。

我一定要使用Conversation.begin()Conversation.end()方法?

如果是这样,这里将是很好的地方调用它们?

Answer 1:

如果你可以升级到2.2 JSF,马上行动吧。 它提供了一个原生@ViewScoped的CDI标注。

import javax.faces.view.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class Bean implements Serializable {
    // ...
}

另外,安装OmniFaces这带来了自己的CDI兼容@ViewScoped ,包括工作@PreDestroy (这是JSF破@ViewScoped )。

import javax.inject.Named;
import org.omnifaces.cdi.ViewScoped;

@Named
@ViewScoped
public class Bean implements Serializable {
    // ...
}

另一种方法是安装MyFaces的CODI其中透明桥接JSF 2.0 / 2.1 @ViewScoped到CDI。 这不仅增加了自动生成的请求参数的URL(如@ConversationScoped会做)。

import javax.faces.bean.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class Bean implements Serializable {
    // ...
}

如果你确实需要使用@ConversationScoped ,那么你的确需要maunally开始和结束。 您需要@Inject一个Conversation并调用begin()@PostConstructend()在交谈中,通常会被重定向到一个新的视图操作方法的最新举措。

import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Named;

@Named
@ConversationScoped
public class Bean implements Serializable {

    @Inject
    private Conversation conversation;

    // ...

    @PostConstruct
    public void init() {
        conversation.begin();
    }

    public String submit() {
        // ...

        conversation.end();
        return "some.xhtml?faces-redirect=true";
    }

}

也可以看看:

  • 如何选择合适的豆范围是什么?


Answer 2:

我想你可以从CDI扩展受益于创建自己的范围,从而可以实现的背景下,并使用@NormalScope

  • CDI触发一个事件AfterBeanDiscovery每个bean调用后
  • 您可以使用CDI扩展到@Observes这一事件,并添加上下文实现
  • 在你的范围内实现,您可以:
    1. 使用Contextual它的名字就可以获得你的bean FacesContext ViewRoot Map每个Ajax调用返回后回
    2. 使用CreationalContext如果从第一步bean的名字没有找到在创建它FacesContext ViewRoot Map

为了更深入的解释,我建议这个链接: http://www.verborgh.be/articles/2010/01/06/porting-the-viewscoped-jsf-annotation-to-cdi/



Answer 3:

注入谈话到你的bean,并在@PostConstructor方法展开对话,如果对话是短暂的。

和删除记录后,结束您的谈话,您引导到目的地页面。 当开始对话。 下面是一个例子

public class BaseWebBean implements Serializable {

private final static Logger logger = LoggerFactory.getLogger(BaseWebBean.class);
@Inject
protected Conversation conversation;

@PostConstruct
protected void initBean(){
}

public void continueOrInitConversation() {
        if (conversation.isTransient()) {
            conversation.begin();
            logger.trace("conversation with id {} has started by {}.", conversation.getId(), getClass().getName());
        }
    }

public void endConversationIfContinuing() {
        if (!conversation.isTransient()) {
            logger.trace("conversation with id {} has ended by {}.", conversation.getId(), getClass().getName());
            conversation.end();
        }
}

}

@ConversationScoped
@Named
public class yourBean extends BaseWebBean implements Serializable {
    @PostConstruct
    public void initBean() {
        super.initBean();
        continueOrInitConversation();
    }

    public String deleteRow(Row row)
    {
        /*delete your row here*/
        endConversationIfContinuing();
        return "yourDestinationPageAfter removal";
    }

}


Answer 4:

有持有的一些推广到Java EE栈功能项目: DeltaSpike 。 这是缝3,阿帕奇CODI的整合。 在其他之上,它包括@ViewScoped到CDI。 这是一个古老的文章,现在已经达到1.3.0版本



Answer 5:

您可以使用:

import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class PageController implements Serializable {

    private String value;

    public void setValue(String value) {
    this.value = value;
    }

    public String getValue() {
    return value;
    }

    public void execute() {
    setValue("value");
    }

    @PostConstruct
    public void init() {
    System.out.println("postcontructor");
    }

}


文章来源: How to replace @ManagedBean / @ViewScope by CDI in JSF 2.0/2.1