Announcement Announcement Module
Collapse
No announcement yet.
Teaching tricks to Roo Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Teaching tricks to Roo

    Hello,

    I wonder how can i do in -Roo terms- the following: My use case requires a custom entity non-numeric -String type-Id field that should be entered through the UI.

    I have no problem enabling the custom id as needed. However Roo automatically removes the the field -because is an Id, I guess- from UI code generation. Consequently it is not available in the jspx forms. i.e create and such.

    I hope I made my point clearly on it!

    Thx in advance
    jD

  • #2
    Don't call your own domain field "id"

    Can't you just give the field a Java name other than "id", for example "personId" or "pizzaId"? You can always change the field label to "Id" in the UI by editing src\main\webapp\WEB-INF\i18n\application.properties.

    Comment


    • #3
      Roo uses @Id annotation not the name

      Hello Andrew,

      It seems the name is irrelevant to Roo...
      Roo uses the @Id annotation to whether including or not for further UI code generation.

      At least it is what it looks like to me.

      Thx
      jD

      Comment


      • #4
        In that case I don't think I understood your original question. Maybe you could post some code showing what you are trying to do and what doesn't work?

        Comment


        • #5
          Just try to create entities for the two tables shown below using Roo:

          Thx for your help
          jD


          create table users(
          username varchar_ignorecase(50) not null primary key,
          password varchar_ignorecase(50) not null,
          enabled boolean not null);

          create table authorities (
          username varchar_ignorecase(50) not null,
          authority varchar_ignorecase(50) not null,
          constraint fk_authorities_users foreign key(username) references users(username));
          create unique index ix_auth_username on authorities (username,authority);

          Comment


          • #6
            If I understand correctly, you want the "username" column of the "users" table (i.e. the primary key) to be editable via the UI? That would be a highly unusual database design; hopefully you're at liberty to change it.

            Normally primary keys are generated by the database and not editable by (or visible to) the user. A better design would be:

            Code:
            create table users(
                  id int primary key,
                  username varchar_ignorecase(50) not null,
                  password varchar_ignorecase(50) not null,
                  enabled boolean not null);
            
            create table users_authorities (
                  id int primary key,
                  user_id int not null,
                  authority_id int not null);
            
            create table authorities (
                  id int primary key,
                  name varchar_ignorecase(50) not null);
            This keeps your primary key separate from your business key.

            I've left out the constraints and indexes for clarity, but you'd want them in real life. Also, I've added an id to all tables, as ids are always useful and they're hard to add later.

            I've also moved the authority names into a separate table for better normalisation.

            I hope this answers your question.

            Comment


            • #7
              I really appreciate the time and effort in answering my questions

              On the tables previously posted: They are coming from spring security 3.1x reference doc: http://static.springsource.org/sprin...rs_authorities.

              I truly believe they are correct -yours are good too and btw these are similar to the ones I am currently using for moving on with the issue-

              However, It would be great having Roo able to create entities replicating exactly such kind of tables. I am sure there are tons of legacy db out there as this one.
              What you think?

              Thx again
              jD

              Comment


              • #8
                The @Id field can never be editable

                Originally posted by delgad9 View Post
                On the tables previously posted: They are coming from spring security 3.1x reference doc: http://static.springsource.org/sprin...rs_authorities.
                Yes, but importantly, they don't share your requirement that the username be editable via the UI.

                Originally posted by delgad9 View Post
                However, It would be great having Roo able to create entities replicating exactly such kind of tables. I am sure there are tons of legacy db out there as this one.
                What you think?
                Now you're talking about reverse-engineering JPA entities from an existing database, which is the subject of ROO-435. But regardless of whether you do that or write your entities by hand, or even whether you're using Roo or Spring, the @Id field of a JPA entity can never be editable via the UI; it just doesn't make sense. For example, if a user with username = "bob" (which is also his primary key) edits his username to "bob2", how would the JPA provider know that it should update the existing "bob" row instead of inserting a new row with a PK of "bob2"?

                Comment


                • #9
                  Yes you can. I show how...

                  I pretty much agree with everything you previously posted but the part on "never make the @Id editable from the UI". Specially since, I am strong supporter of surrogate keys for web development. However, I am supporter of never-say-never as well.

                  Even though I could just end in a rhetorical development exercise.
                  I decided to move the ball a little further and complete the implementation of database model taken from spring security 3.1.0.; previously referred.
                  allowing the username field annotated with @Id and being editable from the UI.

                  RESULTS:
                  It was really easy to tweak the jspx forms:create, list, show, etc. for properly handing the @Id annotated field 'username' from the UI. Presentation sourcecode seemed ready for such thing.

                  Following, I am showing pieces of controller/entity code on making JPA to correctly decide when to insert vs. merge

                  First the entity part:
                  Code:
                  	@Transactional
                  	public User User.merge(String oldUsername) {
                  		if (this.entityManager == null)
                  			this.entityManager = entityManager();
                  		this.setUsername(oldUsername);
                  		User merged = this.entityManager.merge(this);
                  		this.entityManager.flush();
                  		return merged;
                  	}
                  
                  	@Transactional
                  	public User User.merge(String oldUsername, String newUsername) {
                  		User oldUser = this.entityManager.find(User.class, oldUsername);
                  		this.entityManager.remove(oldUser);
                  		this.entityManager.flush();
                  		User newUser = new User();
                  		newUser.setUsername(newUsername);
                  		newUser.setPassword(this.getPassword());
                  		newUser.setEnabled(this.getEnabled());
                  		User merged = this.entityManager.merge(newUser);
                  		this.entityManager.flush();
                  		return merged;
                  	}
                  Second: Controller part

                  Code:
                      @RequestMapping(method = RequestMethod.PUT)
                      public String UserController.update(@Valid User user, BindingResult result, ModelMap modelMap) {
                  .........................
                  .........................
                  ..........................
                  	 String inComing = user.getUsername();
                     	 int val = inComing.indexOf(',');
                     	 String newUsername = inComing.substring(0, val);
                     	 String oldUsername = inComing.substring(val+1, inComing.length());
                       if(newUsername.equals(oldUsername))   
                          user.merge(oldUsername);
                       else
                      	user.merge(oldUsername, newUsername);
                       
                          return "redirect:/users/" + user.getUsername();

                  Very cool experience. I'll save it. I have the feeling that I going to use it down the road.

                  Thx Roo People. Thx everybody
                  jD

                  Comment


                  • #10
                    And do you know what is going to happen if anything has a foreign key to username?

                    Comment


                    • #11
                      I do...

                      1) I fully agree that a surrogate-key implementation is the correct one; as the one posted by Andrews before. In fact my actual implementation of the entity model posted in the security 3.1 reference manual is this way.

                      2)As mentioned before this experiment was only a rhetorical development exercise for understanding better the details of the awesome tagx library coming with Roo and its flexibility.

                      3) As a Developer I can tell you that it is doable -however not practically or recommended- on taking care on the foreign key as well.

                      Thx
                      jD

                      Comment

                      Working...
                      X