How to make the best DTO request class? - java

I need to make a DTO class that represents a JSON request body.
I’d like to make it fully immutable with final fields. I’ve already seen implementations based on #JSONCreator all args constructor but I also require one more feature.
The DTO class should be flexible and tolerate some missing fields in a request meanwhile ensure that all necessary properties are in-place.
Could you provide me an example of such DTO, please?

Jackson will automatically handle missing fields and just set those fields to null.
It also has some configuration options on whether when serializing responses, null fields should be omitted or set to the special value null.
objectMapper.setSerializationInclusion(Include.NON_NULL);
On another note, if you are designing an API, you might want to look at Swagger / OpenAPI and define your API declaratively from there (you can specify whether a field is optional or required). Then use the codegen tools to automaticlly generate your DTOs. (They will follow the best patterns and also offer Fluent API style setters).

As #jbx pointed out that Jackson automatically handles missing fields and sets it to null.
If you want to ensure that required fields are populated, you need to mark those as #javax.annotation.Nonnull or lombok.NonNull.
Using this Jackson throws a NullPointerException if that field in null while de-serialization of request to DTO class.

Related

Does adding redundant #JsonProperty value annotations to fields increase deserialization performance?

I'm using Jackson (2.6.0) to deserialize JSON requests into simple POJOs. I have implemented all the setter methods in my POJOs to fine tune the assignment. Some of the field names in the JSON are rather cryptic, such as seq. I'd like to name my java class field something like layoutSequnce.
I'm aware to do this I simply need to annotate my field as:
#JsonProperty("seq")
private int layoutSequence;
My question is for JSON fields I do not needto rename, such as title, is there any minimal performance advantage to annotating it anyway as:
#JsonProperty("title")
private String title;
My question stems from my understanding of how I think Jackson works behind the scenes. I'm assuming Jackson uses reflection to introspectively examine my POJO and identify the current field it's attempting to assign from the JSON value. With this approach, I'm assuming it has to do some searching to find a match, which has some small amount of overhead.
If I specify the field name directly, will Jackson just blindly attempt to initialize my field using a setter that matches the pattern of the field name (setTitle() in this example) I've identified in the annotation? Or does it still perform an internal class search to validate the method's existence?
No, it should not improve performance. Introspection is only done once, to build the JsonDeserializer, and never after this initial time.
Annotation introspection (or even just general field, method introspection) is rather expensive operation, and so serializers/deserializers are aggressively cached to avoid having to do it more than once.
The only case where lookups would need to be repeated are when constructing a new ObjectMapper, that is, when not reusing/sharing small numbers (ideally one) of mappers.
ObjectReaders are different in that there is very little overhead, as they share cached deserializers with ObjectMapper that created them, so there is no need to reuse them. But mappers need to be reused.

Swagger with Spring-MVC and custom serializers

