Hi guys,
in a Seam/JSF/Facelets evaluation project I ran into the following problem. Looks like
there is a problem if you use embeddable Objects in Entity beans.
Consider the following entity bean containing an embedded object: @Entity
| @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
| @DiscriminatorColumn(name = "TYPE", discriminatorType =
DiscriminatorType.STRING)
| @Table (name = "CLassAB")
| @Name("classA")
| public class ClassA
| implements java.io.Serializable {
|
| @Id
| @GeneratedValue
| @Column (name = "Id")
| private int id;
|
| @Column (name = "Var1", nullable=false, length=3)
| @NotNull @Length(min=2, max=3)
| private String var1;
|
| @Embedded // <------- trouble maker
| private ClassE classEInst;
|
| @Basic
| private Double latitude;
|
| @Basic
| private Double longitude;
|
|
|
| public int getId() {
| return id;
| }
|
| protected void setId(int id) {
| this.id = id;
| }
|
|
| public String getVar1() {
| return var1;
| }
|
| public void setVar1(String var1) {
| this.var1 = var1;
| }
|
|
| public ClassE getClassEInst()
| {
| return classEInst;
| }
|
| public void setClassEInst(ClassE classEInst)
| {
| this.classEInst = classEInst;
| }
|
|
| public Double getLatitude() {
| return latitude;
| }
|
|
| public void setLatitude(Double latitude) {
| this.latitude = latitude;
| }
|
| public Double getLongitude() {
| return longitude;
| }
|
| public void setLongitude(Double longitude) {
| this.longitude = longitude;
| }
|
| public GeoPoint getLocation() {
| return new GeoPoint(latitude,longitude);
| }
|
|
| public String toString() {
| return var1;
| }
| }Please disregard the inheritance. You don't need to bother with it for this
issue.
ClassE just contains a single integer in this test case@Embeddable
| public class ClassE
| implements java.io.Serializable {
|
| private int classEVar;
|
|
| public ClassE() {
| }
|
|
| public ClassE(int classEContents) {
| this.classEVar = classEContents;
| }
|
| public int getClassEVar() {
| return classEVar;
| }
|
| public void setClassEVar(int classEVar) {
| this.classEVar = classEVar;
| }
The problem arises in a JSF page where I want to edit instances of entity bean ClassA
(classAEdit.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:o="http://www.optimizer.de/jsf"
| template="template.xhtml">
|
| <!-- content -->
| <ui:define name="content">
| <div class="section">
| <h1>Edit ClassA - Test</h1>
| <h:form>
| <fieldset>
| <o:classA-input classAInst="#{classASearch.selectedClassAInst}"
showId="#{false}" /> // <------------- (1)
| <div class="entry errors"><h:messages
globalOnly="true" /></div>
| <div class="entry">
| <div class="input">
| <h:commandButton value="Save"
action="#{classAEdit.update}" class="button"/>
| <h:commandButton value="Delete"
action="#{classAEdit.delete}" class="button"/>
| <s:link value="Cancel" action="classAList"
linkStyle="button" buttonClass="button"/>
| </div>
| </div>
| </fieldset>
| </h:form>
| </div>
| </ui:define>
| </ui:composition>
Take a look at (1).
tag classA-input is defined in a facelets tag lib (classA-input.xhtml)<!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:ui="http://java.sun.com/jsf/facelets"
|
xmlns:h="http://java.sun.com/jsf/html"
|
xmlns:f="http://java.sun.com/jsf/core"
|
xmlns:c="http://java.sun.com/jstl/core"
|
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
|
xmlns:s="http://jboss.com/products/seam/taglib"
| xmlns:o="http://www.optimizer.de/jsf">
| <ui:composition>
| <div class="entry">
| <div class="label"><h:outputLabel
for="id">ID:</h:outputLabel></div>
| <div class="output"><h:outputText
id="id">#{classAInst.id}</h:outputText></div>
| </div>
| <div class="entry">
| <div class="label"><h:outputLabel
for="classEInst">Class E Instance
(embedded):</h:outputLabel></div>
| <div class="input">
| <h:inputText id="classEInst"
value="#{classAInst.classEInst}" /><br/> //
<------------------ (2)
| <span class="errors"><h:message for="classEInst"
/></span>
| </div>
| </div>
| <div class="entry">
| <div class="label"><h:outputLabel
for="latitude">Latitude:</h:outputLabel></div>
| <div class="input">
| <h:inputText id="latitude" value="#{classAInst.latitude}"
/><br/>
| <span class="errors"><h:message for="latitude"
/></span>
| </div>
| </div>
| <div class="entry">
| <div class="label"><h:outputLabel
for="longitude">Longitude:</h:outputLabel></div>
| <div class="input">
| <h:inputText id="longitude" value="#{classAInst.longitude}"
/><br/>
| <span class="errors"><h:message for="longitude"
/></span>
| </div>
| </div>
| </ui:composition>
| </html>In (1) an input field with contents `{{classASearch.selectedClassAInst}
is created.
Here is the relevant part of classASearch: @Stateful
| @Name("classASearch")
| @Scope(ScopeType.SESSION)
| public class ClassASearchAction implements ClassASearch
| {
| @PersistenceContext
| private EntityManager em;
|
| private String searchString;
|
| @DataModel
| private List<ClassA> classAInstList;
| @DataModelSelection
| @Valid
| private ClassA selectedClassAInst; // <--------------------
| [...]
| }
The interesting part is that everything works fine if the ClassE instance is displayed in
(2). However, if you change the contents and want to save, you'll get an error -
apparingly from MyFaces:
/WEB-INF/facelets/tags/classA-input.xhtml @20,68
value="#{classAInst.classEInst}": Exception setting property classEInst of base
with class test.ClassB
[hint: classA-input.xhtml @20,68 is (2)]
Since the code works fine for Strings or - as you can see above - doubles, but fails with
embedded objects, I guess MyFaces is not compatible with @Embedded Objects created by
EJB3/Hibernate.
However, I don't know where to file the bug. Is MyFaces supposed to deal correctly
with an EJB3 embedded obejct? Or is Hibernate/EJB3 implementing the embedded object in a
strange way so that MyFaces can't deal correctly with the code? Or are JBoss and
MyFaces just not as compatible as they should be?
So is this a bug or a feature request? File a bug in the JBoss or in the Apache JIRA???
---
BTW, the problem seems to arise in PropertyResolverImpl.setValue(). In
http://myfaces.apache.org/impl/xref/org/apache/myfaces/el/PropertyResolve... you
can see the error is thrown in the catch (RuntimeException e) part in setValue().
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3958497#...
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&a...