Spring DataBinder equivalent for Json - java

I am currently working on a web project which is using Play Framework 2.1.0. Play supports a decent API for parsing form data and mapping that to the Model beans directly. Which looks something like,
Form<Employee> form = Form.form(Employee.class).bindFromRequest();
if (form.hasErrors()) {
return badRequest(template.render(form));
}
This API also does validations on the fly and is capable of handling binding failures, when say a String could not be converted to an Integer. The Form API keeps the collection of errors mapped to the name of the property. Underlying the Form API, Play is using DataBinder of Spring's validation framework which is actually doing all the magic.
I was wondering if there is similar binding API to convert from JSON to the bean directly, with support for handling binding failures?
Play 2.0 uses Jackson internally which fails when there are binding failures and simply throws an exception. I looked at the code and does not look easy to supress these errors.
Is there some framework that can satisfy my requirement out of the box?
Essentially, I need the framework to convert from JSON to Java Bean, which can handle binding failures gracefully.
It would be wonderful if it allows me to collect them somewhere so I can generate appropriate validation errors. I will run custom validations on the parsed object using javax.validation APIs to perform more specific validations once the JSON is parsed into the Bean.

I achieved this by adding custom deserializers in Jackson
SimpleDeserializers deserializers = new SimpleDeserializers();
deserializers.addDeserializer(Integer.class, new MyIntegerDeserializer(null));
deserializers.addDeserializer(Long.class, new MyLongDeserializer(null));
ObjectMapper mapper = new ObjectMapper().setDeserializerProvider(
new StdDeserializerProvider().withAdditionalDeserializers(deserializers));
MyModel value = mapper.treeToValue(node, MyModel.class);
MyIntegerDeserializer and MyLongDeserializer are custom deserializers for Integer and Long values respectively. These are in my case exact copy of the internal default corresponding deserializer classes with additional code to gracefully handle NumberFormatException

Related

Spring boot able to accept Enum as Request parameter

So, I got into this new Spring Boot project which was already under developement and while writing API's I used Enum for #RequestParam in my controller and it worked.
I did not write any converters for this.
Later on I noticed that in this project the other developers had written custom Converter's for this.
So I decided to search the web regarding this and all solutions that came up for using Enum with Controller in Spring Boot used converter, could not find any examples without converter like how I did.
Below is one an example of how I wrote this, LoanStatus is an Enum:
#RequestMapping(value = "/loans", method = RequestMethod.GET)
public ResponseEntity<?> getPatientsLoan(HttpServletRequest request,
#RequestParam(value = "loanStatus", required = false) LoanStatus loanStatus) {}
So is this a relatively new feature that Spring Boot accepts Enums now without the need for converter's and that is why all the examples used converters or will I face some issue in feature cause I did not user converter's even though it is currently working for me?
Spring has supported String to Enum conversion since Spring 3.0. There is a ConverterFactory which dynamically creates a converter for the specific enum.
Prior to that you would need to write a custom Converter or PropertyEditor to convert enums. But basicallly with the current versions you don't need to if the String matches the Enum name.
If you want custom enum conversion (by some internal value or whatever) you still would need a custom converter.

Vertx model binding for my Rest API layer

I'm using Vertx 3, and I'm trying to find a good decoupled module that knows to turn query-string, headers and both content-type and body into a bean?
I know spring does that and various other frameworks as well, but I don't want to introduce a new framework i just want a super fast model binder that will either know to auto bind to a certain method or at least auto bind a certain class so i can invoke my rest method that currently accept one parameter, which is the model.
public ResponseBase query(QueryRequest model){ ... }
I don't mind adding annotations to the parameters etc.
Thanks!
Current my team use vertx Json.decodeValue to turn body (json string) to java class.
MyClass body = Json.decodeValue(rc.getBodyAsString(), MyClass.class);
to config Json to handle unknown properties, I setting
Json.mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
for your query string, I think it is easy to write a class to convert it to a json string :)
I also catch DecodeException on Json.decodeValue to re throw a 400 Bad Request error.

