Skip to Main Content

Java EE (Java Enterprise Edition) General Discussion

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Custom Converter not Working with JSF selectOneMenu

843844Mar 29 2010
I have Google'd this for hours and have found no answers to this question. I'm new to the JSF and JavaEE worlds, but have been working with Java for several years. Hopefully someone will be able to shed some light for me. I'm teaching at a major university and we're trying to introduce JavaEE6 technologies in our Databases course. Here are all of the relevant files that I'm using.

index.xhtml:
            <h1 style="text-align: center">Add New Book</h1>
            <h:form>
                <table>
                    <tr>
                        <td>Title:</td>
                        <td>
                            <h:inputText id="title" value="#{BookView.book.title}"
                                         required="true"/>
                        </td>
                    </tr>
                    <tr>
                        <td>Publication Date (YYYY):</td>
                        <td>
                            <h:inputText id="pubDate" value="#{BookView.book.pubDate}"
                                         required="true"/>
                        </td>
                    </tr>
                    <tr>
                        <td>Price:</td>
                        <td>
                            <h:inputText id="price" value="#{BookView.book.price}"
                                         required="false"/>
                        </td>
                    </tr>
                    <tr>
                        <td>Publisher:</td>
                        <td>
                            <h:selectOneMenu id="pub" value="#{BookView.publisher}">
                                <f:converter converterId="pubConverter"/>
                                <f:selectItems value="#{PublisherView.publishers}"
                                               var="publisher"
                                               itemLabel="#{publisher.name}"
                                               itemValue="#{publisher.id}"/>
                            </h:selectOneMenu>
                        </td>
                    </tr>
                </table>
                <h:commandButton value="Add New Book" action="#{BookView.addBook}"/>
            </h:form>
BookView.java:
@ManagedBean(name="BookView")
@RequestScoped
public class BookView
{
    @EJB
    private BookFacade bookFacade;

    private Book book;

    private Publisher publisher;
    
    /** Creates a new instance of BookView */
    public BookView()
    {
        book = new Book();
    }

	/** Apropriate getters and setters for book and publisher */

    public String addBook()
    {
        book.setPublisher(publisher);
        this.bookFacade.create(book);
        return "listBooks";
    }
}
book.java (getters and setters removed):
@Entity
public class Book implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(length = 100)
    private String title;

    @ManyToOne
    @JoinColumn(name = "publisherId")
    private Publisher publisher;

    private Integer pubDate;

    @Column(precision=8, scale = 2)
    private double price;

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof Book)) {
            return false;
        }
        Book other = (Book) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "edu.usafa.dfcs.cs364.bookapp.entities.Book[id=" + id + "]";
    }

}
publisher.java (getters and setters removed):
@Entity
public class Publisher implements Serializable
{
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(length = 60)
    private String name;

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof Publisher)) {
            return false;
        }
        Publisher other = (Publisher) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return getName();
    }

}
PublisherConverter.java:
@FacesConverter(forClass=Publisher.class, value ="pubConverter")
public class PublisherConverter implements Converter
{
    private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("BookPU");

    public PublisherConverter()
    {
    }
    
    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value)
    {
        if (value == null && value.equals("0")) {
            return null;
        }
        try {
            Long key = Long.valueOf(value);
            EntityManager em = emf.createEntityManager();
            Publisher publisher = em.find(Publisher.class, key);
            return publisher;
        } catch (NumberFormatException e) {
            throw new ConverterException("Invalid value: " + value, e);
        }
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value)
    {
        Publisher publisher = (Publisher) value;
        Long id = publisher.getId();
        if (id != null) {
            return String.valueOf(id.longValue());
        } else {
            return "0";
        }
    }

}
The code compiles fine, but when I run on my GlassFish v3 (standard with NetBeans 6.8) server, it complains that Long cannot be cast to Publisher in the Converter getAsString method (line 1).

Output from GlassFish log (upon delployment from NetBeans):
INFO: edu.usafa.dfcs.cs364_BookApp_war_1.0-SNAPSHOT was successfully deployed in 1,520 milliseconds.
SEVERE: Error Rendering View[/index.xhtml]
java.lang.ClassCastException: java.lang.Long cannot be cast to edu.usafa.dfcs.cs364.bookapp.entities.Publisher
        at edu.usafa.dfcs.cs364.bookapp.controller.PublisherConverter.getAsString(PublisherConverter.java:45)
        at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getFormattedValue(HtmlBasicRenderer.java:502)
        at com.sun.faces.renderkit.html_basic.MenuRenderer.renderOption(MenuRenderer.java:532)
        at com.sun.faces.renderkit.html_basic.MenuRenderer.renderOptions(MenuRenderer.java:790)
        at com.sun.faces.renderkit.html_basic.MenuRenderer.renderSelect(MenuRenderer.java:842)
        at com.sun.faces.renderkit.html_basic.MenuRenderer.encodeEnd(MenuRenderer.java:296)
...
Any ideas? I was supposed to cover this in class this morning and I had to do a work-around in the BookView class to get this working for them, but I'd like to use the Custom Converter as it was intended.

Thanks for any help you can provide,
Alex
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Apr 26 2010
Added on Mar 29 2010
0 comments
1,081 views