Spring Boot DTO/Payload validation with extra not required fields - spring

In Spring Boot applications, while implementing REST APIs, validation is done of the DTO object received by the server.
We can easily validate the required fields of DTO objects by validation annotations.
But I want to send error response for the payload where extra not required fields exist.
So validation should fail for the payloads like below:
{
"data": {
"type": "user",
"attributes": {
"firstName": "Kazi Mahbubur",
"lastName": "Rahman",
"age": 30,
"x": "x",
"y": "y",
"z": "z",
}
}
}
In the above request body (JSON type), the x, y, z attributes are not required according to REST API spec. Attributes x, y, z are unexpected and not required fields.
How to achieve this validation fail using Spring Bean Validation?
Or, the best way to handle this scenario as a DTO/payload validation fail?

Related

How to use "anyOf" in JSON schema validation which is using RAML and MULE API?

I need to implement schema validation for incoming JSON payload.
The below elements will be there in the JSON,
"partyId": {
"type": ["string","null"],
"maxLength": 16,
"required": false,
"description": "Party ID"
},
"erpId": {
"type": ["string","null"],
"maxLength": 20,
"required": false,
"description": "ERP ID"
}
Required validation :
Any one element should be available in JSON, Else it should reject the request.
My project is using "$schema":"http://json-schema.org/draft-06/schema#"
Some follow up question?
How to find which schema draft version using in my project (some schema json file there is no draft version in the top)?
Which maven dependency is supporting this schema draft version ?
the required keyword takes a list of property names, not a boolean. It should live at the same level as "type": "object" and "properties".
https://json-schema.org/understanding-json-schema/reference/object.html#required-properties
you can use anyOf to check for the availability of any of a multiple number of properties.
https://json-schema.org/understanding-json-schema/reference/conditionals.html

Microservice design

We have a product where 4 microservices are communicating with each other.
Let's say entry point receives a payload as below:
{
"Employees": [
{
"userId": "rirani",
"jobTitleName": "Developer",
"firstName": "Romin",
"lastName": "Irani",
"preferredFullName": "Romin Irani",
"employeeCode": "E1",
"region": "CA",
"phoneNumber": "408-1234567",
"emailAddress": "romin.k.irani#gmail.com"
}
]
}
The 1st microservice does validation on the payload "employeeCode" it allows only employee code which. starts with "E" else returns 400 status code. The Same payload is forwarded to other componet as well if all validation passes.
Now my question is tomorrow there could be fair chance that external service consumes our any of the components to process their request. Do we need to have the validation in all the components?
Now there is no external client which uses our components but in the future maybe.
It's a more of a design question. Do we need to make our validation as a jar or we should not duplicate the validation itself? Its client responsibility to send the correct data if they are calling any other component except Microservice-1.
Thanks, in advance.

Spring Integration Java DSL: How to loop the paged Rest service?

