互相更新JSF复合组件

时间:2012-04-18 07:13:40

标签: java design-patterns jsf-2 composite-component

我有疑问如何更新同一页面上的其他复合组件。如果我输入客户ID并单击“搜索”按钮,则应在数据库中搜索客户,如果存在,则系统继续搜索基于客户ID的案例。反之亦然。

对于此示例,假设关系Customer:Case为1:1。

main_page.xhtml

<h:body>
    <ui:composition template="/WEB-INF/template/layout.xhtml">
        <ui:define name="content">
            <custom:component_customer
                customerId="#{mainPageController.customer.id}"
                searchCustomer="#{mainPageController.searchCustomer}"
            />
            <custom:component_case
                caseaseId="#{mainPageController.case.caseId}"
                searchCase="#{mainPageController.searchCase}"
            />
        </ui:define>
    </ui:composition>
</h:body>

component_customer.xhtml

<composite:interface>
    <composite:attribute name="customerId" type="java.lang.Long"/>
    <composite:attribute name="searchCustomer" method-signature="void searchCustomer()"/>
</composite:interface>

<composite:implementation>
    <h:form>
        <h:inputText id="id" value="#{cc.attrs.customerId}"/>
        <h:commandButton value="Search" action="#{cc.attrs.searchCustomer}"/>
    </h:form>
</composite:implementation>

component_case.xhtml

<composite:interface>
    <composite:attribute name="caseId" type="java.lang.Long"/>
    <composite:attribute name="searchCase" method-signature="void searchCase()"/>
</composite:interface>

<composite:implementation>
    <h:form>
        <h:inputText id="id" value="#{cc.attrs.caseId}"/>
        <h:commandButton value="Search" action="#{cc.attrs.searchCase}"/>
    </h:form>
</composite:implementation>

MainPageController.java

@ManagedBean
@ViewScoped
public class MainPageController {

@EJB
private CaseLogic caseLogic;
@EJB
private CustomerLogic customerLogic;

private Customer customer = new Customer();
private Case case = new Case();

// getter & setters

public void searchCustomer() {
}

public void searchCase() {
}

1)是否有一些通用的“JSF”解决方案?

2)或者我应该尝试以某种方式在java代码中实现设计模式Observer?但是存在许多观察者(Customer,Case,...)存在许多主题(MainPageController,SecondPageController,...)的问题。

2 个答案:

答案 0 :(得分:0)

用面板abs包装组件盒为它提供一个ID。将该ID作为更新属性提供给搜索。在命令按钮中使用该属性。

答案 1 :(得分:0)

我只能通过实现Observer设计模式来实现更新复合组件(不同主题负责注册其Observers):

主题

public abstract class Subject {
    private final List<Observer> observerList = new ArrayList<>();

    public void registerObserver(final Observer observer) {
        observer.setSubject(this);
        observerList.add(observer);
    }

    public List<Observer> getObserverList() {
        return observerList;
    }

    public abstract void notifyObservers(final Observer observer);
}

具体主题

@ManagedBean
@ViewScoped
public class MainPageController extends Subject {
    @ManagedProperty(value = "#{caseComponent}")
    private CaseComponent caseComponent;
    @ManagedProperty(value = "#{customerComponent}")
    private CustomerComponent customerComponent;
    private final String customerComponentId = "MainPageCustomer";
    private final String caseComponentId = "MainPageCase";

    @Override
    public void notifyObservers(final Observer changed) {
        for (Observer observer : getObserverList()) {
            observer.update(changed);
        }
    }

    // is invoked by JSF framework thanks to @ManagedProperty injection
    public void setCaseComponent(CaseComponent caseComponent) {
        this.caseComponent = caseComponent;
        registerObserver(this.caseComponent);
    }

    // is invoked by JSF framework thanks to @ManagedProperty injection
    public void setCustomerComponent(CustomerComponent customerComponent) {
        this.customerComponent = customerComponent;
        registerObserver(this.customerComponent);
    }

    public String getCustomerComponentId() {
        return customerComponentId;
    }

    public String getCustomerComponentId() {
        return customerComponentId;
    }
}

观察

public interface Observer {
    public abstract void setSubject(Subject subject);
    public abstract void update(Observer changed);
}

具体观察者(CustomerComponent)

@ManagedBean
@ViewScoped
public class CustomerComponent implements Observer {

    @EJB
    private CustomerLogic logic;
    private Subject subject;
    // backing bean property
    private Customer customer = new Customer();

    @Override
    public void setSubject(final Subject subject) {
        this.subject = subject;
    }

    @Override
    public void update(final Observer changed) {
        if (changed instanceof CustomerComponent) {
            // do nothing, in this case the customer was updated yet
            // in public void searchCustomer() method
        } else if (changed instanceof DeliverySiteComponent) {
            DeliverySiteComponent deliverySiteComponent = (DeliverySiteComponent) changed;
            searchCustomer(deliverySiteComponent.getDeliverySite());
        }
   }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(final Customer customer) {
        this.customer = customer;
    }

    public void searchCustomer() {
        customer = logic.find(customer);
        if(customer != null && customer.getId() != null) {
            subject.notifyObservers(this);
        }
    }

    private void searchCustomer(final DeliverySite deliverySite) {
        customer = logic.find(deliverySite);
    }
}

具体观察者(CaseComponent)

@ManagedBean
@ViewScoped
public class CaseComponent implements Observer {
    ...
}

main_page.xhtml(此处设置id以强制JSF框架创建MainPageController的实例)

<h:body>
    <ui:composition template="/WEB-INF/template/layout.xhtml">
        <ui:define name="content">
            <custom:component_customer
                id="#{mainPageController.customerComponentId}"
                customerId="#{customerComponent.customer.id}"
                searchCustomer="#{customerComponent.searchCustomer}"
            />
            <custom:component_case
                id="#{mainPageController.caseComponentId}"
                caseaseId="#{caseComponent.case.caseId}"
                searchCase="#{customerComponent.searchCase}"
            />
        </ui:define>
    </ui:composition>
</h:body>

所以,现在我将每个复合组件仅与其托管bean连接。