Referencing CDI producer method result in h:selectOneMenu

Posted by user953217 on Stack Overflow See other posts from Stack Overflow or by user953217
Published on 2011-09-19T18:04:03Z Indexed on 2011/11/17 9:50 UTC
Read the original article Hit count: 289

Filed under:
|
|
|

I have a named session scoped bean CustomerRegistration which has a named producer method getNewCustomer which returns a Customer object. There is also CustomerListProducer class which produces all customers as list from the database. On the selectCustomer.xhtml page the user is then able to select one of the customers and submit the selection to the application which then simply prints out the last name of the selected customer.

Now this only works when I reference the selected customer on the facelets page via #{customerRegistration.newCustomer}. When I simply use #{newCustomer} then the output for the last name is null whenever I submit the form.

What's going on here? Is this the expected behavior as according to chapter 7.1 Restriction upon bean instantion of JSR-299 spec?

It says:

... However, if the application directly instantiates a bean class, instead of letting the container perform instantiation, the resulting instance is not managed by the container and is not a contextual instance as defined by Section 6.5.2, “Contextual instance of a bean”. Furthermore, the capabilities listed in Section 2.1, “Functionality provided by the container to the bean” will not be available to that particular instance. In a deployed application, it is the container that is responsible for instantiating beans and initializing their dependencies. ...

Here's the code:

Customer.java:

@javax.persistence.Entity
@Veto
public class Customer implements Serializable, Entity {
    private static final long serialVersionUID = 122193054725297662L;
    @Column(name = "first_name")
    private String firstName;
    @Column(name = "last_name")
    private String lastName;
    @Id
    @GeneratedValue()
    private Long id;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return firstName + ", " + lastName;
    }

    @Override
    public Long getId() {
        return this.id;
    }
}

CustomerListProducer.java:

@SessionScoped
public class CustomerListProducer implements Serializable {

    @Inject
    private EntityManager em;

    private List<Customer> customers;

    @Inject
    @Category("helloworld_as7")
    Logger log;

    // @Named provides access the return value via the EL variable name
    // "members" in the UI (e.g.,
    // Facelets or JSP view)
    @Produces
    @Named
    public List<Customer> getCustomers() {
        return customers;
    }

    public void onCustomerListChanged(
            @Observes(notifyObserver = Reception.IF_EXISTS) final Customer customer) {
//      retrieveAllCustomersOrderedByName();
        log.info(customer.toString());
    }

    @PostConstruct
    public void retrieveAllCustomersOrderedByName() {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Customer> criteria = cb.createQuery(Customer.class);
        Root<Customer> customer = criteria.from(Customer.class);
        // Swap criteria statements if you would like to try out type-safe
        // criteria queries, a new
        // feature in JPA 2.0
        // criteria.select(member).orderBy(cb.asc(member.get(Member_.name)));
        criteria.select(customer).orderBy(cb.asc(customer.get("lastName")));
        customers = em.createQuery(criteria).getResultList();
    }
}

CustomerRegistration.java:

@Named
@SessionScoped
public class CustomerRegistration implements Serializable {

    @Inject
    @Category("helloworld_as7")
    private Logger log;

    private Customer newCustomer;

    @Produces
    @Named
    public Customer getNewCustomer() {
        return newCustomer;
    }

    public void selected() {
        log.info("Customer " + newCustomer.getLastName() + " ausgewählt.");
    }

    @PostConstruct
    public void initNewCustomer() {
        newCustomer = new Customer();
    }

    public void setNewCustomer(Customer newCustomer) {
        this.newCustomer = newCustomer;
    }

}

not working selectCustomer.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
    <title>Auswahl</title>
</h:head>
<h:body>
    <h:form>
        <h:selectOneMenu value="#{newCustomer}" converter="customerConverter">
            <f:selectItems value="#{customers}" var="current"
                itemLabel="#{current.firstName}, #{current.lastName}" />
        </h:selectOneMenu>
        <h:panelGroup id="auswahl">
            <h:outputText value="#{newCustomer.lastName}" />
        </h:panelGroup>
        <h:commandButton value="Klick"
            action="#{customerRegistration.selected}" />
    </h:form>
</h:body>
</html>

working selectCustomer.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
    <title>Auswahl</title>
</h:head>
<h:body>
    <h:form>
        <h:selectOneMenu value="#{customerRegistration.newCustomer}" converter="customerConverter">
            <f:selectItems value="#{customers}" var="current"
                itemLabel="#{current.firstName}, #{current.lastName}" />
        </h:selectOneMenu>
        <h:panelGroup id="auswahl">
            <h:outputText value="#{newCustomer.lastName}" />
        </h:panelGroup>
        <h:commandButton value="Klick"
            action="#{customerRegistration.selected}" />
    </h:form>
</h:body>
</html>

CustomerConverter.java:

@SessionScoped
@FacesConverter("customerConverter")
public class CustomerConverter implements Converter, Serializable {
    private static final long serialVersionUID = -6093400626095413322L;

    @Inject
    EntityManager entityManager;

    @Override
    public Object getAsObject(FacesContext context, UIComponent component,
            String value) {
        Long id = Long.valueOf(value);
        return entityManager.find(Customer.class, id);
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component,
            Object value) {
        return ((Customer) value).getId().toString();
    }

}

© Stack Overflow or respective owner

Related posts about jsf

Related posts about jsf-2.0