【问题标题】:Porting functionality of a managed bean while migrating from Core JSF to Seam从 Core JSF 迁移到 Seam 时移植托管 bean 的功能
【发布时间】:2011-12-10 23:42:30
【问题描述】:

我曾经用预定义的值初始化实体对象的某些属性,早在它在 jsf 托管 bean 的 @PostConstruct 方法(甚至托管 bean 的构造函数)中实例化时。在将项目移植到 Seam 且托管 bean 消失时,我无法再保留此功能(还想知道在没有托管 bean 的 JSF 2.2 中它会如何)。

实体类:

@Entity
@Name("task") // this line in Seam version
public class Task implements Serializable {

    private Integer id;
    private String subject;
    private Date creationDate;
    private Date completionDate;
    private Category category;
    private User user;

    public Task() {
    }

    public Task(Date creationDate) {
        this.creationDate = creationDate;
        this.user = user;
    }

    // getters & setters, etc.
}

JSF 托管 Bean

public class TaskBean extends BaseBean {

    // Super class provides the logged in user object and a default category object

    private Task task = new Task(java.util.Calendar.getInstance().getTime(), this.user);

    @PostConstruct
    public void initTaskBean() {
        if (certainConditionMet) 
            task.setCategory(defaultCategory);
    }

    // Other managed bean business...
}

JSF 页面

<h:form>
<h:panelGrid columns="2">
    Date: <h:outputText value="#{taskBean.task.creationDate}">
            <f:convertDateTime pattern="dd/MM/yyyy" />
           </h:outputText>
    User:  <h:outputText value="#{taskBean.task.user.name}" />
    Subject: <h:inputText value="#{taskBean.task.subject}" id="subjectField" />
    Category: <h:selectOneMenu value="#{taskBean.task.category}" id="catMenu">
                <f:selectItems value="#{taskBean.categories}" />
              </h:selectOneMenu>
    // remaining stuff
</h:panelGrid>
</h:form>

Seam 版本中的无状态会话 Bean 也承担了 jsf 托管 bean 的责任

@Name("taskAction")
@Stateless
public class TaskAction implements TaskActionLocal {

    @PersistenceContext
    private EntityManager em;

    @In private FacesMessages facesMessages;
    @In User user;
    @In Category defaultCategory
    @Logger private Log log;

    @In
    // private Task task = new Task(java.util.Calendar.getInstance().getTime(), user)
    // the above didn't work so 
    private Task task; 

    @PostConstruct
    public void baslarken() {
        System.out.println("TaskAction PostConstructed");
        task = new task(java.util.Calendar.getInstance().getTime(), user);
        if (certainConditionMet) 
                task.setCategory(defaultCategory);

        // the above won't work either. Date and User always blank on the ui form
    }

    // other business methods, etc
}

表格的接缝版:

<h:form id="todo" styleClass="edit">
    <rich:panel>
        <f:facet name="header">Task To Do</f:facet>

        <s:decorate id="dateField" template="layout/edit.xhtml">
            <ui:define name="label">Date:</ui:define>
            <h:outputText value="#{task.creationDate}"/>
        </s:decorate>

        <s:decorate id="userField" template="layout/edit.xhtml">
            <ui:define name="label">User:</ui:define>
            <h:outputText value="#{task.user.name}"/>
        </s:decorate>

        <s:decorate id="subjectField" template="layout/edit.xhtml">
            <ui:define name="label">Başlık</ui:define>
            <h:inputText id="subject" required="true" value="#{task.subject}" >
            <a4j:support event="onblur" reRender="subjectField" bypassupdates="true" ajaxSingle="true" />
            </h:inputText>
        </s:decorate>

        <!-- other components, etc -->
    </rich:panel>
</h:form>

我需要有关如何使任务对象在实例化时预先填充日期和登录用户数据(最好是默认类别)的建议。

【问题讨论】:

    标签: jsf seam managed-bean postconstruct


    【解决方案1】:

    首先我很抱歉,但我找不到关于这个答案的评论链接?? (所以版主可以随意移动这篇文章;))

    应该可以将 entityhome 类扩展为会话 bean。但如果这是正确的做法,我不确定。我更有可能创建一个更准确地服务于我的目的的新会话 bean。

    用于工厂调用。您将在 jsf 页面中以与任何其他名称相同的方式调用它。 IE。价值=“#{createNewTask.id}”。或者你可以将它注入另一个类。看看接缝文档。它真的写得很好。

    【讨论】:

    • 谢谢,马丁。我在项目中应用了一种服务外观模式,其中每个直接与数据库的通信都是使用会话 bean 作为服务外观完成的,并且它们由 Seam(托管 bean)组件调用 - 尽管 Seam 明智的这种模式可能不是非常适合,因为它消除了对 JSF 托管 bean 的需求。因此,我将寻找一种更适合 Seam 的设计模式,以及一种能够让我为大型项目保持代码整洁的设计模式。
    【解决方案2】:

    您有多种初始化实体的可能性。您可以为实体扩展 EntityHome 类。这是编辑器处理实体的默认实现。如果您使用 seam-gen 创建应用程序,也会使用它。

    这看起来像这样:

    @Name("queryHome")
    @Scope(ScopeType.CONVERSATION)
    public class QueryHome extends EntityHome<Query> {
        /*
         * (non-Javadoc)
         * @see org.jboss.seam.framework.Home#createInstance()
         */
        @Override
        public Query createInstance() {
            Query query = super.createInstance();
            query.setUser(loggedUser);
            query.setCreationDate(new Date());
            query.setLastExecutionDate(new Date());
            return query;
        }
    }
    

    您将调用 queryHome.getInstance()。 如果 entityHome 中的 id 属性被设置,它将尝试从数据库中加载具有此 id 的实体,如果没有 id,它将调用 createInstance()。 这就是我正常使用的方式。

    您还可以在接缝托管 bean 中创建工厂注释方法。在那里你可以为所欲为。

    @Name("CreationFactory")
    @Scope(ScopeType.STATELESS)
    pulic class CreationFactory {
    
        @Factory("createNewTask")
        public Task createTask() {
            Task task = new Task();
            task.sometext = "sometext";
            return task;
        }
    }
    

    我通常不直接访问或创建 bean,但我使用像 entityhome 这样的管理器组件来完成它。您可以通过工厂简化访问,但这在 Seam 文档中进行了说明。

    马丁

    【讨论】:

    • martin,感谢您的建议,第一种方式工作得很好——尽管我不确定在 EJB 场景中,将 EntityHome 作为会话 bean 扩展是否可行(是吗?)第二种方式,你能告诉我如何调用 createTask 方法吗?
    猜你喜欢
    • 2016-07-09
    • 2011-03-25
    • 1970-01-01
    • 2011-07-18
    • 1970-01-01
    • 1970-01-01
    • 2011-07-10
    • 2021-02-25
    • 2015-11-26
    相关资源
    最近更新 更多