How to loop the paged Rest service with the Java DSL Http.outboundGatewaymethod?
The rest URL is for example
http://localhost:8080/people?page=3
and it returns for example
"content": [
{"name": "Mike",
"city": "MyCity"
},
{"name": "Peter",
"city": "MyCity"
},
...
]
"pageable": {
"sort": {
"sorted": false,
"unsorted": true
},
"pageSize": 20,
"pageNumber": 3,
"offset": 60,
"paged": true,
"unpaged": false
},
"last": false,
"totalElements": 250,
"totalPages": 13,
"first": false,
"sort": {
"sorted": false,
"unsorted": true
},
"number": 3,
"numberOfElements": 20,
"size": 20
}
where the variable totalPages tells the total pages amount.
So if the implementation
integrationFlowBuilder
.handle(Http
.outboundGateway("http://localhost:8080/people?page=3")
.httpMethod(HttpMethod.GET)
.expectedResponseType(String.class))
access one page, how to loop all the pages?
The easiest way to do this is like wrapping the call to this Http.outboundGateway() with the #MessagingGateway and provide a page number as an argument:
#MessagingGateway
public interface HttpPagingGateway {
#Gateway(requestChannel = "httpPagingGatewayChannel")
String getPage(int page);
}
Then you get a JSON as a result, where you can convert it into some domain model or just perform a JsonPathUtils.evaluate() (based on json-path) to get the value of the last attribute to be sure that you need to call that getPage() for the page++ or not.
The page argument is going to be a payload of the message to send and that can be used as an uriVariable:
.handle(Http
.outboundGateway("http://localhost:8080/people?page={page}")
.httpMethod(HttpMethod.GET)
.uriVariable("page", Message::getPayload)
.expectedResponseType(String.class))
Of course, we can do something similar with Spring Integration, but there are going to be involved filter, router and some other components.
UPDATE
First of all I would suggest you to create a domain model (some Java Bean), let's say PersonPageResult, to represent that JSON response and this type to the expectedResponseType(PersonPageResult.class) property of the Http.outboundGateway(). The RestTemplate together with the MappingJackson2HttpMessageConverter out-of-the-box will do the trick for you to return such an object as a reply for the downstream processing.
Then, as I said before, looping would be better done from some Java code, which you could wrap to the service activator call. For this purpose you should daclare a gateway like this:
public interface HttpPagingGateway {
PersonPageResult getPage(int page);
}
Pay attention: no annotations at all. The trick is done via IntegrationFlow:
#Bean
public IntegrationFlow httpGatewayFlow() {
return IntegrationFlows.from(HttpPagingGateway.class)
.handle(Http
.outboundGateway("http://localhost:8080/people?page={page}")
.httpMethod(HttpMethod.GET)
.uriVariable("page", Message::getPayload)
.expectedResponseType(PersonPageResult.class))
}
See IntegrationFlows.from(Class<?> aClass) JavaDocs.
Such a HttpPagingGateway can be injected into some service with hard looping logic:
int page = 1;
boolean last = false;
while(!last) {
PersonPageResult result = this.httpPagingGateway.getPage(page++);
last = result.getLast();
List<Person> persons = result.getPersons();
// Process persons
}
For processing those persons I would suggest to have separate IntegrationFlow, which may start from the gateway as well or you can just send a Message<List<Person>> to its input channel.
This way you will separate concerns about paging and processing and will have a simple loop logic in some POJO method.

How to remove Jackson "type" field on generics

When a Spring Boot controller returns a generic object, Jackson marshals it and automatically adds a "type" field to the generated JSON. It basically marshals this object:
public class PaginatedResponse<T> {
List<T> list;
int total;
// ctors, getters and setters
}
The marshaled response looks like this:
{
"list":[
{"type": "foo", "id": 1},
{"type": "foo", "id": 2}
],
"total": 2
}
whereas I would like to get this:
{
"list":[
{"id": 1},
{"id": 2}
],
"total": 2
}
I do understand the purpose of this mechanism, but this JSON will not be unmarshaled back to the original PaginatedResponse object and I'd like to drop the "type" field. How can I do that?
I'm using Jackson 2.7.6 within Spring Boot 1.4.5 with no Jackson-specific settings in the properties file or Jackson annotations on either of the unmarshaled objects.

How to remove hypermedia elements from representations produced by Spring Data REST?

When using Spring Data for my REST API, the responses returned currently include the _links field:
{
"_embedded": {
"users": [
{
"imageUrl": "some_image_url",
"name": "some name",
"id": "57420b2a0d31bb6cef4ee8e9",
"_links": {
"self": {
"href": "http://localhost:8080/users/57420b2a0d31bb6cef4ee8e9"
},
"user": {
"href": "http://localhost:8080/users/57420b2a0d31bb6cef4ee8e9{?projection}",
"templated": true
}
}
},
...
Is there a way to produce output, such that the _links field is hidden? e.g.:
{
"_embedded": {
"users": [
{
"imageUrl": "some_image_url",
"name": "some name",
"id": "57420b2a0d31bb6cef4ee8e9",
},
...
I find that because I am exposing the id field, _links are not really necessary, and mostly just clutter up my responses.
There isn't. Hypermedia is a fundamental trait of REST APIs and Spring Data REST heavily uses it to allow you to build clients that can use the links present in the responses to navigate to related resources.
Of course you can dumb down your clients to not make use of that information but that will lead to a much tighter coupling (as you can't change the URIs on the server side anymore, your clients expects to talk to a dedicated server whereas with hypermedia you can just point it to a different server etc.).
In contrast to a lot of other self-proclaimed REST frameworks out there, one of the key aspects of the framework's design is to respect the fundamental principles in REST and explicitly leverage them. Or at least, don't create incentives to easily break them. This is clearly expressed in the reference documentation and on the project website. Find out more about key design decisions in this presentation on Spring Data REST, and this one on Domain-Driven Design & REST.

Resources