Spring Data Page object serialization to JSON with Spring Boot 2? - java

I am trying to upgrade my Spring Boot 1.5 project to Spring Boot 2.0.2. This includes an update to Spring Data 2.x as well.
I have now noticed that the JSON representation of Page has changed. It now looks like:
{
"content": [{
"id": "96ab09c6-2cfc-4195-899b-899b623e6e97",
"title": "Test Title",
"shortDescription": "Short description",
"description": "Test Description",
"date": "2018-02-14",
"imageUrl": "/api/images/newsposts/f637e6bd-a13a-4ebc-8c58-8ba639e09f70"
}],
"pageable": "INSTANCE",
"totalPages": 1,
"totalElements": 1,
"last": true,
"size": 0,
"number": 0,
"first": true,
"numberOfElements": 1,
"sort": {
"unsorted": true,
"sorted": false
}
}
If it is sorted, it looks similar to this:
"pageable": {
"sort": {
"sorted": true,
"unsorted": false
},
"offset": 0,
"pageSize": 20,
"pageNumber": 0,
"paged": true,
"unpaged": false
},
"totalElements": 1,
"last": true,
"totalPages": 1,
"size": 20,
"number": 0,
"first": true,
"numberOfElements": 1,
"sort": {
"sorted": true,
"unsorted": false
}
Notice the pageable element that was not there before. Also the sort element is not very useful. Is this something that was intended? Or it is just a bad idea to return org.springframework.data.domain.Page object in my REST controller?

APIwise, Spring tends to be very backward compatible.
This could be one of the minor case of backward incompatibility but Pageable is a Spring-specific construct and who's to say it will never change. Depending on one of the Spring's implementation data class till the REST layer does not seem right somehow. It would be good to handle this change in the service layer.
This is a very good example which shows the benefits of a 'layered' architecture :)

Related

How to get a child object in response with java streams

Alrighty I've been banging my head in a wall whole day and cant solve this issue. I am trying to find an id in a object list which is like 3 levels down the hierarchy with java stream. I know how to do it with for loop but I need to get it with stream.
json response is
"NumberOfOwners": 1,
"CurrentPage": 1,
"TotalItems": 1,
"TotalPages": 1,
"PageSize": 1,
"PageItems": [
{
"Id": 1560,
"Title": "PlsWrk",
"IsSubmitted": true,
"Owner": {
"Branch": null,
"Position": null,
"Id": null,
"FirstName": null,
"LastName": null,
"ParentName": null,
"Gender": null,
"Image": null,
"LoginStatusId": 0,
"EmployeeStatus": 0,
"CompanyName": null,
"IsSubcontractor": false
},
"KeyResults": [
{
"Id": 5032,
"Title": "asdf1",
"OverallStatus": 2,
"MonthKeyResults": [
{
"Id": 12484,
"Month": 9,
"Status": 3,
"Progress": "REaplace1"
},
{
"Id": 12483,
"Month": 8,
"Status": 3,
"Progress": "sadf4"
},
{
"Id": 12482,
"Month": 7,
"Status": 1,
"Progress": "On Track1"
}
]
},
{
"Id": 5033,
"Title": "asdf2",
"OverallStatus": 1,
"MonthKeyResults": [
{
"Id": 12485,
"Month": 7,
"Status": 2,
"Progress": "Recovery2"
},
{
"Id": 12487,
"Month": 9,
"Status": 2,
"Progress": "asdfreas"
},
{
"Id": 12486,
"Month": 8,
"Status": 1,
"Progress": "asdf5"
}
]
},
{
"Id": 5034,
"Title": "asdf3",
"OverallStatus": 2,
"MonthKeyResults": [
{
"Id": 12490,
"Month": 9,
"Status": 1,
"Progress": "asdafa"
},
{
"Id": 12489,
"Month": 8,
"Status": 2,
"Progress": "asdf6"
},
{
"Id": 12488,
"Month": 7,
"Status": 3,
"Progress": "Replace3"
}
]
}
]
}
]
Precisely I want stream to return MonthyKeyResult object with a specific id
Atm I am here
public static MonthKeyResults getOkrMonthlyProgressById(PageItems okr, Integer monthlyProgressId){
//here i get KeyResults object list
List<KeyResults> keyResult = okr.getKeyResults().stream().collect(Collectors.toList());
//and now I am trying to get all MonthKeyResults
//objects but I not doing it right
List<MonthKeyResults> monthKeyResults = keyResult.stream().
filter(monthKeyResult -> monthKeyResult.
getMonthKeyResults().
stream().collect(Collectors.toList()));
//and then I am thinking of going trough the monthKeyResults
//list with stream and finding Id I need and returning that
//whole object with something like this
MonthKeyResults mKeyResults = monthKeyResults.stream().filter(id -> id.getId().
equals(monthlyProgressId)).findAny().orElse(null);
return mKeyResult
}
I got one more question
I've separated getting the final object as you see in 3 streams, is it possible to get it in one go or you need to separate this objects like this and go trough them separately?
Probably you're looking for something like:
return okr.getKeyResults().stream()
.flatMap(keyResult -> keyResult.getMonthKeyResults().stream())
.filter(monthKeyResult -> monthKeyResult.getId().equals(monthlyProgressId))
.findAny()
.orElse(null);
Edit: fixed typo.

