1 2 Previous Next 15 Replies Latest reply on Jul 19, 2006 11:51 AM by niesar

    Embeddable Objects (EJB3) not working properly

      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/PropertyResolverImpl.html you can see the error is thrown in the catch (RuntimeException e) part in setValue().

        • 1. Re: Embeddable Objects (EJB3) not working properly
          gavin.king

          You need a JSF converter.

          • 2. Re: Embeddable Objects (EJB3) not working properly

             

            "gavin.king@jboss.com" wrote:
            You need a JSF converter.

            Are you sure, Gavin?

            I'm far from being a JSF master, but I don't see yet how to do that. My problem is the input side rather than the output/display side.

            Consider ClassE (the embedded Object) containing more than one instance variable (which is a bit closer to my real world problem). Let's say ClassE has 2 instance variables like
            int classEVar1
            String classEVar2 // <-- new

            The conversion from the ClassE object to Strings seems to be quite straightforward. I could pass the ClassE instance to 2 different converters, one to convert classEVar1 to a String and another one to convert (extract) classEVar2. Quite inconvenient since I need 2 converters, but that can be done.

            However, I don't know how to deal with the input fields since 2 different input fields are comprising a single ClassE instance. You know, if I follow the approach with the 2 different converters from above, they will produce 2 different ClassE objects, one containing classEVar1 and another one classEVar2. That won't work.

            Hence it looks like I need a converter which is able to handle multiple input Strings and produces a single ClassE Object. Is that possible at all?

            • 3. Re: Embeddable Objects (EJB3) not working properly
              pmuir

               

              public ClassE getClassEInst() {
               return classEInst;
              }

              <h:inputText id="classEInst" value="#{classAInst.classEInst}" />


              An inputText takes a value of type String, or, a value that has been converted to/from String NOT an embeddable EJB3 bean. So, either reference specific fields on the embeddable object:

              <h:inputText id="classEInst" value="#{classAInst.classEInst.classEVar}" /


              or, as Gavin said, provide a converter for ClassE to be set via a input string.

              • 4. Re: Embeddable Objects (EJB3) not working properly
                gavin.king

                 

                "niesar" wrote:
                "gavin.king@jboss.com" wrote:
                You need a JSF converter.

                Are you sure, Gavin?

                ...

                The conversion from the ClassE object to Strings seems to be quite straightforward. I could pass the ClassE instance to 2 different converters, one to convert classEVar1 to a String and another one to convert (extract) classEVar2. Quite inconvenient since I need 2 converters, but that can be done.


                You don't need a custom converter for primitive values because JSF has a set of builtin converters. But if you need JSF to convert a string value to an instance of a user class then of course you need to tell JSF how to do that.

                • 5. Re: Embeddable Objects (EJB3) not working properly

                  Thanks for your answers, guys. I appreciate that!

                  Maybe I have to make the following point much more clear:

                  I can't access instance variables from my (embedded) ClassE instance like

                  <h:inputText id="classEInst" value="#{classAInst.classEInst.classEVar}" >

                  When I try to populate the input fields with a construction like that, I immediately get an error message.
                  javax.faces.el.PropertyNotFoundException: /WEB-INF/facelets/tags/classA-input.xhtml @20,79 value="#{classAInst.classEInst.classEVar}": Bean: test.ClassE, property: classEVar
                   at com.sun.facelets.el.LegacyValueBinding.getValue(LegacyValueBinding.java:58)
                   at javax.faces.component.UIOutput.getValue(UIOutput.java:77)
                   at org.apache.myfaces.shared_impl.renderkit.RendererUtils.getStringValue(RendererUtils.java:217)
                   at org.apache.myfaces.shared_impl.renderkit.html.HtmlTextRendererBase.renderInput(HtmlTextRendererBase.java:135)
                   at org.apache.myfaces.shared_impl.renderkit.html.HtmlTextRendererBase.encodeEnd(HtmlTextRendererBase.java:53)
                  ...

                  Please note, that this error occurrs much earlier than everything we were talking about before. With this approach I'm not even able to display the data and I don't even get to the point to input anything.

                  In fact, that is what I considered a bug or an incompatibility in my first post. In my understanding #{classAInst.classEInst.classEVar} should also work if ClassE is embedded in ClassA using the EJB3 @Embeddable/@Embedded annotation. However, this doesn't work!


                  It looks like I can't access any instance variable from my embedded ClassE object. The only workaround I could find is to pass the complete ClassE object like
                  <h:inputText id="classEInst" value="#{classAInst.classEInst}" >

                  But that causes the problem that I have the restriction 1object <---> 1String for the JSF converter. This way it's also no option.

                  So right now I have no clue how to solve this problem.


                  • 6. Re: Embeddable Objects (EJB3) not working properly
                    pmuir

                     

                    "niesar" wrote:

                    <h:inputText id="classEInst" value="#{classAInst.classEInst.classEVar}" >



                    This is most definitely should work. Doesn't matter to JSF EL whether it's Embedded or not. Having looked at your code I can't see why it doesn't I'm afraid. Perhaps Class is a keyword in JSF EL, have you tried using another name? Does accessing classAInst.classEInst.classEVar work if you put an inputText for it in classAEdit.xhtml rather than the tag source file?

                    The only workaround I could find is to pass the complete ClassE object like
                    <h:inputText id="classEInst" value="#{classAInst.classEInst}" >

                    But that causes the problem that I have the restriction 1object <---> 1String for the JSF converter. This way it's also no option.


                    This is not the right way to access properties of an object.

                    • 7. Re: Embeddable Objects (EJB3) not working properly
                      gavin.king

                      Note that none of these questions have anything to do with Seam. Now, I don't mind if you discuss your JSF problems here. But if you are going to talk about bugs and use italics and exclamation points and multiple question marks, please consider taking this to the correct place which would be the MyFaces forum.

                      OTOH, if you wish to continue this discussion here, that is fine by me, but please lay off of the "bug or incompatibility" talk. Thanks.

                      • 8. Re: Embeddable Objects (EJB3) not working properly

                        Gavin,

                        please don't feel offended! My intention is far away to come anyway close to that point. Sorry about that!!! (Well, actually I'm feeling a bit offended now)

                        You know, my original question was which part of this combination of JBoss AS/EJB3/Seam/JSF/MyFaces is actually causing the problem - and where to file the bug. Please don't get me wrong. That is definitely not supposed to be an offense at all. I simply don't know if I can definitely say that this is a MyFaces issue. So I'm raising the question here since Seam/JBoss AS comes bundled with all this stuff and it looks like I'm supposed to use it. That's the simple reason I start the discussion here. You know, if it turns out it's a MyFaces issue, I'll take the discussion over there - and I'll try to tell people over here that there's a problem they could run into. Isn't that the way it should be?

                        Now, since I already spent days with this problem and a lot of time to boil my real world problem down to it's essence, I just didn't want to live with a strange workaround and leave the problem as it is. That won't help anybody! Actually, reporting these kind of problems is a bit my way to pay back a little to open source projects where I'm not involved myself. I think that's a lot better than just walking away. Offending anybody is not my business.

                        So I'm asking again: Where exactly is the problem?

                        1. possibility:
                        MyFaces problem since it should be able to deal correctly with the EJB3 stuff Hibernate/EJB3 is producing? You know, I wasn't so confident any more when I decompiled the ClassA.class file (ClassE is embedded in ClassA). At least the decompiler gives some strange output telling me something about a reference to ClassE in a way I never saw before. But since this decompiler is quite old, it surely knows nothing about EJB3 or even EJB. However, it seems that ClassA.class doesn't look like standard Java meta code from a few years back any more. Anyway, I don't know if there is a strict definition how the meta code has to look like when EJB3 @Embeddable/@Embedded is used. In case this is well defined, it could be that EJB3/Hibernate is producing some code which is only working in the JBoss world or MyFaces can't handle a well defined case.

                        2. possibility:
                        MyFaces may not even be supposed to handle this kind of code. In that case there is the incompatibility I was talking about before and Hibernate/EJB3 and MyFaces simply don't fit. But since I only use MyFaces because it's kind of built in here, I can only guess that all the EJB3 stuff should work in MyFaces.

                        3. possibility:
                        I'm doing something wrong and my code is a piece of shit. Well, that can easily be. But as I said, I spent more than the complete weekend on this issue and now I think I simplified the test case so far, that I'm pretty convinced there is an issue with the @Embeddable/@Embedded stuff. You know, if I'm using a workaround and don't use @Embeddable/@Embedded, everything works fine. However, that's no option for my real world stuff. But never mind.

                        So - without offending anybody, please - where do you think is the problem?
                        Is this definitely a MyFaces issue? Is there nobody else using @Embeddable/@Embedded in combination with Seam/JSF? I'm not ready to believe this yet, since I thought that is common practice - at least if legacy databases must be used.
                        And no, I don't ask any more where to file the bug. That seems to be a question which is by far too dangerous ;)))

                        • 9. Re: Embeddable Objects (EJB3) not working properly
                          gavin.king

                          What I can absolutely definitively promise you is that this has nothing to do with @Embedded/@Embeddable.

                          • 10. Re: Embeddable Objects (EJB3) not working properly
                            pmuir

                             

                            "niesar" wrote:
                            Is this definitely a MyFaces issue? Is there nobody else using @Embeddable/@Embedded in combination with Seam/JSF?


                            In order

                            1) No, the issue is most likely with your code. Having you tried cleaning and rebuilding from scratch.

                            2) Yes, I do, and it works exactly as I would expect it to for me. For example, I have a Client object, which has an Address object getter/setter. The Address has a (String) address getter/setter and (String) postcode getter/setter. I can access them as

                            #{client.address.address}

                            or
                            #{client.address.postcode}


                            Whether the object has any EJB3/JPA annotations is irrelevant.

                            If you are still stuck perhaps put your runnable test case up somewhere and I can look at it.

                            • 11. Re: Embeddable Objects (EJB3) not working properly

                               

                              "gavin.king@jboss.com" wrote:
                              What I can absolutely definitively promise you is that this has nothing to do with @Embedded/@Embeddable.

                              Thanks again for your comment, Gavin!!!

                              Wow, if you even promise the embedded objects are working properly in combination with MyFaces, I'll take that as granted (and especially if you're saying "absolutely definitely" - wow!). So I'll throw in more time to find out what's wrong with my code. No idea yet, since I thought I just tried about everything, but we'll see...

                              My honest apologies again for causing a bad mood. Looks like using "???", "!!!", and italics is my way to emphasize a point (and actually I wasn't aware this looks strange these days). Sorry about that!

                              • 12. Re: Embeddable Objects (EJB3) not working properly

                                Hi, petemuir!

                                thanks a lot for taking a second look at my problem. I really appreciate that!!!

                                "petemuir" wrote:
                                1) No, the issue is most likely with your code. Having you tried cleaning and rebuilding from scratch.

                                Well, I kind of started from scratch. However. my real worls starting point was kind of complicated. So I had to reduce complexity step by step and finally ended in the ClassA/ClassE test case I showed you before.

                                "petemuir" wrote:
                                2) Yes, I do, and it works exactly as I would expect it to for me.

                                This backs Gavin's promise. I'm absolutely convinced now I'm doing something wrong...

                                "petemuir" wrote:

                                If you are still stuck perhaps put your runnable test case up somewhere and I can look at it.

                                That's extremely nice! Thank's a lot!!!
                                If you don't mind - let me come home first (I'm more or less on the other side of the planet by now and don't have the test code with me). If I can't solve the issue I will happily send you my code.

                                Thanks a lot for this offer, petemuir!!!

                                • 13. Re: Embeddable Objects (EJB3) not working properly
                                  jboss-nth-fan

                                   

                                  "gavin.king@jboss.com" wrote:
                                  Note that none of these questions have anything to do with Seam. Now, I don't mind if you discuss your JSF problems here. But if you are going to talk about bugs and use italics and exclamation points and multiple question marks, please consider taking this to the correct place which would be the MyFaces forum.

                                  OTOH, if you wish to continue this discussion here, that is fine by me, but please lay off of the "bug or incompatibility" talk. Thanks.


                                  Hi Gavin,

                                  Here is a twist to the topic:
                                  I've came to appreciate the power and strengths of JSF, and I really love the way Seam takes over in the places where JSF really needed some help.
                                  (s:Link with actions, nicely formated exception stack trace, pages.xml, etc etc)

                                  Now from having seen colleagues to struggle with JSF somewhat non-obvious ways of doing things (or presenting errors, misconfig, etc..)

                                  Wouldn't this be another case where seam can improve things?
                                  It looks to me like some sort of "auto-converter" could alliviate the need to look into JSF non-friendly details.

                                  Just my $0.02

                                  Yeyo

                                  • 14. Re: Embeddable Objects (EJB3) not working properly

                                    Nth-Fan, maybe the SeamGen utility would be something you'd be interested in.

                                    http://wiki.jboss.org/wiki/Wiki.jsp?page=JBossSEAMGen

                                    Although, talk about this and other issues are off topic for the thread. If you have questions about the SeamGen util, ask them in this topic.

                                    http://www.jboss.com/index.html?module=bb&op=viewtopic&t=86876

                                    1 2 Previous Next