View Full Version : Long fields in Command Class
irus
Mar 27th, 2007, 11:16 AM
Hi Forum,
I'm facing the following problem.
I've a field in database which is a BIGINT. According to Spring MVC in my Command class I don't need to declare this
as a String field and deal with the conversion logic. But When I declare this field as "long" or "Long" in CommandClass I have the following problem.
When user enters a non integer value in the field say "sdf" I get the following exception ....
Failed to convert property value of type [java.lang.String] to required type [java.lang.Long] for property correlationId; nested exception is java.lang.NumberFormatException: For input string: "sdf"
This is not the exception that I want to show on the screen. I want to show a simple message like
"Please enter a number in this field".
What is the recommended way of declaring fileds that are not Strings like int, long etc., in commandClass and deal with the exceptions ?
Marten Deinum
Mar 27th, 2007, 11:26 AM
Specify a MessageSource and put your messages in a properties file. You might want to read-up on the MessageSources in the reference guide, chapter 3.8.1 (http://static.springframework.org/spring/docs/2.0.x/reference/beans.html#context-functionality-messagesource) is the one you want to read.
Also check the countries sample shipped with Spring, which uses a MessageSource to resolve messages and exceptions.
Also when such a bind exception occurs Spring generates a list of messagecodes which it uses to locate a custom message. Checkout the DefaultMessageCodesResolver (http://www.springframework.org/docs/api/org/springframework/validation/DefaultMessageCodesResolver.html) for the generated Message codes.
Steve O
Mar 27th, 2007, 11:36 AM
That issue should be caught in the validator and a message sent to the UI.
The sample apps have great examples of this action.
Steve O
Marten Deinum
Mar 27th, 2007, 11:45 AM
You don't even get to the validator.... Spring cannot bind and thus there is nothing to validate.
irus
Mar 27th, 2007, 01:50 PM
It is true that we don't even get to the validator. Which is where my question is! should I declare the BIGINT property as String in my command Class? apparently this can be avoided as per the reading below? I'm also using validation.xml and validation-rules.xml whrere in I have the message "key" for the error. The "key" resolves to a message in the messageResources.properties.
My question is what is the standard recommendation in this case? the following is from spring documentation chapter 13 2nd paragraph (http://static.springframework.org/spring/docs/2.0.x/reference/mvc.html).
"Spring Web MVC allows you to use any object as a command or form object - there is no need to implement a framework-specific interface or base class. Spring's data binding is highly flexible: for example, it treats type mismatches as validation errors that can be evaluated by the application, not as system errors. All this means that you don't need to duplicate your business objects' properties as simple, untyped strings in your form objects just to be able to handle invalid submissions, or to convert the Strings properly. Instead, it is often preferable to bind directly to your business objects. This is another major difference to Struts which is built around required base classes such as Action and ActionForm."
Marten Deinum
Mar 27th, 2007, 02:03 PM
My first post in this thread answers that... Have you read all the answers?
Also what is your problem now? Are you having doubts about having a Long/long in your commandObject instead of a String?
irus
Mar 27th, 2007, 02:50 PM
My question is about what the field should be declared as long/Long or String?
Also, Customization of error messages from properties file is something that I've done already. The Error message that I posted in the question
Failed to convert property value of type [java.lang.String] to required type [java.lang.Long] for property correlationId; nested exception is java.lang.NumberFormatException: For input string: "sdf"
is automatically generated by Spring framework. So it is not under my control to configure it! My question is not about how to implement internationalization using messageResources.properties. Are you telling that I can configure this error message too?
leonardoborges
Mar 27th, 2007, 03:01 PM
I think you'd have to do some javascript to prevent the user from entering anything but numbers.
Or, you could implement a PropertyEditor to return null if the user entered a text instead of a number. That way, in the validator, you could check if there is a valid value or not.
irus
Mar 27th, 2007, 03:07 PM
Thanks I got that.
I have declared the field as a String in the Command object, in that way spring will populate the field with whatever the value user entered and then apply FieldChecks.validateLong() validator on the field so if the user enters text it is caught!
Marten Deinum
Mar 27th, 2007, 03:21 PM
is automatically generated by Spring framework. So it is not under my control to configure it! My question is not about how to implement internationalization using messageResources.properties. Are you telling that I can configure this error message too?
Well yes I'm telling you that... The message you see is the default message if no other message can be found. That is what I answered in my first post, which you obviously ignored to read closely.
Also when such a bind exception occurs Spring generates a list of messagecodes which it uses to locate a custom message. Checkout the DefaultMessageCodesResolver for the generated Message codes.
When you have long in your class and you enter 'sdf' for instance Spring fails to convert that to a valid number. 4 errorcodes will be generated and used for trying to resolve a message. IN your case that would be
1. typeMismatch.command.correlationId
2. typeMismatch.correlationId
3. typeMismatch.long or typeMismatch.java.lang.Long when it isn't a primitive
4. typeMismatch
Spring tries to resolve the most specific one at first and the least specific as last.
pmularien
Mar 27th, 2007, 03:26 PM
So it is not under my control to configure it! My question is not about how to implement internationalization using messageResources.properties. Are you telling that I can configure this error message too?
Yes, that's exactly what he was telling you. The Javadoc Marten pointed you at, for DefaultMessageCodesResolver, in fact has the list of resourcebundle entries right in it.
For example, in case of code "typeMismatch", object name "user", field "age":
1. try "typeMismatch.user.age"
2. try "typeMismatch.age"
3. try "typeMismatch.int"
4. try "typeMismatch"So in your case, you could define in your resource bundle "typeMismatch.long=Please enter a number", or be more or less specific.
As for your point that these messages are thrown before validation, this is true, but that's just the way the bind/validation process works - and you are still allowed to customize this behavior by appropriate subclassing and/or usage of property editors if you so choose.
irus
Mar 27th, 2007, 06:02 PM
Thanks Deinum,
This was very helpful. I'm now able to declare the properties as Long and configure the error messages too!
peet
May 26th, 2007, 04:56 PM
Hi everyone-
This thread has been very helpful, but I'm still not quite getting success with using the properties file to configure field-specific error messages. (I'm very close, but not quite...)
I can configure a general message for typeMismatch, but if instead I try to do anything more specific than that, such as typeMismatch.java.lang.Integer, I get the default (long) error message.
With this .properties file:
# Default error messages for general types
typeMismatch=One of the fields has invalid input.
typeMismatch.java.lang.Integer=Please enter an integer value.
When I submit invalid input for an Integer field, I get the error message you'd expect:
"One of the fields has invalid input."
But when I comment out the first line like so:
# Default error messages for general types
#typeMismatch=One of the fields has invalid input.
typeMismatch.java.lang.Integer=Please enter an integer value.
I get the default error message:
Failed to convert property value of type [java.lang.String] to required type
[java.lang.Integer] for property group.groupLevel; nested exception is
java.lang.NumberFormatException: For input string: "asdf"
That message would seem to indicate that the messageCodesResolver is looking for a message for java.lang.Integer when resolving for group.groupLevel, but so far no go.
I have also tried:
typeMismatch.int=Please enter an integer value.
just for fun, and:
typeMismatch.group.groupLevel=Group Level must be an integer.
with no success. FYI, the groupLevel property of the group object is indeed declared as:
private Integer groupLevel;
Any thoughts anyone? I'm sure I'm just missing something dumb, but so far I can't see it.
Thanks!
-p
Marten Deinum
May 29th, 2007, 07:45 AM
Is the typeMismatch code generated by Spring or are you declaring it yourself in a validator?
peet
Jun 19th, 2007, 04:12 AM
Is the typeMismatch code generated by Spring or are you declaring it yourself in a validator?
Here's where my inexperience with Spring comes out. I'm not entirely sure I'm answering the right question, but I'm not using a Spring validator with this controller, so I guess the answer is that Spring is generating the typeMismatch code (though I'm not sure where & how this happens).
As I understand though, since it fails during binding, we wouldn't get to the validation step anyway?
-p
Oh, and sorry for replying so slowly. It would seem that my account here is not notifying me of replies to threads by default. Gotta go look into that...
pmularien
Jun 21st, 2007, 10:47 AM
typeMismatch.java.lang.Integer=Please enter an integer value.
This has worked fine in the past for me. You should look at / set a breakpoint in DefaultMessageCodesResolver.resolveMessageCodes to see what messages Spring is trying to use to resolve your error. The Javadoc for this class is also quite detailed in describing the exact sequence of codes that Spring uses for error reporting purposes.
peet
Jun 21st, 2007, 12:26 PM
This has worked fine in the past for me. You should look at / set a breakpoint in DefaultMessageCodesResolver.resolveMessageCodes to see what messages Spring is trying to use to resolve your error. The Javadoc for this class is also quite detailed in describing the exact sequence of codes that Spring uses for error reporting purposes.
Thanks, I'll give that a try.
As you say, I did find the javadoc to be quite informative; now if I can just figure out why I'm not getting the expected behavior, I'll be all set :D
-p
peet
Jun 24th, 2007, 10:46 PM
Hi pmularien-
It turns out that my mistake was up in the view layer. Out of lack of familiarity with the DefaultMessageSourceResolvable and related classes, I had accidentally bypassed the mechanism by which Spring chooses the most specific of the available messages.
My template (Freemarker) was getting the message code directly from DefaultMessageSourceResolvable.getCode(), which just uses the last one in the list, i.e. the most general.
Thanks for the help...
-p
pmularien
Jun 25th, 2007, 07:15 AM
Glad to hear you got it working! :)
vBulletin® v3.7.3, Copyright ©2000-2008, Jelsoft Enterprises Ltd.