[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