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