0

I have question how can I update other composite component which is on the same page. If I enter the customer id and click on button "Search" the customer should be searched in database and if exist then system continue with searching of case base on customer id. And vice versa.

For this example assume that relations Customer:Case is 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) Is there some general "JSF" solution for that?

2) Or should I try somehow implement design pattern Observer in java code? But there is problem that there will be exist Many subjects (MainPageController, SecondPageController, ...) to Many observers (Customer, Case, ...).

sasynkamil
  • 859
  • 2
  • 12
  • 23

2 Answers2

0

wrap component case with a panel abs give it an ID. feed that ID into search as an update attribute. use that attribute in command button.

mosgjig
  • 537
  • 1
  • 9
  • 18
  • ok, I wrapped component case: .... But what you mean "feed that ID into search as and update attribut" and "use that attribue in command button"? – sasynkamil Apr 19 '12 at 16:46
  • sorry for the late reply. I'm on vacation. first the panel needs, to be within a form. next, creat a new parameter for your component that intakes a string representing the items you want to update. feed that string into the update attribute of command button. – mosgjig Apr 19 '12 at 23:49
  • I'm still fighting. But another question: Does standart have attribute "update"? Or I have to use eg PrimeFaces commandButton? – sasynkamil Apr 20 '12 at 16:13
0

I was possible to implement updating composite components only by implementing Observer design pattern (with difference that Subject is responsible for registering its Observers):

Subject

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);
}

Concrete subject

@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;
    }
}

Observer

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

Concrete observer (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);
    }
}

Concrete observer (CaseComponent)

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

main_page.xhtml (id is set here to force JSF framework to create an instance of 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>

So, now I have every composite component connected only with its managed bean.

sasynkamil
  • 859
  • 2
  • 12
  • 23