Incorrect totalElements and totalPages values for Spring Page

I have 21 rows in a database and I am using Spring's Page to get them.
If I specify a page size less than 22, it will show totalElements: 3864 and totalPages is also wrong. What could be wrong?
Example:
GET myurl.com/foo?size=5
yields a result like this
{
"content": [
{
{ "pretend_that": "there are five elements here" }
}
],
"pageable": {
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"offset": 0,
"pageNumber": 0,
"pageSize": 5,
"paged": true,
"unpaged": false
},
"last": false,
"totalPages": 773,
"totalElements": 3864,
"size": 5,
"number": 0,
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"first": true,
"numberOfElements": 5,
"empty": false
}
Example 2:
GET myurl.com/foo?size=50
yields a result like this
{
"content": [
{
{ "pretend_that": "there are 21 elements here" }
}
],
"pageable": {
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"offset": 0,
"pageNumber": 0,
"pageSize": 50,
"paged": true,
"unpaged": false
},
"last": true,
"totalPages": 1,
"totalElements": 21,
"size": 50,
"number": 0,
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"first": true,
"numberOfElements": 21,
"empty": false
}
P.S. if I get the final page, it shows the page and elements count correctly.
I have tried changing Spring Boot versions and that hasn't helped.

Maximum number of fields support to be included in _source.includes in Elastic search for _search api?

