ChrisGeo
ChrisGeo

Reputation: 3907

JSF SelectOneMenu get Entity

I am trying to obtain a Customer entity from a JSF SelectOneMenu component: The classes I have are as follows:

Customer Entity

@Entity
@Table(name="CUSTOMERS")
@NamedQuery(name="Customer.findAll", query="SELECT c FROM Customer c")
public class Customer implements Serializable {

    @Id
    @GeneratedValue
    @Column(name="CUSTOMER_ID")
    private Long customerId;

    @Column(name="FIRST_NAME")
    private String firstName;

    @Column(name="LAST_NAME")
    private String lastName;

    private String email;

    public Long getCustomerId() {  
        return customerId;
    }

    public void setCustomerId(Long customerId) {
        this.customerId = customerId;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        Long localCustomerId = customerId;
        String localFirstName = firstName;
        String localLastName = lastName;
        String localEmail = email;
        if (localCustomerId == null) {
            localCustomerId = 0L;
        }
        if (localEmail == null) {
            localEmail = "";
        }
        if (localFirstName == null) {
            localFirstName = "";
        }
        if (localLastName == null) {
            localLastName = "";
        }

        String toString = "customerId = " + localCustomerId + "\n";
        toString += "firstName = " + localFirstName + "\n";
        toString += "lastName = " + localLastName + "\n";
        toString += "email = " + localEmail;

        return toString;
    }

}

Customer Controller

 @ManagedBean
    @RequestScoped
    public class CustomerController implements Serializable {
    private static final long serialVersionUID = 1L;

    @Resource(name = "jdbc/__CustomerDBPool")
    private DataSource dataSource;

    @PersistenceUnit(unitName = "customerPersistenceUnit")
    private EntityManagerFactory emf;

    @Resource
    private UserTransaction userTransaction;

    @ManagedProperty(value = "#{customer}")
    private Customer customer;


    public DataSource getDataSource() {
        return dataSource;
    }

    public EntityManagerFactory getEmf() {
        return emf;
    }

    public void saveCustomer() {
        EntityManager entityManager = emf.createEntityManager();
        try {
            userTransaction.begin();
            entityManager.persist(customer);
            userTransaction.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public void setEmf(EntityManagerFactory emf) {
        this.emf = emf;
    }

    public List<Customer> getCustomerList() {

        List<Customer> list = null;
        EntityManager em = emf.createEntityManager();
        try {
            Query q = em.createNamedQuery("Customer.findAll");
            int m = q.getResultList().size();

            list = (List<Customer>)  q.getResultList();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    public Customer getCustomerById(Long id) {
        EntityManager entityManager = emf.createEntityManager();
        Query q = entityManager.createQuery("Select c FROM Customer c WHERE c.id = :id");
        q.setParameter("id", id);
        Customer c = (Customer) q.getResultList().get(q.getFirstResult());
        return c;
    }

    public String getCustomerDetails() {
        if (customer == null)
            return "NULL";
        else
            return customer.toString();
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
        //System.out.println(customer);
    }
    }

CustomerConverter

@ManagedBean
@RequestScoped
@FacesConverter(value = "CustomerConverter")
    public class CustomerConverter implements Converter, Serializable {

        @ManagedProperty(value = "#{cController}")
        private CustomerController cc;

        @Override
        public Object getAsObject(FacesContext context, UIComponent component,
                String value) {

            Long pk = Long.parseLong(value);
            Customer c = null;
            List<Customer> list = (List<Customer>) cc.getCustomerList();
            for (Customer k : list) {
                if (k.getCustomerId().equals(pk))
                        c = k;
            }

            return c;
        }

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

        public CustomerController getCc() {
            return cc;
        }

        public void setCc(CustomerController cc) {
            this.cc = cc;
        }
    }

And finally the .xhtml file

<h:head>
    <title>Save Customer</title>
</h:head>

<h:body>
    <h:panelGrid columns="1">

        <h:form>
            <h:messages id="messages"></h:messages>
            <p/>
            <h:selectOneMenu id="select1" value="#{customerController.customer}" converter="CustomerConverter">

                <f:selectItems 
                    value="#{customerController.customerList}" var="c"
                    itemLabel="#{c.customerId} #{c.firstName} #{c.lastName}"
                    itemValue="#{c.customerId}"/>
            </h:selectOneMenu>
            <p/>
            <h:commandButton value="Output" update="output2"></h:commandButton>

            <p/>
            <h:outputText id="output2" value="#{customerController.customerDetails}"/>
        </h:form>

    </h:panelGrid>
</h:body>
</html>

Basically I seem to have trouble instantiating the CustomerController bean withing the CustomerConverter bean. Any ideas what I'm doing wrong?

Upvotes: 0

Views: 1869

Answers (2)

BalusC
BalusC

Reputation: 1109262

Here,

@ManagedBean
@RequestScoped
@FacesConverter(value = "CustomerConverter")
public class CustomerConverter implements Converter, Serializable {

you've registered 2 different managed instances of the class: one as @ManagedBean and another one as @FacesConverter.

Whenever you use #{customerConverter} anywhere in EL context, then a request scoped managed bean instance from @ManagedBean will be returned, wherein the @ManagedProperty is properly injected.

Whenever you use converter="CustomerConverter" anywhere in the view, then the faces converter instance from @FacesConverter will be returned, wherein no dependency injection is supported at all.

This is not right. This is confusing. Just get rid of @FacesConverter and instead use

converter="#{customerConverter}"

Unrelated to the concrete problem: mingling business service and JPA logic in a JSF managed bean is a very poor practicve. You should be using a fullworthy EJB for this. You can find a concrete example in the following related questions:

Upvotes: 1

Laabidi Raissi
Laabidi Raissi

Reputation: 3333

I think using @ManagedBean and @FacesConverter is a very very bad thing to write. A managed bean must be responsible of view handling. A converter is for converting values.
Another bad design point in your code, is that you are accessing to DB directly from your managed bean, which is again very bad. You have to define another layer (DAO layer) for data access.
Suppose you defined a CustomerDAO for customers access. Then you will easily access to CUSTOMERS table in your managed bean and also in converter via your DAO.

Upvotes: 1

Related Questions