[jboss-user] [JBoss Seam] - Embeddable Objects (EJB3) not working properly
niesar
do-not-reply at jboss.com
Mon Jul 17 11:11:20 EDT 2006
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 at 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/PropertyResolverImpl.html 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#3958497
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3958497
More information about the jboss-user
mailing list