While querying an index with more than 1500 fields included inside _source.includes, I'm getting following error from ES.
Error Log:
{
"took": 154,
"timed_out": false,
"_shards": {
"total": 28,
"successful": 15,
"skipped": 0,
"failed": 13,
"failures": [
{
"shard": 0,
"index": "index123",
"node": "...",
"reason": {
"type": "too_complex_to_determinize_exception",
"reason": "too_complex_to_determinize_exception: Determinizing automaton with 52903 states and 54499 transitions would result in more than 10000 states."
}
}
]
},....
Here is the sample query I'm trying to execute.
Query Sample:
{
"explain": false,
"size": 20,
"query": {
"bool": {
"filter": [
{
"bool": {
"adjust_pure_negative": true,
"must": [
{
"terms": {
"boost": 1,
"type": [
"University"
]
}
}
],
"boost": 1
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
},
"from": 0,
"_source": {
"excludes": [
],
"includes": [
--1579 fields included --
]
}
}
Note: When tried lowering number of fields to around 1440 inside _source.includes, ES was able to give response with no error.
I was wondering if there is any hard limit on number fields that can be added inside _source or any config settings to increase that limit.
It would also be helpful, if there's any alternative to get such high number fields to be included and returned from ES.
Thanks in advance!
With so many fields, you should either exclude (using _source.excludes) the ones you don't need instead of including the ones you need, there would be less fields in your query.
Another solution, because _source has limitations with a high number of fields, you can also leverage the fields option which usually performs better than _source.

Arango Edge Creation bug with Spring boot

I am creating a project with ArangoDb for my research. It is a backend project with Spring boot. I was following the tutorials here:
https://github.com/arangodb/spring-data-demo
Everything went well but when I tried creating a controller with the "Character" class. I get this error:
java.lang.StackOverflowError: null
Upon further inspection, I found out that it is the mapping of children and parents that's creating this problem.
In a separate project, I created a basic POJO (class Parts) with basic properties such as name, id and a collection of childParts similar to "childs" in your character class. I did all the mappings (with edges and all) and created the relationships. Then if I have two Parts Objects, P1 and P2, and I make P2 childPart of P1. The JSON response comes as P2 as child of P1 and then P1 as child of P2 and again P2 as child of P1 on and on. Its an infinite loop. Earlier I thought there was some problem with my implementation but when I downloaded the demo code. It has the same problem.
Please let me know if there is a way to get around this or if I missed something.
The postman response of the tutorial code is actually an infinite loop. Something like this:
[
{
"id": "424543",
"name": "Sansa",
"surname": "Stark",
"alive": true,
"age": 13,
"childs": [
{
"id": "424594",
"name": "Ned",
"surname": "Stark",
"alive": false,
"age": 41,
"childs": [
{
"id": "424606",
"name": "Robb",
"surname": "Stark",
"alive": false,
"age": null,
"childs": [
{
"id": "424594",
"name": "Ned",
"surname": "Stark",
"alive": false,
"age": 41,
"childs": [
{
"id": "424606",
"name": "Robb",
"surname": "Stark",
"alive": false,
"age": null,
"childs": [
{
"id": "424594",
"name": "Ned",
"surname": "Stark",
"alive": false,
"age": 41,
"childs": [
{
The annotations #Ref, #Relations, #To, and #From allow to set the field boolean lazy, which specifies whether the entity should be loaded lazily. Depending on how you modeled your entities and on which of the annotations above you use, I think you can solve the problem setting lazy = true in one of them.

Is there a problem with my code or the API I am using?

I am trying to submit an item to an API, the request goes through but comes back with an incorrect item construction returned by the API.
The code works compiles and runs without a problem, unfortunately the item constructed is incorrect.
API I am using: https://www.clover.com/api_docs/#!/inventory/CreateItem
If the above link does not work, navigate to Inventory -> Items -> Create an Inventory Item.
I have played around with what I am sending to the server but my problem is with the tags argument of the API. No matter what I set the "tags" field to, the returned item never has a tags field. I also have a UI that I can see all the item's properties. "tags" is always null.
Here is what I am feeding the API:
{
"name":"test_item_with_label",
"sku":"1234",
"code":"959",
"price":1698,
"tags":[
{
"id":"Z1JC35RHV6PFP",
"name":"Sewing",
"showInReporting":false
}
],
"priceType":"FIXED",
"defaultTaxRates":true,
"hidden":false,
"revenue":true
}
This is the item's properties after the request:
{
"id": "FCMS6MSAFYK1E",
"hidden": false,
"name": "test_item_with_label",
"code": "959",
"sku": "1234",
"price": 1698,
"priceType": "FIXED",
"defaultTaxRates": true,
"isRevenue": true,
"modifiedTime": 1564272103000
}
I want the item to be constructed correctly through the API with tags.
This is the available tags for reference.
"elements": [ {
"id": "Z1JC35RHV6PFP",
"name": "Sewing",
"showInReporting": false
}, {
"id": "STBVZXTVHDYK6",
"name": "Compass Industries",
"showInReporting": false
}, {
"id": "SSWR290EAK8RM",
"name": "Savor Jerky",
"showInReporting": false
}, {
"id": "GCENM7Y4RBJE2",
"name": "Triple K",
"showInReporting": false
}, {
"id": "E9H3YC70T4D6W",
"name": "Sabre/Security Equipment Co.",
"showInReporting": false
}, {
"id": "4ANVQMMFK7MNR",
"name": "Lansky Sharpeners",
"showInReporting": false
}, {
"id": "1H66V1ZK7Y84Y",
"name": "Nebo/ True Utility",
"showInReporting": false
}, {
"id": "0PZ5R8VV61QDJ",
"name": "Victorinox Swiss Army",
"showInReporting": false
}]
Found the answer!
Leaving it here in case anyone else runs into this problem with the Clover PoS API.
Basically their API is wrong! It says you can feed all those arguments in the docs, but you first must create the item THEN come back and tag the item with the correct tag by ID.
Answer found here: https://community.clover.com/questions/1822/can-somebody-tell-me-the-use-of-v3merchantsmidtag.html

Categories

Resources