Jackson and Hibernate Validator

Are there any online tutorial available to use Hibernate validator with Jackson for validating JSON?
I am using Spring and Jackson now for JSON parsing.
With Spring, I use MappingJacksonHttpMessageConverter to automatically translate the incoming JSON payload to Java object.
I would like to add validator annotations to the Java class. For example, if I have the Person class with "name" as one of the fields, I like to validate the JSON payload if the "name" element appears 1 time. If it appears more than 1 time in the payload, then I like the validator to kick in to reject the request.
Right now what I observed is that if there are multiple names in the payload, Jackson simply ignores and picks up the last one.
The Java object is not bound to any XML schema and the like.
What is the best practice for validating JSON?
Spring has JSR-303 support built in, see this chapter in the reference manual.
If you are using Spring MVC, see here, you should just be able to annotate parameters to #RequestMapping methods with #Valid.

How to handle in spring validation of json request / bean if the json cannot be converted to the bean?

I have classic Spring MVC application.
I want to validate a Form using a corresponding Java Bean, annotated with JSR-303 validation annotation.
The form data is sent by an ajax call using JSON. This Json is converted to the target Java Bean with Jackson - automatically by spring:
#RequestMapping(value = ControllerConstants.CALCULATION_MAPPING_SUBMIT_FORM,method = RequestMethod.POST)
public String submitForm(#Valid #RequestBody MyFormBean bean, final BindingResult result) {
...
}
Problem is for example if I have an Integer field in my bean but, in JSON the values is not a number. In this case it cannot create the target bean, that cannot be validated. This situation cannot be solved with custom property editors, since there is no way to convert a a text that not represents an Integer to Integer.
It seems that this is solved in Grails, we get errors from validator (errors is domain object) which has to be created during the data binding. So I assume spring supports this, thus Grails just uses Spring's support)
So how to elegantly solve this situation to handle this "validation" error?
UPDATE
Actually I figured out, that is this is supported by spring if we use simple form submit. The problem is with integration of Jackson deserialized. It does not fills errors. Still how to solve this?
I see two options...
Have client side validation that would not allow the form to be submitted if the there are formatting issues.
On the server side you will have to have a mechanism of handling the exception that would catch it and report the problem back to client.
Hope that helps.
EDIT:
Well not having client side validations may not be a good user experience. Users do not want to be reminded about validation errors after they have made a server round trip. However, if this is still a constraint have a look at following url and it gives elegant way of handling such issues and reporting informative error messages.
http://www.mkyong.com/spring-mvc/spring-3-mvc-and-jsr303-valid-example/

Custom serialization of JDK5 Enum in Axis 1.2 on client-side

I am migrating a SOAP web service to JDK1.5.
I have took advantage of native java enums in the new code.
For some reasons, I'm stuck with Axis 1.2 and it does not natively support JDK5 "enums".
I have found a tutorial on how to implement custom a serialization / deserialization for java enums:
http://www.developpez.net/forums/d236564/java/developpement-web-java/web-services/utiliser-type-enum-jdk5-axis/ (in French).
I have been able to successfully register those custom serialization handlers on the server side via the use of "typeMapping" elements in the ".wsdd" file.
However, I can't figure out how to register the same classes on the client side, as I do not have a ".wssd" file here.
Any help would be appreciated.
Thanks,
Raphael
I have finally found how to manually register a custom type mapping.
I do it when creating an instance of a Service :
service = new Service();
// Get default type mapping
TypeMapping tmap = DefaultTypeMappingImpl.getSingletonDelegate();
// Register our custom serializer / deserializer
tmap.register(
MyCustomClass.class,
MyCustomClassQName,
new MyCustomSerizalizerFactory(),
new MyCustomDeserizalizerFactory());
// Add it back to the service
service.getTypeMappingRegistry().register(
"http://schemas.xmlsoap.org/soap/encoding/", // Default encoding
tmap);
I don't know whether it is the right way to do it, but it works !

Categories

Resources