Results 1 to 9 of 9

Thread: Accessing entity IDs generically

  1. #1
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    667

    Question Accessing entity IDs generically

    I'm writing an abstract class that will be parameterised with a Roo entity type T. A method in my class needs access to that entity's ID. For example:

    Code:
    public abstract class EntityProcessor<T> {
        public void process(T entity) {
            Long id = entity.getId(); // compile error; T is an Object
        }
    }
    The problem is that Roo entities don't seem to implement any interface that has a "getId()" method.

    I can work around this by creating my own "Identified" interface with a "Long getId()" method, and applying that interface manually to all my Roo domain types, but I was wondering if there was a better solution, e.g. using some special generics trickery or an existing interface that has a getId() method.
    Andrew Swan
    "Now is the EJB of our discontent made glorious Spring"

  2. #2
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default

    Hi Andrew

    You have a few options:

    • Manually edit the .java file to extend a common superclass that declares the identifer you want, plus an accessor and mutator (ie no longer relying on Roo to generate the accessor/mutator for you, thus you can use the abstract type or make it implement an interface your remaining infrastructure will observe)
    • Create a Roo add-on that will operate on a @RooEntity trigger annotation and then cause it to generate an ITD that introduces a new interface to the type, such as "implements Identifiable<The_Serializable_Identifier_Type>" (you can invoke EntityMetadata.getIdentifierField().getFieldType() to determine what the identifier type is)
    • Manually write an ITD that performs the same function as the previous bullet point (although there's not much benefit of this option over simply editing the .java files)
    • Make your abstract class reflectively introspect the type in order to acquire its identifier accessor, which Roo and JPA will guarantee always is of Serializable type (with a simple cache you can avoid the relatively poor performance of reflection)
    • Log an enhancement request and we can modify the RooEntity add-on to implement some sort of common Identifiable type if the user creates the Identifiable interface (or more realistically uses a Roo command to create it)


    Lots of ways. :-)

    Cheers
    Ben
    Ben Alex
    Project Founder, Spring UAA, Spring Roo and Spring Security

  3. #3
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    667

    Question

    Thanks Ben. I think your last bullet will provide the most value for the most people in the long run. How about I log an improvement to the effect that every entity implements this interface:

    Code:
    public interface Versioned<T extends Serializable> extends Identified<T> {
        
        Integer getVersion();
    
    }
    Which extends this one:

    Code:
    public interface Identified<T extends Serializable> {
    
        T getId();
        
    }
    But what package should they go into? How about org.springframework.roo.addon.entity?
    Andrew Swan
    "Now is the EJB of our discontent made glorious Spring"

  4. #4
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default

    Hi Andrew

    Sounds good. The only consideration is the interface would need to be code-generated in the user's project. Placing the interface in a Roo-specific package would be incompatible with Roo only operating at development time and with no runtime classpath member. We could alternately get the interface added to Spring Framework, but I'm unsure if an interface of this nature would make a lot of sense. However I know the binding features would benefit from an identifier interface, so this might change in the future.

    Cheers
    Ben

    PS: You'll have to come over and have a beer with the Roo team sometime. We're in North Sydney.
    Ben Alex
    Project Founder, Spring UAA, Spring Roo and Spring Security

  5. #5
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    667

    Question More ideas and questions

    Hi Ben,

    I can see that these two new interfaces ought to be within the user's project. Here's my thoughts about how this could work (better to thrash these things out here than in JIRA, I reckon).

    Rather than create a new addon, enhance the existing "entity" addon to:

    1. automatically generate the Identified and Versioned interfaces in the project's base package* (if they don't already exist), and
    2. introduce the Versioned interface to all current and future entities via the existing Xxx_Roo_Entity ITD (which already introduces the id/version fields and their accessors, so this approach maintains high cohesion).

    Although this would be expanding the scope of what the entity addon does, I can't foresee people objecting to this because:

    1. All Roo entities already have a getId() method and a getVersion() method, so we're not requiring the entities to have any additional behaviour, we're just exposing that behaviour via an interface.
    2. The entities remain independent of any external frameworks or libraries (i.e. remain POJOs) as you said.

    The only thing I'm not clear on is whether Roo could handle the user moving or renaming either of the two new interfaces. Would Roo just regenerate them in the base package again?

    P.S. Beer sounds good! I'll PM you to set it up.
    Andrew Swan
    "Now is the EJB of our discontent made glorious Spring"

  6. #6
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default

    Hi Andrew

    I think it's pretty straight forward to make this totally transparent.

    We could just have a new command that produces an Identifiable or Versioned interface in the package that the user specifies. Mostly it will be the top level package (ie ~) but it could just as easily be specified elsewhere. The generated interface would have an @RooStereotype(RooTypes.IDENTIFIABLE) or @RooStereotype(RooTypes.VERSIONED). The addition of the @RooStereotype would therefore allow a user to manually define this on any type they wanted, plus move it freely to another location. The entity add-on would keep track of which type(s) contained this annotation and this would in turn cause generated entity ITDs to implement it. Roo's existing metadata dependency model would allow tracing of any file system deletion events (which is what is published if someone renames or moves an interface containing the annotation) and then the entity add-on would magically modify the ITDs that previously relied on the "deleted" interface.

    The only stumbling block I foresee (aside from the task of having to write it!) is if someone duplicated a particular @RooStereotype(RooType.SOME_TYPE) annotation in more than one file. We'd avoid that happening from the CLI by hiding the creation command once it detects a particular stereotype is already defined. But we can't stop the user doing it in the IDE. We therefore would need to console report an error. On second thoughts I suppose we could just have the ITDs implement as many interfaces as discovered. That's more in keeping with Roo's "I don't whine about errors needlessly if I can still do something sensible" philosophy.
    Ben Alex
    Project Founder, Spring UAA, Spring Roo and Spring Security

  7. #7
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    667

    Thumbs up

    Sounds good; I'll log it and put the link here.
    Andrew Swan
    "Now is the EJB of our discontent made glorious Spring"

  8. #8
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default

    Andrew, did you end up logging this in Jira?
    Ben Alex
    Project Founder, Spring UAA, Spring Roo and Spring Security

  9. #9
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    667

    Post

    Quote Originally Posted by Ben Alex View Post
    Andrew, did you end up logging this in Jira?
    Eventually! Please see ROO-1081.
    Andrew Swan
    "Now is the EJB of our discontent made glorious Spring"

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •