Using new matchingEntityConverter class. Getting java.lang.ClassCastException
bsgcic Sep 16, 2009 5:03 AMMy background: I am new to both Seam and Java though I've been studying them with great enthusiasm and effort for a significant while. My background is in the old ASP vbscript world (MS Access db). Instead of going .Net, I am developing with Java/seam/postgres.
System environment: Java (latest)/Seam (2.1.2.GA)/Postgresql (8.4)/Jboss AS (5.1.0.GA)/Eclipse (3.4.2) with Seam Tools (latest) on a Windows Server 2003 native Japanese machine. Jboss default server deployed with postgres-ds.xml and postgresql-persistence-service.xml rather than hsqldb-ds.xml and hsqldb-persistence-service.xml.
I have been stumped with getting the s:convertEntity working with a h:selectOneMenu control which has had me pouring through tons of blogs, community posts, etc. for about two full weeks now. Ugh!
I found Christian Bauer's post of his new matchingEntityConverter class yesterday and am now trying to use that instead of s:convertEntity.
matchingEntityConvert can be found at the following links:
relation.to/Bloggers/DropdownsInJSFValidatingTheSelectedValue
Documentation/DropdownBoxesWithEntitiesAndPSageScope
Some initial questions before getting into the current error that I am getting:
1. I believe that I learned from one or more postings that s:convertEntity would work with h:selectOneMenu but not multi-select controls. For example, the following link mentions that Unfortunately, Seam's convertEnum can't handle multi selects yet.
in a discussion of s:convertEnum on a h:selectManyCheckbox control. Link.
Question: Is the matchingEntityConverter class expected to work with multi-select controls as well as single select controls?
2. I have seen postings indicating that Seam assumes that the name of the parameter assigned @id in entities is called id
and that naming it id
is important for some classes such as s:convertEntity. Is this really true? I had named given them a different name (though in my entities and tables for testing the s:convertEntity functionality, I am using the name id
to keep it simple). Should I change all of the @id parameters to id
or does it not matter?
3. I assumed that the following are the classes needed by the matchingEntityConvert class. Is this correct?
In particular, java.util. instead of org.hibernate.mapping. for Collection and Set. Also org.jboss.seam.ui. instead of org.hibernate.loader.entity. for AbstractEntityLoader.
java.beans.Introspector, java.beans.PropertyDescriptor, java.io.Serializable, java.util.Collection, java.util.HashSet, java.util.Set, javax.faces.component.UIComponent, javax.faces.context.FacesContext, javax.faces.convert.ConverterException, org.jboss.seam.annotations.Install, org.jboss.seam.annotations.Name, org.jboss.seam.annotations.faces.Converter, org.jboss.seam.annotations.intercept.BypassInterceptors, org.jboss.seam.annotations.Scope, org.jboss.seam.annotations.Transactional, org.jboss.seam.ui.AbstractEntityLoader, org.jboss.seam.ScopeType
Below is the error information that I am getting:
Stack Trace:
08:59:19,671 SEVERE [viewhandler] Error Rendering View[/person04tst03.xhtml] java.lang.ClassCastException: org.jboss.seam.ui.JpaEntityLoader_$$_javassist_seam_8 cannot be cast to org.jboss.seam.ui.AbstractEntityLoader at org.jboss.seam.ui.AbstractEntityLoader.instance(AbstractEntityLoader.java:55) at com.mysite.conversation.MatchingEntityConverter.getEntityLoader(MatchingEntityConverter.java:76) at com.mysite.conversation.MatchingEntityConverter.getAsString(MatchingEntityConverter.java:95) at org.jboss.seam.ui.converter.PrioritizableConverter.getAsString(PrioritizableConverter.java:67) at org.jboss.seam.ui.converter.ConverterChain.getAsString(ConverterChain.java:126) at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getFormattedValue(HtmlBasicRenderer.java:448) at com.sun.faces.renderkit.html_basic.MenuRenderer.renderOption(MenuRenderer.java:480) at com.sun.faces.renderkit.html_basic.MenuRenderer.renderOptions(MenuRenderer.java:772) at com.sun.faces.renderkit.html_basic.MenuRenderer.renderSelect(MenuRenderer.java:832) at com.sun.faces.renderkit.html_basic.MenuRenderer.encodeEnd(MenuRenderer.java:280) at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:861) at org.jboss.seam.ui.util.cdk.RendererBase.renderChild(RendererBase.java:190) at org.jboss.seam.ui.util.cdk.RendererBase.renderChildren(RendererBase.java:166) at org.jboss.seam.ui.renderkit.ValidateAllRendererBase.doEncodeChildren(ValidateAllRendererBase.java:33) at org.jboss.seam.ui.util.cdk.RendererBase.encodeChildren(RendererBase.java:92) at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837) at org.jboss.seam.ui.util.cdk.RendererBase.renderChild(RendererBase.java:186) at org.jboss.seam.ui.util.cdk.RendererBase.renderChildren(RendererBase.java:166) at org.jboss.seam.ui.renderkit.DecorateRendererBase.doEncodeChildren(DecorateRendererBase.java:152) at org.jboss.seam.ui.util.cdk.RendererBase.encodeChildren(RendererBase.java:92) at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837) at javax.faces.component.UIComponent.encodeAll(UIComponent.java:930) at javax.faces.render.Renderer.encodeChildren(Renderer.java:148) at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837) at javax.faces.component.UIComponent.encodeAll(UIComponent.java:930) at javax.faces.component.UIComponent.encodeAll(UIComponent.java:933) at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:592) at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:100) at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:176) at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110) at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100) at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83) at org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:40) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:178) at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290) at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:390) at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:517) at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:60) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.web.HotDeployFilter.doFilter(HotDeployFilter.java:53) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190) at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92) at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126) at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447) at java.lang.Thread.run(Thread.java:619)
Also the following Warning:
08:59:19,656 WARN [AjaxRendererUtils] AJAX Status component not found for AjaxComponent with id j_id140 08:59:19,812 WARN [AjaxRendererUtils] AJAX Status component not found for AjaxComponent with id j_id140
I put in the following package:
package com.mysite.conversation;
Components.xml:
<?xml version="1.0" encoding="UTF-8"?> <components xmlns="http://jboss.com/products/seam/components" xmlns:bpm="http://jboss.com/products/seam/bpm" xmlns:core="http://jboss.com/products/seam/core" xmlns:drools="http://jboss.com/products/seam/drools" xmlns:framework="http://jboss.com/products/seam/framework" xmlns:mail="http://jboss.com/products/seam/mail" xmlns:persistence="http://jboss.com/products/seam/persistence" xmlns:security="http://jboss.com/products/seam/security" xmlns:transaction="http://jboss.com/products/seam/transaction" xmlns:web="http://jboss.com/products/seam/web" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation= "http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.1.xsd http://jboss.com/products/seam/framework http://jboss.com/products/seam/framework-2.1.xsd http://jboss.com/products/seam/persistence http://jboss.com/products/seam/persistence-2.1.xsd http://jboss.com/products/seam/drools http://jboss.com/products/seam/drools-2.1.xsd http://jboss.com/products/seam/bpm http://jboss.com/products/seam/bpm-2.1.xsd http://jboss.com/products/seam/transaction http://jboss.com/products/seam/transaction-2.1.xsd http://jboss.com/products/seam/security http://jboss.com/products/seam/security-2.1.xsd http://jboss.com/products/seam/mail http://jboss.com/products/seam/mail-2.1.xsd http://jboss.com/products/seam/web http://jboss.com/products/seam/web-2.1.xsd http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.1.xsd"> <core:init jndi-pattern="@jndiPattern@" debug="true" distributable="false"/> <core:manager conversation-timeout="120000" concurrent-request-timeout="500" conversation-id-parameter="cid" /> <transaction:ejb-transaction/> <persistence:managed-persistence-context name="entityManager" persistence-unit-jndi-name="java:/com-mysiteEntityManagerFactory" /> <!-- framework:entity-home name="catGenderHome" entity-class="com.mysite.entity.CatGender" / --> <!-- factory name="catGender" value="#{catGenderHome.instance}" / --> <component name="identifierMatchingEntityConverter" class="com.mysite.conversation.MatchingEntityConverter" > <property name="match">id</property> <!-- That's actually the default property we'd use for comparison--> </component> <security:identity authenticate-method="#{authenticator.authenticate}"/> </components>
View: person04tst03.xhtml
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:rich="http://richfaces.org/rich" xmlns:a="http://richfaces.org/a4j" template="/layout/defaultATemplate.xhtml" > ... (bunch of html) ... <ui:define name="content"> <div class="section"><!-- RandomRef_ALSog --> <h1>person04Create</h1> </div><!-- class="section" --><!-- RandomRef_ALSog --> <div class="section"><!-- RandomRef_kjADe --> <div class="entry errors"> <h:messages id="messages" globalOnly="true"/> </div><!-- class="entry errors" --> <h:form id="person04CreationForm"> <fieldset><!-- RandomRef_BSEgk --> <s:decorate id="usernameDecorate" template="layout/edit.xhtml"> <ui:define name="label">Username:</ui:define> <h:inputText id="username" value="#{person04.username}" required="true"> <a:support id="onblur" event="onblur" reRender="usernameDecorate"/> </h:inputText><!-- id="username" --> </s:decorate><!-- id="usernameDecorate" --> <s:decorate id="nameDecorate" template="layout/edit.xhtml"> <ui:define name="label">Real Name:</ui:define> <h:inputText id="name" value="#{person04.name}" required="true"> <a:support id="onblur" event="onblur" reRender="nameDecorate"/> </h:inputText><!-- id="name" --> </s:decorate><!-- id="nameDecorate" --> <s:decorate id="passwordDecorate" template="layout/edit.xhtml"> <ui:define name="label">Password:</ui:define> <h:inputSecret id="password" value="#{person04.password}" required="true"/> </s:decorate><!-- id="passwordDecorate" --> <s:decorate id="verifyDecorate" template="layout/edit.xhtml"> <ui:define name="label">Verify Password:</ui:define> <h:inputSecret id="verify" value="#{person04Create.verify}" required="true"/> </s:decorate><!-- id="verifyDecorate" --> <s:decorate id="firstNameDecorate" template="layout/edit.xhtml"> <ui:define name="label">First Name:</ui:define> <h:inputText id="firstName" value="#{person04.firstName}" required="true"> <a:support id="onblur" event="onblur" reRender="firstNameDecorate"/> </h:inputText><!-- id="firstName" --> </s:decorate><!-- id="firstNameDecorate" --> <s:decorate id="lastNameDecorate" template="layout/edit.xhtml"> <ui:define name="label">Last Name:</ui:define> <h:inputText id="lastName" value="#{person04.lastName}" required="true"> <a:support id="onblur" event="onblur" reRender="lastNameDecorate"/> </h:inputText><!-- id="lastName" --> </s:decorate><!-- id="lastNameDecorate" --> <s:decorate id="country01Decorate" template="layout/edit.xhtml"> <ui:define name="label">Country01:</ui:define> <!-- h:inputText id="country01" value="# {person04.country01.id}" required="true"> <a:support id="onblur" event="onblur" reRender="country01Decorate"/> </h:inputText --><!-- id="country01" --> <h:selectOneMenu value="#{person04.country01}" required="true" converter="#{identifierMatchingEntityConverter}"> <s:selectItems value="#{country01s}" var="country01Var" label="#{country01Var.name}" noSelectionLabel="Please Select..."/> <a:support event="onchange" reRender="country01Decorate" status="globalStatus"/> <!-- s:convertEntity / --> </h:selectOneMenu> </s:decorate><!-- id="country01Decorate" --> <div class="buttonBox"> <h:commandButton id="person04Create" value="Person04Create" action="#{person04Create.register}"/>   <s:button id="cancel" value="Cancel" view="/home.xhtml"/> </div><!-- class="buttonBox" --> </fieldset><!-- RandomRef_BSEgk --> </h:form><!-- id="person04CreationForm" --> </div><!-- RandomRef_kjADe --> </ui:define><!-- content --> </ui:composition>
PLEASE NOTE: IN THE ENTITY CLASSES: TABLE, COLUMN AND JOINCOLUMN NAMES ARE ENCLODED IN BACKTICKS IN ORDER TO SUCCESSFULLY INTERACT WITH POSTGRESQL.
HOWEVER, I CHANGED THEM TO FORWARD TICKS IN THIS POST AS THEY WERE CAUSING FORMATTING ERRORS IN THIS SEAMFRAMEWORK.ORG FORUM POSTING FORM
Enitity: Person04.java
package com.mysite.entity; import static org.jboss.seam.ScopeType.SESSION; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.SequenceGenerator; import javax.persistence.Table; import org.hibernate.validator.Length; import org.hibernate.validator.NotNull; import org.hibernate.validator.Pattern; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; @Entity @Name("person04") @Scope(SESSION) @Table(name="'person04'") public class Person04 implements Serializable { private String username; private String password; private String name; private Long id; private String firstName; private String lastName; private Country01 country01; public Person04(String name, String password, String username) { this.name = name; this.password = password; this.username = username; } public Person04() {} @NotNull @Length(max=100) @Column(name="'name'") public String getName() { return name; } public void setName(String name) { this.name = name; } @NotNull @Length(min=5, max=15) @Column(name="'password'") public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Length(min=4, max=15) @Pattern(regex="^\\w*$", message="not a valid username") @Column(name="'username'") public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Id @NotNull @SequenceGenerator(name="person04_id_seqIdentifier", sequenceName="person04_id_seq", allocationSize=1) @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="person04_id_seqIdentifier") @Column(name="'id'", unique=true, columnDefinition="bigserial") public Long getId() { return id; } public void setId(Long id) { this.id = id; } @NotNull @Column(name="'firstName'") public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @NotNull @Column(name="'lastName'") public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @ManyToOne @JoinColumn(name="'country01Id'") public Country01 getCountry01() { return country01; } public void setCountry01(Country01 country01) { this.country01 = country01; } @Override public String toString() { return "Person04(" + username + ")"; } }
Entity: Country01.java
package com.mysite.entity; import static org.jboss.seam.ScopeType.SESSION; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.SequenceGenerator; import javax.persistence.Table; import org.hibernate.validator.Length; import org.hibernate.validator.NotNull; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; @Entity @Name("country01") @Scope(SESSION) @Table(name="'country01'") public class Country01 implements Serializable { private Long id; private String name; public Country01(String name) { this.name = name; } public Country01() {} @Id @NotNull @SequenceGenerator(name="country01_id_seqIdentifier", sequenceName="country01_id_seq", allocationSize=1) @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="country01_id_seqIdentifier") @Column(name="'id'", unique=true, columnDefinition="bigserial") public Long getId() { return id; } public void setId(Long id) { this.id = id; } @NotNull @Length(max=100) @Column(name="'name'") public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { /* return "Country01(" + id + "," + firstName + "," + lastName + ")"; */ return "Country01(" + name + ")"; } }
Country01List.java
package com.mysite.session; import javax.ejb.Local; import com.mysite.entity.Country01; @Local public interface Country01List { public void getCountry01s(); public Country01 getCountry01(); public void destroy(); }
Country01ListAction.java
package com.mysite.session; import static javax.ejb.TransactionAttributeType.REQUIRES_NEW; import static org.jboss.seam.ScopeType.SESSION; import java.io.Serializable; import java.util.List; import javax.ejb.Remove; import javax.ejb.Stateful; import javax.ejb.TransactionAttribute; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.jboss.seam.annotations.Destroy; import org.jboss.seam.annotations.Factory; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Observer; import org.jboss.seam.annotations.Out; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.datamodel.DataModel; import org.jboss.seam.annotations.datamodel.DataModelSelection; import org.jboss.seam.annotations.security.Restrict; import org.jboss.seam.faces.FacesMessages; import org.jboss.seam.log.Log; import com.mysite.entity.Country01; @Stateful @Scope(SESSION) @Name("country01List") @TransactionAttribute(REQUIRES_NEW) public class Country01ListAction implements Country01List, Serializable { private static final long serialVersionUID = 1L; @PersistenceContext private EntityManager em; @DataModel private List<Country01> country01s; @DataModelSelection private Country01 country01; @Logger private Log log; @Factory @Observer("country01Confirmed") public void getCountry01s() { country01s = em.createQuery("select c from Country01 c") .getResultList(); } public Country01 getCountry01() { return country01; } @Destroy @Remove public void destroy() {} }
Any help you could provide on this would be so much appreciated.
Jeff