I have this controller:
#RequestMapping("/api")
public ResponseEntity<?> a(Pageable pageable) throws IOException {
ObjectMapper mapper = new ObjectMapper( );
File file = new File( "samplejson.json" );
JsonNode jsonNode = mapper.readTree( file );
List<JsonNode> nodes = new ArrayList<>();
if ( !jsonNode.isArray() )
nodes.add( jsonNode );
else
for ( JsonNode node : jsonNode )
nodes.add( node );
return new ResponseEntity<Object>( new PageImpl( nodes, pageable, nodes.size() ), HttpStatus.OK );
}
and when i postman it, it gives me this response:
{
"content": [
{
"id": 1,
"first_name": "Dode",
"email": "dcardall0#zimbio.com",
"gender": "Female",
"timestamp": "11/12/1981"
},
{
"id": 2,
"first_name": "Andrus",
"email": "amcgeever1#jigsy.com",
"gender": "Male",
"timestamp": "10/25/1988"
},
{
"id": 3,
"first_name": "Allyn",
"email": "afakes2#samsung.com",
"gender": "Male",
"timestamp": "9/3/1997"
},
{
"id": 4,
"first_name": "Merell",
"email": "mmoreton3#census.gov",
"gender": "Male",
"timestamp": "3/7/2009"
}
],
"last": true,
"totalElements": 10,
"totalPages": 1,
"size": 20,
"number": 0,
"sort": [
{
"direction": "DESC",
"property": "id",
"ignoreCase": false,
"nullHandling": "NATIVE",
"descending": true,
"ascending": false
}
],
"first": true,
"numberOfElements": 10 }
in the URI i have this
http://localhost:8080/api?sort=id, desc
However the pagination isn't working. As you can see, the sort direction in the response says "DESC". So it's supposed to be in descending order, right? But it's not working. I think because it's inside an object content which was created by pagination. But i don't know how to access what's inside content.
in order to apply PageRequest options like sort etc. you need to use PagingAndSortingRepository (see Spring Paging documentation)
So the sorting and getting the page is executed inside repository logic. See org.springframework.data.jpa.repository.support.SimpleJpaRepository.readPage
You can also go through this tutorial: https://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-part-seven-pagination/
Related
I have a JSON array, in that I need to make match count using ParentCommentID and parse data into recyclerview using text view while counting i get number count only one position and same for other item also, any help.
{
"d": {
"results": [
{
"__metadata": {
"id": "e7433825-6771-4f5e-96c7-c4d2674d7764",
"uri": "",
"etag": "\"2\"",
"type": "SP.Data.InquiryDiscussionsListListItem"
},
"Author": {
"__metadata": {
"id": "f064775c-6161-4bdb-9f4d-8bc6a898d218",
"type": "SP.Data.UserInfoItem"
},
"Title": "Submitter1"
},
"Id": 1501,
"ID": 1501,
"Title": null,
"Created": "2019-06-06T04:15:17Z",
"ParentCommentID": "1439",
"Comment": "<div class=\"ExternalClass8C333A77B6564A53BED74CA1BA2D2A10\">
reply add for 009</div>",
"CommentType": null,
"CommentDocumentName": null,
"AppID": "1083",
"Role": "Customer"
},
{
"__metadata": {
"id": "e92f708f-93dc-4587-8c4f-5518ed24f360",
"uri": "",
"etag": "\"2\"",
"type": "SP.Data.InquiryDiscussionsListListItem"
},
"Author": {
"__metadata": {
"id": "209d2d9a-bb07-4064-aaa0-231ad881a80f",
"type": "SP.Data.UserInfoItem"
},
"Title": "Submitter1"
},
"Id": 1500,
"ID": 1500,
"Title": null,
"Created": "2019-06-06T04:14:55Z",
"ParentCommentID": "1439",
"Comment": "<div class=\"ExternalClass44B1A0BB4D314C57BEE20141BFF10491\">comment add for 009</div>",
"CommentType": null,
"CommentDocumentName": null,
"AppID": "1083",
"Role": "Customer"
},
{
"__metadata": {
"id": "ec112002-3132-4bc1-8f85-03fbd9fda11d",
"uri": "",
"etag": "\"2\"",
"type": "SP.Data.InquiryDiscussionsListListItem"
},
"Author": {
"__metadata": {
"id": "6e8ecb1d-4deb-4168-a8b4-a725abf8002a",
"type": "SP.Data.UserInfoItem"
},
"Title": "Sarada Devi Potti"
},
"Id": 1439,
"ID": 1439,
"Title": "Canceled",
"Created": "2019-06-03T09:32:34Z",
"ParentCommentID": null,
"Comment": "<div class=\"ExternalClass5E1BFEDC348C43719AD940E644E0E0B6\">sdaeadfasdf</div>",
"CommentType": "Public",
"CommentDocumentName": null,
"AppID": "1083",
"Role": "Budget Analyst"
}
]
}
}
My code is onbind method:
Map<String, Integer> commentsCountMap = new HashMap<>();
for(Result res : discussionsList) {
String parentCommentId = res.getParentCommentID();
// If the MyDocsResult has a parent comment
if(parentCommentId != null) {
// get the count for this parent comment (default to 0)
int nbCommentsForParent = commentsCountMap.getOrDefault(parentCommentId, 0);
// increment the count
nbCommentsForParent++;
// Update the Map with the new count
commentsCountMap.put(parentCommentId, nbCommentsForParent);
System.out.println(commentsCountMap);
Log.d("Count:",commentsCountMap.toString());
}
}
for example id 1439, having two ParentCommentID, so in that case for id 1439 there should be a count of two comments, I tried to use for in my
recyclerview adapter but its dose not work.
I think you need to run through the list of Results and when when you find a Result that has a parent comment, then you go in the map, get the parent comment, increment its count by one and stick it back in the Map:
Assuming your Result class is something like this:
class Result {
private String id;
private String parentCommentID;
public Result(String id, String parentCommentID) {
this.id = id;
this.parentCommentID = parentCommentID;
}
// GETTERS/SETTERS
}
And you have a discussion list with 3 Results
discussionsList = Arrays.asList(
new Result("1439", null),
new Result("1500", "1439"),
new Result("1801", "1439")
);
Like your case, 1439 has no parent and 1500 and 1501 both have 1439 as parent
Then you can do this kind of thing:
Map<String, Integer> commentsCountMap = new HashMap<>();
// Loop through the discussion Map
for(Result res : discussionsList) {
String parentCommentId = res.getParentCommentID();
// If the Result has a parent comment
if(parentCommentId != null) {
// get the count for this parent comment (default to 0)
int nbCommentsForParent = commentsCountMap.getOrDefault(parentCommentId, 0);
// increment the count
nbCommentsForParent++;
// Update the Map with the new count
commentsCountMap.put(parentCommentId, nbCommentsForParent);
}
}
System.out.println(commentsCountMap);
This outputs
{1439=2}
I have a token restful service, which generates the following info when I use postman to hit it (GET).
{
"authorities": [
{
"id": 1,
"authority": "admin"
},
{
"id": 2,
"authority": "ROLE_USER"
}
],
"details": {
"remoteAddress": "0:0:0:0:0:0:0:1",
"sessionId": null,
"tokenValue": "7760e769-9b1e-4669-8b6d-85e51809934d",
"tokenType": "bearer",
"decodedDetails": null
},
"authenticated": true,
"userAuthentication": {
"authorities": [
{
"id": 1,
"authority": "admin"
},
{
"id": 2,
"authority": "ROLE_USER"
}
],
"details": {
"remoteAddress": "0:0:0:0:0:0:0:1",
"sessionId": null
},
"authenticated": true,
"principal": {
"id": 1,
"username": "sysadmin",
"password": "$2a$10$xm6.EOh8GrsnwRy91d2cueZPwvPojuExnYEGy1auFyzqYTtdlHvUe",
"accountNonExpired": true,
"accountNonLocked": true,
"credentialsNonExpired": true,
"enabled": true,
"authorities": [
{
"id": 1,
"authority": "admin"
},
{
"id": 2,
"authority": "ROLE_USER"
}
],
"userId": "1"
},
"credentials": null,
"name": "sysadmin"
},
"credentials": "",
"oauth2Request": {
"clientId": "movez",
"scope": [
"all"
],
"requestParameters": {
"grant_type": "refresh_token"
},
"resourceIds": [],
"authorities": [],
"approved": true,
"refresh": false,
"redirectUri": null,
"responseTypes": [],
"extensions": {},
"grantType": "refresh_token",
"refreshTokenRequest": null
},
"principal": {
"id": 1,
"username": "sysadmin",
"password": "$2a$10$xm6.EOh8GrsnwRy91d2cueZPwvPojuExnYEGy1auFyzqYTtdlHvUe",
"accountNonExpired": true,
"accountNonLocked": true,
"credentialsNonExpired": true,
"enabled": true,
"authorities": [
{
"id": 1,
"authority": "admin"
},
{
"id": 2,
"authority": "ROLE_USER"
}
],
"userId": "1"
},
"clientOnly": false,
"name": "sysadmin"
}
However, when I use RestTemplate exchange to make the api call, I get the following,
The problem here is
There are two layers "authorities", which doesn't match the structure in the Json.
If we go deep, we only have the authority "ROLE_USER", the "admin" is not retrieved.
My code is
Map auth = restTemplate.exchange(tokenVerifyUri, HttpMethod.GET, entity, Map.class).getBody();
It previously worked fine but have this trouble after I upgrade spring to 2.0 (not sure if it is related).
Please help. Thanks in advance.
UPDATE:
If I change Map.class to String.class in exchange function, I got the correct Json.
I have a JSON file like this:
{
"objects": [{
"type": "FirstType",
(...)
"details": {
"id": 1,
"name": "FirstElementOfTheFirstType",
"font": "18px arial"
},
"id": "18e"
},
(...)
{
"type": "SecondType",
(...)
"details": {
"id": 1,
"name": "FirstElementOfTheSecondType",
"font": "18px arial"
},
"id": "18f"
}
],
"background": "#ffffff"
}
My goal is to delete nodes of a certain type and id in details F.e. if I would like to delete elements of type named FirstType and id of 1.I would get:
{
"objects": [
(...)
{
"type": "SecondType",
(...)
"details": {
"id": 1,
"name": "FirstElementOfTheSecondType",
"font": "18px arial"
},
"id": "18f"
}
],
"background": "#ffffff"
}
I think I partialy achieved this:
final DocumentContext jsonContext = JsonPath.parse(element.getJsonContent());
jsonContext.delete("$['objects'][?(#.type == 'FirstType')][?(#.details.id == '1')]");
But I would like to consider type and id in details as well, but I am not sure if two filter expressions are written correctly. I feel like I stuck here
EDITED: Solved
Ok. For future references, correct form goes like this:
DocumentContext jsonContext = JsonPath.parse(element.getJsonContent());
jsonContext.delete("$['objects'][?(#.type == 'FirstType' && #.details.id == 1)]");
element.setJsonContent(jsonContext.jsonString());
I have following structure names Discussion. I want to fetch the last message in a discussion by a user. I tried following incomplete Spring MongoDB query, could you please let me know how to fetch just one message (sorted by lastmodifieddate) per discussion or find the discussions where a user is the recipient of the last message in the conversation.
Aggregation aggr = newAggregation(
match(Criteria.where("participants").regex(Pattern.compile(userid))),
unwind("messages"),
match(new Criteria().orOperator(Criteria.where("messages.touserId").is(userid),Criteria.where("messages.fromuserId").is(userid))),
sort(Direction.DESC, "messages.lastModifiedDate"),
group("_id").push("messages").as("messages"),
project("_id","messages")
);
{
"_id": {
"$oid": "57c2d7c8e4b0bcf181b7db0a"
},
"_class": "xxxxx",
"participants": [
"56893b22e4b0e8d1c6a25783",
"56893bb6e4b0e8d1c6a25785",
"577c2f6ee4b09ccb44d14415"
],
"messages": [
{
"_id": {
"$oid": "57c2d7c8e4b0bcf181b7db08"
},
"fromuserId": "577c2f6ee4b09ccb44d14415",
"fromuser": "xxxx",
"touserId": "56893b22e4b0e8d1c6a25783",
"touser": "Bloreshop1",
"message": "Check Product Price",
"isMute": false,
"index": 1,
"createDate": {
"$date": "2016-08-28T12:23:36.037Z"
},
"lastModifiedDate": {
"$date": "2016-08-28T12:23:36.037Z"
},
"createdBy": "xxxx",
"lastModifiedBy": "xxxxx"
},
{
"_id": {
"$oid": "57c2d7c8e4b0bcf181b7db09"
},
"fromuserId": "577c2f6ee4b09ccb44d14415",
"fromuser": "xxxxxx",
"touserId": "56893bb6e4b0e8d1c6a25785",
"touser": "Bloreshop2",
"message": "Check Product Price",
"isMute": false,
"index": 2,
"createDate": {
"$date": "2016-08-28T12:23:36.302Z"
},
"lastModifiedDate": {
"$date": "2016-08-28T12:23:36.302Z"
},
"createdBy": "xxxxx",
"lastModifiedBy": "xxx"
}
],
"discussionTopic": "Check Product Price",
"messageCount": 2,
"createDate": {
"$date": "2016-08-28T12:23:36.318Z"
},
"lastModifiedDate": {
"$date": "2016-08-28T12:23:36.318Z"
},
"createdBy": "xxxx",
"lastModifiedBy": "xxxxx"
}
You are looking for $slice(aggregation). Current release 1.9.5 version doesn't support slice.
Aggregation aggr = newAggregation(
match(Criteria.where("participants").regex(Pattern.compile(userid))),
unwind("messages"),
match(new Criteria().orOperator(Criteria.where("messages.touserId").is(userid), Criteria.where("messages.fromuserId").is(userid))),
sort(Direction.DESC, "messages.lastModifiedDate"),
group("_id").push("messages").as("messages"),
project("_id").and("messages").project("slice", 1));
Unreleased Version (2.x) supports slice
Aggregation aggr = newAggregation(
match(Criteria.where("participants").regex(Pattern.compile(userid))),
unwind("messages"),
match(new Criteria().orOperator(Criteria.where("messages.touserId").is(userid), Criteria.where("messages.fromuserId").is(userid))),
sort(Direction.DESC, "messages.lastModifiedDate"),
group("_id").push("messages").as("messages"),
project("_id").and("messages").slice(1));
{
"platform": "iOS",
"device": {
"os_name": "iPhone OS",
"manufacturer": "Apple",
"type": "iPhone3",
"version": "1",
"os_version": "5.1.1"
},
"app_version": "1.0",
"device_id": "",
"app_key": "1234567890",
"developer_key": "",
"app_name": "test",
"session": { // here
"platform": "iOS",
"device": {
"os_name": "iPhone OS",
"manufacturer": "Apple",
"type": "iPhone3",
"version": "1",
"os_version": "5.1.1"
},
"app_version": "1.0",
"device_id": "",
"app_key": "1234567890",
"developer_key": "",
"app_name": "test"
}
}
This is the data generated by MappingJacksonConverter but I don't know how to disable the "session" field containing the whole recursive data.
HttpEntity<OlSession> sessionEntity = new HttpEntity<OlSession>(new OlSession());
ResponseEntity<String> response = restTemplate.postForEntity("http://localhost:3000/test/abcd", sessionEntity, String.class);
This is the code to post the above data. Is there any part that I need to add to disable the "session" field?
There are two simple solution.
1) Use jackson annotation to ignore that property.
But in this way, session in OlSession property will not be serialized everywhere.
#JsonIgnore
Object getSession() {
return session
}
Take a look this doc JacksonAnnotation
2) Just set null before you send.