I have two APIs referencing the POJO class below.
class Data{
private String name;
private String age;
private String address;
private String phone_number;
}
I need to annotate the fields in this POJO as below.
class Data
{
#JsonProperty(required = true)
private String name; // required field
#JsonProperty(required = true)
private String age; // required field
#JsonInclude( Include.Non_Null)
private String address; // optional field
#JsonIgnore
private String phone_number; // ignore field
}
The annotations need to be applied to only one of API.The other API should not be impacted by this change.
One way of achieving this is to create two separate POJOs, one for each API. But is it possible to achieve the results using the same POJO classes? Is there a way to configure the annotations based on which API is being invoked?
Some repetition is not bad especially if they're used for two different purposes.
Ideally these would be in two different packages as well. That way, you don't have a name clash.
If you want to avoid but I do not recommend it is have
class RequiredData extends Data {
#JsonProperty(required = true)
void setName(String name) {
super.setName(name);
}
}
The annotations need to be applied to only one of API.The other API
should not be impacted by this change.
One way of achieving this is to create two separate POJOs, one for
each API. But is it possible to achieve the results using the same
POJO classes? Is there a way to configure the annotations based on
which API is being invoked?
You can create a library containing the classes that two APIs to have to share and introduce it in both APIs as a dependency.
That would allow to ensure both parts of your System will have the same definition of these domain classes.
Note: you need to have a strong reason for doing so. Because there was a reason to implement them as independent APIs and introducing this dependency creates a coupling between them. If there would be a considerable amount of such classes, then as a consequence APIs would not be able to evolve independently.
Related
I have, say, a class Person which, depending on the endpoint, would have its firstName either required or not. Is there a way of doing this with Swagger OpenAPI documentation tags in Java?
I'm imagining it could look a bit like this if it were/is possible:
public class Person {
#Path("/endpoint1", required = true)
#Path("/endpoint2", required = false)
private String firstName;
}
You'll need two classes - one where the firstName property is required, and another one where it's optional. To reduce code duplication, you can define a base class that contains all properties except for firstName and inherit the other two Person classes from this base class.
Is there any approach to convert entity to dto object partially? Or are there any best practices for using the entity, pojo/dto and response object in MVC pattern?
You have couple of approaches. I assume you have a web project.
Manual mapping approach. Create Dto map it manually to your entity. This would involve all the boilerplate code around it - Builders, all argument Constructor, getters, setters whatever approach you will use to populate the DTO.
The different hydration Technics apply in different situations. Builder pattern presumes you would have an immutable objects. Getters and Setters are supported out opf the box by frameworks as Jackson. You may decide to minimize your boilerplate code by using lombok, imutables or other frameworks.
Mapping framework. Another option would be to use a supplied mapper like ObjectMapper, or FastMap there may be other choices. This would remove large portion of manual mapping you would need to establish following aproach 1.
Deserializer. Example of such aproach would be spring-data-rest where your repository returns the entities straight which are than serialized in JSON . Using normal spring MVC this would be to return your entity straight to your controller layer and based on annotations or other means (serializers) map it to your network format JSON, XML whatever you use.
These are the different options. Which one is best depends on your usecase.
One of possible approaches is copy constructor. The example below.
// entity annotations ...
public class EntityExample {
private Long id;
private String name;
private Integer score;
// getters and setters ...
}
public class DtoExample {
private Long id;
pricate String name;
// For serialization and deserialization
public DtoExample() {
}
public DtoExample(EntityExample entity) {
this.id = entity.getId();
this.name = entity.getName();
}
// getters and setters ...
}
I am developing a RESTful API in Spring Boot 2+, for which I need to perform several validations. Nothing really fancy, just the typical #NotNull, #NotEmpty, #Max, #Min, #Email, #Regex, #Future, etc stuff...
Except that I have beans from an API that I must use yet cannot modify. This means that I cannot annotate the fields and methods in those DTOs.
It would be great if I could create mixin-like classes or interfaces with the same structure of the real DTOs I must use in the API, on which I would happily place bean-validation's annotations.
For example, if I had the following DTOs that I couldn't modify:
public class Person {
private String name;
private String dateOfBirth;
private Address address;
// constructors, getters and setters ommited
}
public class Address {
private String street;
private String number;
private String zipCode;
// constructors, getters and setters ommited
}
I would create the following 2 interfaces that mimic their structure and annotate them as I need:
public interface PersonMixin {
#NotBlank String name();
#Past String dateOfBirth();
#Valid #NotNull Address address();
}
public interface AddressMixin {
#NotBlank String street();
#Positive int number();
#NotBlank String zipCode(); // Or maybe a custom validator
}
As you see, the name of the methods in the interfaces match the names of the properties of the bean classes. This is just one possible convention...
Then, ideally, somewhere while the app is loading (typically some #Configuration bean) I would be very happy to do something along the lines of:
ValidationMixinsSetup.addMixinFor(Person.class, PersonMixin.class);
ValidationMixinsSetup.addMixinFor(Address.class, AddressMixin.class);
Except that ValidationMixinsSetup.addMixinFor is pure fantasy, i.e. it doesn't exist.
I know that there exists a similar construct for Jackson regarding JSON serialization/deserialization. I've found it extremely useful many times.
Now, I've been looking at both Spring and Hibernate Validator's source code. But it's not a piece of cake... I've dug into ValidatorFactory, LocalValidatorFactoryBean, TraversableResolver implementations, but I haven't been able to even start a proof-of-concept. Could anyone shed some light into this? I.e. not how to implement the whole functionality, but just how and where to start. I'm after some hints regarding which are the essential classes or interfaces to extend and/or implement, which methods to override, etc.
EDIT 1: Maybe this approach is not the best one. If you think there's a better approach please let me know.
EDIT 2: As to this approach being overly complicated, too convoluted, Rube Goldberg, etc, I appreciate and respect these points of view, but I'm not asking whether validation through mixins is good or bad, convenient or inconvenient, neither why it might be like so. Validation through mixins has pros on its own and I think it could be a good approach for some valid use cases, i.e. having declarative validation instead of scripted or programmatic validation while also separating validation from the model, letting the underlying framework do the actual validation job while I only specify the constraints, etc.
Using programmatic API (as mentioned in the comment) in case of Person you could apply next mappings for your constraints:
HibernateValidatorConfiguration config = Validation.byProvider( HibernateValidator.class ).configure();
ConstraintMapping mapping = config.createConstraintMapping();
mapping.type( Person.class )
.field( "name" )
.constraint( new NotNullDef() )
.field( "number" )
.constraint( new PositiveDef() )
.field( "address" )
.constraint( new NotNullDef() )
.valid();
Validator validator = config.addMapping( mapping )
.buildValidatorFactory()
.getValidator();
And as you are using Spring - you would need to do that in one of your sping config files where you define a validator bean.
I'm looking for a way to export some JPA entities to a REST API, but instead of sending the whole entity every time I want to share just some specific fields depending of the entry point. Here's a small example:
Say we have an Author class with few fields:
#Entity
public class Author implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = SEQUENCE)
private Long id;
#NotNull
#Size(min = 1, message = "{required.field}")
private String name;
#NotNull
#Size(min = 1, message = "{required.field}")
private String country;
private LocalDate birthDate;
// getters and setters
}
And say we have this REST service (just two methods):
#Path("authors")
public class AuthorREST {
#Inject
private AuthorBC bc;
#GET
#Produces("application/json")
public List<Author> find(#QueryParam("q") String query) throws Exception {
List<Author> result;
if (Strings.isEmpty(query)) {
result = bc.findAll();
} else {
result = bc.find(query);
}
return result;
}
#GET
#Path("{id}")
#Produces("application/json")
public Author load(#PathParam("id") Long id) throws Exception {
Author result = bc.load(id);
if (result == null) {
throw new NotFoundException();
}
return result;
}
}
Now, this way, I'll always have the 4 fields when my API is called.
I understand that if I use Jackson I can set an #JsonIgnore to fields I want to ignore, and they will always be ignored.
But what if I want that, in some cases, my whole entity is returned by one service, and in other service (or other method in the same service), only 2 or 3 fields are returned?
Is there a way to do it?
#JsonView and mix-in
You already know you can use annotations such as #JsonIgnore and #JsonIgnoreProperties to make Jackson ignore some properties.
You also could check the #JsonView annotation. For some details on how to use #JsonView with JAX-RS, have a look here.
If modifying the JPA entities is not an option, consider mix-in annotations as described in this answer.
Data Transfer Object
Data Transfer Object (DTO) is a pattern that was created with a very well defined purpose: transfer data to remote interfaces, just like webservices. This pattern fits very well in REST APIs and using DTOs you'll have more flexibility in the long run. You can have tailored classes for your needs, once the REST resource representations don't need to have the same attributes as the persistence objects.
To avoid boilerplate code, you can use mapping frameworks such as MapStruct to map your REST API DTOs from/to your persistence objects.
For details on the benefits of using DTOs, check the following answers:
Why you should use DTOs in your REST API
Using tailored classes of request and response
To give better names to your DTOs, check the following answer:
Giving meaningful names to your DTOs
If you want to decouple the parsing from your JPA entities and return only certain attributes you can always use Mixins for this purpose.
http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html
https://github.com/FasterXML/jackson-docs/wiki/JacksonMixInAnnotations
One more thing. If you want things to be dynamic in one service to return one representation in another to return another representation. Your option is to write a custom JSON serializer!
Check this post for how to create a customer serializer:
How do I use a custom Serializer with Jackson?
For myself I found it quite suitable to use #JsonView annotation. So you can define fields to be rendered in specific view. You can find more info here http://wiki.fasterxml.com/JacksonJsonViews
I think you can write a custom MessageBodyWriter using Jersey framework and you can control the response payload the way you want. Here you have to write few lines of code in-order to manage the response payload. For more information please visit https://jersey.java.net/documentation/latest/message-body-workers.html#d0e6826
I would use Spring Data REST and then use the ApiModel annotation to hide the attributes you do not want exposed.
I'm working in a Spring Boot project, as my implement at the moment, almost for each API I have request and response classes.
For example:
#RequestMapping(value = "/notice", method = RequestMethod.POST)
public AddNoticeResponse addNotice(#Valid #RequestBody AddNoticeRequest){
Notice notice = ... // creating new notice from AddNoticeRequest
noticeRepository.save(notice);
AddNoticeResponse response = ... // creating new response instance from Notice
return response;
}
The request and response classes look like:
#Data
#AllArgsConstructor
public class AddNoticeRequest{
private String subject;
private String message;
private Long timeToLive;
}
// Ommiting some annotations for brevity
public class AddNoticeResponse{
private String subject;
private String message;
private Long timeToLive;
private Date createTime;
private String creator;
}
I have two problems.
Creating too many classes and naming them some times made me nuts.
Some request and response have common fields.
For example: There's two kind of Notice: Email and Notification:
public class Email {
private String subject;
private String message;
private String receiver;
}
So, should I use an inner class that extends the common class or just put all the fields into one class? Which is better?
public class AddNoticeRequest {
private String subject;
private String message;
class Email extends AddNoticeRequest{
private String receiver;
}
}
public class AddNoticeRequest{
private String subject;
private String message;
private Long timeToLive;
private String receiver;
}
Then when the client performs a request to add an Email notice, will some fields be null?
Using tailored DTOs for request and response will give you more flexibility in the long run. Actually, nothing prevents you from using inheritance and inner classes, but I would just avoid it.
I already answered a similar question here, highlighting the benefits of using DTOs over persistence entities in REST APIs. Below you'll find a few benefits of this approach:
DTOs can be tailored to your needs and they are great when exposing only a set of attributes of your persistence entities. You won't need annotations such as #XmlTransient and #JsonIgnore to avoid the serialization of some attributes.
By using DTOs, you will avoid a hell of annotations in your persistence entities, that is, your persistence entities won't be bloated with non persistence related annotations;
You will have full control over the attributes you are receiving when creating or updating a resource;
If you are using Swagger to document your REST API, you can use #ApiModel and #ApiModelProperty annotations to document your API models without messing your persistence entities;
You can have different DTOs for each version of your API;
You'll have more flexibility when mapping relationships;
Your DTOs can have a list of links for HATEOAS. That's the kind of thing that shouldn't be added to persistence objects.
You can use mapping frameworks such as MapStruct to map your REST API DTOs from/to your persistence objects.
Don't subclass the req/resp objects.
Use an auto de/serialiser like Jackson in your frame work to convert message payloads into business object.
However, you will still end up with a large number of business objects.
I will suggest you to use JSON format instead of creating class and returning its instance every time. But still if you need a class hierarchy you can create a class and put a variable which will store JSON.