Spring form tags. Allow nulls in form:select (enum) - spring

I'm using Spring form tags for filling form with values.
I have form backing object:
public class FormInfo {
public enum Status {ON, OFF}
private Satus status;
//getter setter
...
}
And in JSP Status enum presented like this:
<form:form commandObject="formInfo " ...>
<form:select path="status">
<form:option value="null" label="Please select"/>
<form:options/>
</form:select>
</form:form>
All works fine, i.e. default message and enum values are presented in <select>.
But the status field is not required, so I want allow user to leave Status field unselected. But if form submitted without selecting status field, then I get error:
error in object 'formInfo' on field 'status': rejected value [null];
How I can set enum to null when no values is selected?
Please note I'm using JSR 303 validation. And error described above is not happens automatically, I get this error message manually from following method BindingResult#getFieldErrors().
This is my controller code:
public void myMethod(#Valid #ModelAttribute("formInfo") FormInfo sourcingDetail, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
log.error("Error during validation is occurred." + bindingResult.getFieldErrors().toString()); // <-- this is error message
}
...
}
Also please note, I didn't set any JSR-303 annotation (like #NotNull) on status field.
UPDATE:
Almost full error message which I get from calling this method BindingResult#getFieldErrors() (explained above):
Error during validation is occurred.[Field error in object 'formInfo'
on field 'status': rejected value [null];
...
[Failed to convert property value of type 'java.lang.String' to
required type 'com.my.project.model.Status' for property 'status';
nested exception is java.lang.IllegalStateException: Cannot convert
value of type [java.lang.String] to required type
[com.my.project.model.Status] for property 'status': no matching
editors or conversion strategy found],

Looks like you have the same problem as i!.
There is a method in the controller that serves as a hook where you could specify how to transform the String values, that came from the HTTP request, to a concrete object!.
The method is called initBinder, and there you attach the right behavior to do the conversion properly. I am still researching, but so far, looks good.
Take a look at this :
Form Values to be Null instead of "" in Spring
http://kaushalyas.blogspot.com.ar/2011/02/data-binding-in-spring-mvc.html
Hope it helps to found the solution!
Greetings
Victor.

Related

problem with the payload when saving a record

when I try to add\change the value of a custom lookup and then save it, I get this error:
Exception Message: Error identified in Payload provided by the user for Entity :'', For more information on this error please follow this help link https://go.microsoft.com/fwlink/?linkid=2195293 ----> InnerException : Microsoft.OData.ODataException: An undeclared property 'ey_org_unit_hr_id' which only has property annotations in the payload but no property value was found in the payload. In OData, only declared navigation properties and declared named streams can be represented as properties without values.
at Microsoft.OData.JsonLight.ODataJsonLightResourceDeserializer.ReadUndeclaredProperty(IODataJsonLightReaderResourceState resourceState, String propertyName, Boolean propertyWithValue)
at Microsoft.OData.JsonLight.ODataJsonLightResourceDeserializer.ReadPropertyWithoutValue(IODataJsonLightReaderResourceState resourceState, String propertyName)
at Microsoft.OData.JsonLight.ODataJsonLightResourceDeserializer.<>c__DisplayClass9_0.<ReadResourceContent>b__0(PropertyParsingResult propertyParsingResult, String propertyName)
at Microsoft.OData.JsonLight.ODataJsonLightDeserializer.ProcessProperty(PropertyAndAnnotationCollector propertyAndAnnotationCollector, Func`2 readPropertyAnnotationValue, Action`2 handleProperty)
at Microsoft.OData.JsonLight.ODataJsonLightResourceDeserializer.ReadResourceContent(IODataJsonLightReaderResourceState resourceState)
at Microsoft.OData.JsonLight.ODataJsonLightReader.StartReadingResource()
at Microsoft.OData.JsonLight.ODataJsonLightReader.ReadResourceSetItemStart(PropertyAndAnnotationCollector propertyAndAnnotationCollector, SelectedPropertiesNode selectedProperties)
at Microsoft.OData.JsonLight.ODataJsonLightReader.ReadAtStartImplementationSynchronously(PropertyAndAnnotationCollector propertyAndAnnotationCollector)
at Microsoft.OData.ODataReaderCore.ReadImplementation()
at Microsoft.OData.ODataReaderCore.InterceptException[T](Func`1 action)
at System.Web.OData.Formatter.Deserialization.ODataReaderExtensions.ReadResourceOrResourceSet(ODataReader reader)
at System.Web.OData.Formatter.Deserialization.ODataResourceDeserializer.Read(ODataMessageReader messageReader, Type type, ODataDeserializerContext readContext)
at System.Web.OData.Formatter.ODataMediaTypeFormatter.ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger).
ErrorCode: -2147185383
HexErrorCode: 0x80048d19
the field's logical and schema name is "ey_org_unit_hr_id" (both of them are identical).
I opened the post request that the form sends and this is what I found:
{"ey_org_unit_hr_id#odata.bind":"/ey_businessunits(91293b20-afb7-e611-bec8-0050568c00dc)",
"ey_org_unit_hr_id#OData.Community.Display.V1.FormattedValue":null,
"ey_s_name":"test555",
"ey_b_is_doctor_house":false,
"ey_b_is_route_service_requests":false,
"ey_b_real_branch":false,
"statuscode":1,
"statecode":0}
then I opened the metadata and found out that the NavigationalProperty Name of this field is different than what is used in the post request (ey_org_unit_hr_id is used in the request but the navigational property name is ey_ey_businessunit_ey_branch_hr which is also the name of the relationship).
Photo of the navigation property name
so i tried to send a post request using postman whith the currect NavigationProperty Name and it worked without an error.
Here is the request:
{"ey_ey_businessunit_ey_branch_hr#odata.bind":"/ey_businessunits(91293b20-afb7-e611-bec8-0050568c00dc)",
"ey_ey_businessunit_ey_branch_hr#OData.Community.Display.V1.FormattedValue":null,
"ey_s_name":"test555",
"ey_b_is_doctor_house":false,
"ey_b_is_route_service_requests":false,
"ey_b_real_branch":false,
"statuscode":1,
"statecode":0}
I thought about changing the navigational property name to what is used in the original post request but I don't know if I can change the metadata.
Try this property name: _ey_org_unit_hr_id_value.
You should check your error code at the below link.
https://learn.microsoft.com/en-us/power-apps/developer/data-platform/reference/web-service-error-codes
AFAIK, the 0x80048d19 code will be exposed by sending request with invalid data.
In my case, I got this error code when i sent request without header "Content-Type: application/json"
I hope this can be helpful to you

Springboot - validating enum

I have an enum that I am validating like this:
#EnumValueValidator(enumClass = MyEnum.class)
String value
It's a string field, but it is validated against a list of enums. However, once the validation is completed, and I know the field is valid, I want the getter to return the enum.
So I added a getter like this
public MyEnum getValue()
return MyEnum.valueOf(value)
The problem is if the value is not one of the valid enum types, the validation doesn't issue the proper error message, because it gets an exception calling the getter on the invalid type. I don't want the validation to use the getter. It should use the field directly. The getter() should only be used by explicit calls in the business logic. Is there a way to do this?

Why does #GetMapping method return request param while sending response?

I get request params as POJO and do nothing in method but in jsp shows parameter which I get from request.Why does method return my object?
Additionally, when I use primitive type or String, It doesn't return object and works perfectly
Controller
#GetMapping("/ULD_details")
public String ULD_detailGet(ActionError ID){
return "ULD_detail";
JSP
<tr>
<td >ULD id</td>
<td>${actionError.ID}</td>
</tr>
Link
http://localhost:8080/UCM-controller/ULD_details?ID=1145
It doesn't return your object. It returns the String "ULD_detail", which is the name of the view to execute.
This view is executed, and finds an actionError bean in the request attributes (i.e. in the model), because the Spring documentation about handler methods arguments says:
Any other argument
If a method argument is not matched to any of the above, by default it is resolved as an #RequestParam if it is a simple type, as determined by BeanUtils#isSimpleProperty, or as an #ModelAttribute otherwise.
And the documentation of ModelAttribute says:
The default model attribute name is inferred from the declared attribute type (i.e. the method parameter type or method return type), based on the non-qualified class name: e.g. "orderAddress" for class "mypackage.OrderAddress"

Basic MVC nullable char validation

I have the following in one of my view models:
public char? MyChar { get; set }
I noticed there appears to be no client-side validation on the textbox for MyChar, and it's possible for a user to submit a string that is too long for this char to my controller (it simply doesn't bind and remains null).
So, I added the [MaxLength] annotation. Client-side validation now works as expected, but when I submit a valid value to the server, I get the following exception in my event logs:
Exception information:
Exception type: InvalidCastException
Exception message: Unable to cast object of type 'System.Char' to type 'System.Array'.
at System.ComponentModel.DataAnnotations.MaxLengthAttribute.IsValid(Object value)
How can I validate the max length of a char correctly both client-side and server-side?
What I've Tried
For now, I've created my own MaxLength attribute for it to work with char types, but it feels like a heavy approach.

Play Framework: automatic validation of controller methods applied?

I have some issue with validation of parameters passed to a controller method.
Following the suggestion from the tutorial, I am using the same controller method for "save" and "create new" of an entity. See example in
http://www.playframework.org/documentation/1.2.4/guide9
So, my controller method looks like:
public static void saveEntity(long l, Long itemId,
#Required(message="error.shouldspecifyname") String name,
#Required(message="error.shouldspecifycategory") String category)
If 'itemId' is not part of the data sent via an HTTP request - it is supposed to be set to 'null'.
Unfortunately, it seems like "Play" is automatically adding a validation error on the "missing" parameter.
When looking into the validation errors' list, every time 'itemId' is 'null' - I am getting an error Incorrect value for field itemId
Is it a documented behavior? Any way to override it, or "get rid" of the error.
I am handling the errors simply using redirection, like:
if(validation.hasErrors() )
{
validation.keep();
showSomePage();
}
So the errors are displayed "out of the context" they get generated. This is the reason the "automatic" error bothers me.
Thanks for any hint.
Most likely it fails to validate itemId because it's declared as Long, are you sure you have "Long" there ant not just "long"? We are using validation with controllers every where and it works with #Required and passed "null" to "Long" values.
Worst case you can remove error from validation object based on "itemId" key, also if you're using controller to save model object, you might want to use:
public static void saveEntity(#Required #Valid MyEntity entity) {
if(validation.hasErrors() ) {
validation.keep();
showSomePage();
}
entity.save();
}
It will automaticly hook your changes inside existing entity if you pass ID from page with:
<input type="hidden" name="myEntity.id" value="${myEntity.id}">

Resources