6 Replies Latest reply on Jun 21, 2002 10:12 PM by java_etc

    How to Represent Mixed Collections of Entities

    ryanramage

      First of all I want to state that JBoss rocks!

      Anyway, on to my question. I am writting a small app to test out the CMR featues of EJB 2.0. I try to think of my data model first in terms of UML class diagrams and then try to map it to EJBs. For the most part this is working good, but I have run into a little problem that I dont know how to map to CMR EJBs. Consider this:

      1) One CD has many tracks.
      2) A track may be music, a movie, a document, etc...and these are distinct enough to merrit their own object.

      In UML I would make a 'Track' interface that the classes 'Music', 'Movie', 'Document' all extend and then the 'CD' class would have a collection of 'Tracks'. At runtime you could then just cast to the class you want.

      My question is, how do I represent this problem with EJBs using CMR? Can this be done? Is this a bad idea?

      I have thought about writing a base EJB called 'TrackBean' and then extending it with 'MusicBean', 'MovieBean', etc... But then how do I deal with the Local and Remote interfaces? Would they just extend 'Track' and 'TrackLocal'?

      I guess the other (worse) idea is to write a 'TrackBean' and then have a bi-directional one-to-one relationship with a 'MusicBean' and 'MovieBean'. I really dont like this because a 'TrackBean' should not have to know about the different types of tracks, but I still want to be able to go from a Collection of Track Beans to their specific type of track.


      If anyone has come across this (I am sure it is common), could you please pass on your design pattern? Can it be done using CMR?




        • 1. Re: How to Represent Mixed Collections of Entities

          Wouldn't you want an object model something like this?


          interface Track {

          public String getName();
          public int getNumber();
          public Data getDate();

          }

          interface Data{
          int getId();
          }

          interface Music extends Data{
          Group getArtist();
          }

          interface Movie extends Data{
          Person getDirector();
          }

          interface Document extends Data{
          Collection getAuthors();
          }


          • 2. Re: How to Represent Mixed Collections of Entities
            ryanramage

            That would work, but that is not a very clean model. The Track interface should not have the methods in it like getName() and getData() because it should not have to know about the different sub-classes. If I added a new type of track called a Image track, I would have to change the Track interface itself.

            This is how I would represent the model (not using EJBs).

            class CD {
            private Track[] tracks; // we could use a Collection, but lets type it for the example.
            }

            // sorry in my problem I said interface, but I am going to actually make it a class
            class Track {
            private int trackID;
            }

            // I *should* call this class eightTrack =)
            class MusicTrack extends Track {
            Group getGroup();
            }

            class MovieTrack extends Track {
            String getMovieName();
            String getDirector();
            }


            My question is not really how do I model this in UML or in the _traditional_ java, but how would I turn these classes into Entity Beans that follow this pattern?



            • 3. Re: How to Represent Mixed Collections of Entities
              janjanke

              Hallo,

              I have the same kind of design problems right now. A clean inheritance like with normal classes does not seem possible with entity beans because of the home interface and the primary keys. I am going to tell you something about my approach:

              I also started modelling the complete application using UML class diagrams and I heavily used inheritance. Because I was not able to find an appropriate solutions to keep this structure in my EJB components, I decided to use the entity beans only for persistence. There won't be any business methods. The next layer - after the entity beans layer - will be a layer of normal Java classes that exactly represent the class structure I originally modelled. There are some rules for this classes: All persistent fields are replaced by getter/setter methods which directly fetch/set the value from the underlying entity beans layer. All classes that are not on the lowest inheritance level are declared as abstract and their fields are represented by abstract getter and setter methods. All lowest level classes will map to exactly one entity bean. This entity bean my have a large number of different relationships to other beans because it inherits all upper class associations. The distribution of primary keys is controlled by an external service class (to keep them unique across a number of entity beans belonging to the same class hierarchy). Entity beans instances are created using the normal classe's constructor and they are retrieved using estatic finder methods within the logic classes. A session bean could now perform some business workflow by using the logic classes. It would profit from polymorphism and can work with normal classes without even knowing that they are backed by entity beans. Nevertheless this approach has to be developed very carefully. It seems to tend to programming errors because of the design rules for the business logic classes.

              Sincerely,
              Jan

              • 4. Re: How to Represent Mixed Collections of Entities
                paulward

                There's a little pain involved if you wish to persist a heirarchy of objects into a single table using CMP 2.0.

                I would do as you suggest and have a Track interface with implementing classes of Music, Movie, Document, etc.

                I would then create a TrackInfoBean cmp entity that contains all of the fields you plan on having in the table.

                TrackInfoBean would have methods:

                public Track getTrack();
                public void setTrack(Track track);

                These methods would handle the mapping of polymorphic data to/from the entity fields.

                • 5. Re: How to Represent Mixed Collections of Entities
                  timdeboer

                  My 2c...

                  I might be missing the boat here but i would think regardless of any common interface the these document, music etc objects have, they would still be best persisted in 3 seperate tables each with a foreign key back to the cd table.

                  You then have the following three objects and 3 tables at the persistence level (actually maybe 4 tables... I'd probably slip a table between document etc and cd_compilation to ensure integrity of cd_compilation_order) ...

                  class Document implements CDTrack{
                  public String getName(){}
                  public int getRunningTime(){}
                  public String getDocumentAuthor(){}
                  }

                  class MusicTrack implements CDTrack{
                  public String getName(){}
                  public int getRunningTime(){}
                  public String getComposer(){}
                  }

                  class AVITrack implements CDTrack{
                  public String getName(){}
                  public int getRunningTime(){}
                  public String getProducer(){}
                  public String getDirector(){}
                  }

                  create or replace table document(
                  id number,
                  cd_compilation_id number,
                  cd_compilation_order number,
                  name varchar2(100),
                  running_time number,
                  author
                  )

                  create or replace table music_track(
                  id number,
                  cd_compilation_id number,
                  cd_compilation_order number,
                  name varchar2(100),
                  running_time number,
                  composer
                  )

                  create or replace table avi_track(
                  id number,
                  cd_compilation_id number,
                  cd_compilation_order number,
                  name varchar2(100),
                  running_time number,
                  director varchar2(100),
                  producer varchar2(100)
                  )

                  and the CDTrack interface at the business level. I actually like wrapping any publicly available persistence in a business layer - or any persistence that starts doing "fancy stuff" - but then again i'm just a bit of a prude! Ideally i'd wrap the above classes with interfaces at the business layer which could then implement the CDTrack interface..

                  Interface CDTrack{
                  public String getName();
                  public int getRunningTime();
                  }

                  The CDCompilation class (at the bus layer of course!) could then have a

                  CDTrack[] getTracks

                  method returning all the tracks which would perform the more complex operation of retrieving the appropriate records from each table and combining them to form the CDTrack array.

                  Hope this helps/makes sense??!

                  • 6. Re: How to Represent Mixed Collections of Entities
                    java_etc

                    I may be oversimplifying, but I remember reading the IBM J2EE guidelines that stated if you retrieve >5 E-EJBs at one time, then just use the Session EJB without E-EJBs.

                    How about a simple Session-EJB JDBC query, that puts all the info into an array of DOs (VOs)?

                    VOs may or may not be the parent classes for the E-EJBs, so that becomes the "Entity Inherits VO Strategy" of the VO pattern, otherwise, it is just a plain business-layer Session Facade pattern.