Results 1 to 10 of 10

Thread: Manual (Non-@GeneratedValue) Entity identifiers are excluded from the create.jspx

  1. #1
    Join Date
    Sep 2007
    Posts
    20

    Default Manual (Non-@GeneratedValue) Entity identifiers are excluded from the create.jspx

    By default Roo excludes the entity @Id fields from the create.jspx and update.jspx views. While expected for the automatically generated identifiers this behavior seems incomplete for the ‘manually’ managed ids (e.g. without @GeneratedValue annotation).

    The following example illustrates the issue:
    1. New entity with string identifier (myId) and single string attribute (firstName)
    Code:
    entity --class ~.domain.Person --identifierField myId --identifierType java.lang.String
    field string --fieldName firstName
    2. From STS move the myId attribute (with the annotations) from the Person_Roo_Entity.aj to the Person.java, add getter/setter for it and remove the @GeneratedValue(..) annotation.
    Roo detects the change and removes the myId from the Person_Roo_Entity.aj

    The myId attribute inside the Person class looks like:
    Code:
        @Id    
        @Column(name = "myId")    
        private String myId;
    3. Create a scaffold controller for the Person:
    Code:
    controller scaffold --entity ~.domain.Person --class ~.web.PersonController
    The result crete/update jspx views include only the 'firstName' attribute and if you try to save the object an exception is thrown due to uninitialized myId field.

    Is there a way to make the controller command aware of the 'manual' semantics of the identifier?

    My Dev Environment:
    --------------------------------------------
    Roo :1.0.1.RELEASE [rev 601]
    STS : 2.3.0.RELEASE [Build Id: 200912171331]
    Java :build 1.6.0_16-b01

  2. #2
    Join Date
    Mar 2008
    Location
    Sydney, AU
    Posts
    974

    Default

    Roo manages identifiers for you in the most intuitive way. I am not sure if it is a good ideas to let users manage identifiers themselves as there is obviously a lot of room for uniqueness problems. But I agree in the odd case it might make sense. So the solution is to customize the generated code to fit your needs.

    Another (maybe more elegant solution) is to let Roo manage the identifiers and simply have another field which looks like an id but it is actually not. For example you could make sure that the Roo maintained identifier is given a different name (like 'myId') and then create a field called 'id' which will appear in your forms. Just an idea.

    HTH,
    Stefan
    Stefan Schmidt
    Software Engineer, Spring Roo
    SpringSource - a division of VMware
    twitter @schmidtstefan

  3. #3
    Join Date
    Sep 2007
    Posts
    20

    Default

    Thanks for the ideas Stefan,

    I decided to stick with the "customized views" approach.

    It does not feel natural to have two unique identifiers for the same entity: one as a business key and another as database Id. Actually I used the second approach to generate the views and then "unified" the Ids and disabled controller's automatically maintained views.

    Cheers, Chris

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

    Default

    It's a very old ORM problem.

    ORM providers tend to recommend identifiers are totally synthetic and have no business meaning, making their display on a UI generally unnecessary. Indeed often great lengths are gone to to hide the ID, as it reveals an internal of the system and allows guessing at how many records there are, manual changing of the identifier to see other records etc.

    On the other hand data architects tend to prefer identifiers have real business meaning. They make everything as immutable as possible and composite primary keys are the norm. Many ORM-like solutions don't handle this or do so with lots of extra hoops (even JPA requires writing custom Serializable identifiers to represent the composite primary key). So more work for a developer, but a better model from a strictly relational perspective (which in some way should be the priority given the database is likely to outlive the application by a few decades anyway and have lots of applications using it).

    Of course in the present era of noSql DBs, identifiers have again switched to having business meaning. That's because noSql DBs often want naturally sorted records so they can tackle range queries and partitioning more effectively, so totally synthetic identifiers are again a problem.

    Then we have offline operation and document databases, which almost always use UUIDs extensively. That's because partitioning is a problem to be managed some other way (eg use a sharding model) and you need to use UUIDs. Of course then we try to do UUIDs in a browser, which is a nightmare of unreliability, so then the server has to give our UUIDs so they have a semblance of proper UUID randomness and form.

    I guess to conclude it's non-trivial and there are many schools of thought. With Roo I just went with sequential identifiers by default as most people are backing to a relational DB. I've often seen a compromise where a surrogate primary key is used and that's the sequence or UUID, but the real primary key remains a composite primary key but JPA is configured to simply treat those as read-only fields. Remember as Roo just uses JPA you are free to write your own identifiers at any time and add them to the .java file, and Roo will recognise this. The web tier is designed to work with numeric keys, though.
    Ben Alex
    Project Founder, Spring UAA, Spring Roo and Spring Security

  5. #5
    Join Date
    May 2006
    Location
    Madrid
    Posts
    382

    Default

    It's a common problem, indeed.

    In some environments, people in charge of some application business want to assign unique meaningful codes manually and they want the database be aware of not repeating these values.

    It should be elegant to have a hidden numeric identifier, but it comes out two issues:

    1.- Sometimes these persons have direct knowledge of the underlying existing technology (database tables, for instance) and want to take the decisions (regardless the lack of their technical knowledge)

    2.- Sometimes, and this is the most common situation, the underlying database already exists when you come to develop a Java application. And there is no way (nor intention) to fix the absence of numerical identifiers.

    So, is it possible to tell Roo that we don't want it manages the identifiers? My request include the generated test files, because I need to avoid this kind of asserts in the code:

    org.junit.Assert.assertNull("Expected 'TableExample' identifier to be null", obj.getCode());

    (See public void testPersist() within the XXXTest_Roo_IntegrationTest class file)


    If you create a JIRA ticket, I will vote for it.

  6. #6

    Unhappy

    Quote Originally Posted by jbbarquero View Post
    So, is it possible to tell Roo that we don't want it manages the identifiers? My request include the generated test files, because I need to avoid this kind of asserts in the code:

    org.junit.Assert.assertNull("Expected 'TableExample' identifier to be null", obj.getCode());

    (See public void testPersist() within the XXXTest_Roo_IntegrationTest class file)
    When we have non-Roo managed Id or non-integral type Id like String, the integration tests generated are all failing. With most of the entities with such id Roo support for test generation becomes use less.
    Can this feature be added to test generation?

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

    Default

    You can stop Roo from generating an identifier by providing your own @Id field with associated accessor and mutator in the entity's .java file. Note that automated integration testing is only designed to automatically test mainstream entities with sequence-based keys. You can always delete (or never create) the integration test and data on demand .java files for entities that do comply with this requirement and write them by hand if you'd still like tests for that entity.
    Ben Alex
    Project Founder, Spring UAA, Spring Roo and Spring Security

  8. #8
    Join Date
    May 2006
    Location
    Madrid
    Posts
    382

    Default

    After doing what Ben has said, you can use Roo with all its features, as well.

    Let Roo creates the integration tests and you copy from the .aj files to the .java files all the test methods that you want to manage manually.

    Automatically, Roo will delete these methods from the .aj files, and you can safely modify them according your needs without Roo interfering

    For instance, you can provide a rando or fixed ID to the JPA object (just before the assert id is null)

    Code:
            org.junit.Assert.assertNull("Expected 'TableExample' identifier to be null", obj.getCode());
    
    //Try here:
    obj.getSode("Test_code");
    
            obj.persist();
    //...
    It worked for us.
    Last edited by jbbarquero; May 28th, 2010 at 06:47 AM.

  9. #9
    Join Date
    May 2006
    Location
    Madrid
    Posts
    382

    Default

    Please Ben, could you take in mind that the problem still remains?

    We can modify the jspx files, but since Roo is aware of them, it deletes all the changes that we make.

    Are you going to consider this in Roo? If not, I will create a JIRA Ticket for studying this issue.

    Regards.

  10. #10
    Join Date
    Jul 2010
    Posts
    1

    Default Maintaining jspx changes

    Quote Originally Posted by jbbarquero View Post
    We can modify the jspx files, but since Roo is aware of them, it deletes all the changes that we make.
    Regards.
    I tried the way of modifying the jspx file, and in order to maintain my changes in the jspx file, just need to change the respective Controller @RooWebScaffold automaticallyMaintainView entry from default value of "true" to "false".

    However the downside is any future changes in the jspx need to be manually maintained.

Posting Permissions

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