Chariot Training Classes

Training Courses

I run Chariot's training and mentoring services. We provide training in AngularJS, HTML5, Spring, Hibernate, Maven, Scala, and more.

Chariot Education Services

Technology

Chariot Emerging Tech

Learn about upcoming technologies and trends from my colleagues at Chariot Solutions.

Resources

Chariot Conferences

Podcasts

« Didn't make it to Philly Emerging Tech? Watch the sessions online! | Main | Spring Roo in Action released! »
Sunday
May062012

Don't call names - Roo's Tag with a tag problem

Eureka, ish..

I was trying to find time to debug a problem that's been on my backlog for a while, and someone else ran into it. A reader over on the Manning Spring Roo in Action forum was getting hit with a 400 invalid request error when trying one of the samples from the book (the many-to-many example).

A while back, I ran into this problem - my m:m arrangement was between Courses and Tags, and the field name of the actual tag in the Tag entity was called 'tag'. When I did this, I got the same error. Someone hit it in the forums, we renamed it to 'name' and committed our code, and I forgot about it for a while.

My theory was that the type converters somehow were generated wrongly. Nope, I have a " target="_blank" class="offsite-link-inline">JUnit test to review that does it properly, so that's not the problem.

Actually, the problem is with the type conversion, but it's not the fault of the Roo code for type converters (to my knowledge so far). They are just doing what they are supposed to do.

The REAL Problem

First of all, my theory on the bad type converters was wrong. I proved it by writing a set of tests to make sure I a) understood the true workings of the generated type converters and b) that they worked. In the next edition of Roo in Action I think I need to devote some time to these. See the attached sample at the end to see my tests. Here is how they work (example - the tag):

Type Conversions

  • Convert an object -> a single line String representation as a default label for a given dropdown entry. (converterFactory.getTagToStringConverter())
  • Hydrate a Tag via a String representation of the key (converterFactory.getStringToTagConverter())
  • Hydrate a Tag via a primary key value (converterFactory.getIdToTagConverter())

All of these work just fine when tested individually, which they should.

The Tag to String converter is used in dropdowns for the many-to-many relationship, so that when the tag editing screen (which owns the relationship) allows a user to select one or more courses, it just shows the field values separated by spaces.

So, now what?

Spring MVC creates forms with a set of assumptions, including the fact that the form will be of a certain bean instance root. This is provided by specifying the modelAttribute in Spring MVC, but since Roo does this for us, we aren't in charge of that in a scaffolded UI.

Here is the create.jspx file for reference.

The scaffolded value is generated by create.tagx, which uses this code:

<form:form action="${form_url}" method="POST"
   modelAttribute="${modelAttribute}" enctype="${enctype}" 
   onsubmit="${jsCall}"> ...

The essential problem I think we're running into with the samples the way they are put together is:

  • The "bean context" / model attribute name of the form being submitted is expected to be 'tag'
  • The form is submitting fields in this form with names such as description, id, and also tag
  • Spring MVC is spitting nails on the fact that you have tag.tag in your request. It wants to convert the nested tag into another Tag object, by hydrating it (probably to support recursive relationships or something). Well, it takes your String for the tag label and tries to take it through idToTagConverter() which fails on a numeric parse.

How to fix For now, avoid using the entity name as a field name in a given entity. I need to do more extensive testing to see why this is happening. This is something that I should know by heart, I guess, but I've been wrestling with other areas of Java and Roo and haven't been as connected to the web forms as I used to be.

If anyone wants to take this on, I have posted the code sample in the original Manning thread (look on the second page) with the junit tests included. Just create a course, then create a tag with the 'tag' field of any alpha value.

[b]The sample test[/b]

I created a spring junit test to check my assumptions (I imported hamcrest-all for matching support to make the assertions readable quickly, the pom includes org.hamcrest:hamcrest-all:1.1).

PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments (1)

I can confirm your suggestion to rename the "tag" member of Tag to something else like "name" worked. Good grief these kinds of bugs are driving me nuts trying to get a handle on Spring MVC!

September 12, 2012 | Unregistered CommenterJeffH

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>