I am trying to use Swagger to document a Spring-MVC based REST-API and am having problems getting Swagger to reflect the use of custom serializers and deserializers.
Because the JSON must conform to an established format (which is not particularly well designed) and I wanted to have a properly designed API model in the Java classes, I have used a few custom implementations of JsonSerializer to generate the JSON output. When I enable Swagger with annotations in the Spring-MVC controllers, the generated documentation ignores the custom serializers and describes the model as if it had been serialized with the default Jackson settings. So far so good, I didn't really expect Swagger to automatically understand the implementation of the serializers.
What I however would expect (and I can't find anything about this in the Swagger documentation) is a way to use Swagger annotations on the relevant attributes in the model classes to manually describe the model. Am I missing something or is it really not possible to Swagger as a documentation tool in connection with custom serializers (or deserializers for that matter)?
Edit: The Swagger documentation is not particularly good, but I have already tried to work with #ApiModelProperty on the deviating properties. As far as I can see, it has absolutely no effect on the generated output (tested with Swagger-SpringMVC 0.8.5 and 0.9.5).
You can use model substitutes for e.g. Lets say you have a service
#RequestMapping(value = { "/some-resource" }, method = POST,
consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<Void>
businessTypeEcho(#RequestBody CustomSerializableResource business) {
return new CustomSerializableResource();
}
you can setup a type substitution rule that tells springmvc how to represent the custom serializable type in the swagger ui.
#Bean //Don't forget the #Bean annotation
public SwaggerSpringMvcPlugin customImplementation(){
return new SwaggerSpringMvcPlugin(this.springSwaggerConfig)
.apiInfo(apiInfo())
.directModelSubstitute(CustomSerializableResource.class, SubstitutedSerializableResource.class)
.includePatterns(".*pet.*");
}
class SubstitutedSerializableResource {
//getters and setters that describe what
//CustomSerializableResource should look like in the UI
}
Unfortunately, this is going to create a parallel universe of types that aren't used at runtime.
Update:
If I understand your comment correctly, you're using it to format system-wide types i.e. booleans to Y/N or dates to mm/dd/yyyy perhaps. IMO, what you're probably looking for is to use model substitutes (see example above).
Substitute Date with String (this is the prescriptive guidance) In the case of dates your only option to communicate the format expected unfortunately is only via a textual description of the particular field or property.
Substitute Boolean with a enum you can create i.e. YesNoEnum that represents how you expect the objects to be serialized. This will provide the documentation with a set of allowed values.
At the end of the day, its a trade-off between creating these meta classes just for documentation vs. standardizing the API models to use serialization primitives as much as possible.

Required field in model

Before I was using Python NDB API and there was required attribute which I can set on properties. I can't find anything similar in Objectify documentation. How to do that with Objectify?
You may want to use the standard java bean validation framework for this:
http://beanvalidation.org/
It seems that objectify has no such functionality, where you would require user to set a value of field.
You can however prevent saving of fields with null value: #IgnoreSave(IfNull.class). (you can use any of the [If][2] subclasses: IfDefault, IfEmpty, IfEmptyString, IfFalse, etc..)

How to use reflection to retrieve private variable property from JPA objects

One of my goals is to create an engine that will set values in pojo object from JPA objects dynamically using reflection. One of the matching criteria is, that the field names should match.
I was successfully able to implement this for two pojo objects. But when I tried using JPA objects as one of the object parameter, it didn't work. Based on my research I found out that the method Class.getDeclaredFields() , does not give me the name of the field but the getter/setter method name of member variable for JPA objects.
Can anyone please give me a lead or direction as in where/what should I look to accomplish this task?
JPA providers will often use dynamic proxy classes of your concrete JPA classes, so you have no guarantee of the field names in the proxy. The only guarantee about a proxy is that the methods are the same. Use a debugger to inspect the runtime class of the JPA class instances that you're trying to use and you'll see the problem.
The best you'll be able to do is use reflection to call methods on JPA-returned objects.
All that aside, I don't really see why you'd need to POJO-ify an entity class anyway, since an entity is primarily an annotated... POJO.
One of the matching criteria is, that the field names should match.
I think that this is the root of your problem. There is simply no guarantee that a Java object's field names will match the names of getters and setters ... or anything else. If you make this assumption, you will run into cases where is doesn't work.
The best solution is to simply not use this approach. Make it a requirement that the Pojo classes conform to the JavaBeans spec and rely on the setters to set the properties. This is likely to work more often than making assumptions about (private) field names.
In fact, the state of a generic JPA object implemented using a dynamic proxies could well be held in a hash map. Those fields you can see could simply be constants used for something else.

Extra/dupe members in SOAP response prevents serialization (Axis, Java, Gson)

I am using Axis to call a SOAP-based web service. I'm then trying to serialize the returned remote object as JSON, using the Google Gson library.
The serialization to JSON fails, with Gson complaining that "there are multiple elements with the name __equalsCalc()).
When I inspect the returned object in my IDE (Eclipse), I can see that this is true -- the returned object has three members called __equalsCalc() and another three called __hashCode.
I know from looking around that these are added by WSDL2Java (I think) in order to avoid recursion. My question is, why are there THREE of each? And how can I get the serializer to ignore these? They're not actually part of the object's definition (it's called a RemoteProject, for reference). Can I do something hackish like cast the RemoteProject to a RemoteProject to get it to drop those members?
This turns out to be not too hard to solve. I have multiple copies of the same instance var because the class being serialized is shadowing fields of the same name from superclasses. Since I don't care about these fields, the best approach in Gson is to write a custom ExckusionStrategy which can selectively ignore fields based on their name:
http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/ExclusionStrategy.html
I don't know GSon.
With Jackson, you can annotate properties (i.e - fields that have getters/setters according to Java bean convention) with #JsonIgnore.
This way you can prevent issues like recursion/no matching setter or getter and so on...
Try to find out if you have the same at GSon or use Jackson.

Categories