How to parse belowJSON in springboot - spring

How to parse the response JSON and get summary and action each time and form a separate object with that.
{
"issues": [
{
"fields":
{
"summary": "This is summary",
"action": "Start"
}
}, {
"fields":
{
"summary": "Second summary",
"action": "Stop"
}
}
]
}

You can create a Issues class and Fields class. Below is a snippet for reference,
public class Issues {
private List<Fields> fields;
// Getters and Setters
}
public class Fields {
private String summary;
private String action;
// Getters and Setters
}
You can map the response to the Issues object and go ahead iterating the fields List to fetch the summary and action out of it.

Related

Spring GraphQL mutation NullPointerException

I'm learning GraphQL in spring boot and I have created a mutation that saves used details in database. When I try to call the mutation from GraphiQL UI using following mutation query, it throws NullPointerException because the object I passed in mutation is not mapped with UserDto and I don't know why.
I have following code:
Controller
#Controller
public class UserController {
private UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
#QueryMapping(name = "userById")
public UserDto findUserById(#Argument Long id) {
return userService.findById(id);
}
#QueryMapping
public String removeUserById(#Argument Long id) {
return userService.removeById(id);
}
#MutationMapping(name = "save")
public UserDto save(#Argument UserDto user) {
return userService.save(user);
}
#QueryMapping(name = "users")
public List<UserDto> findAll() {
return userService.findAll();
}
}
GraphQL Schema
schema {
query: Query
mutation: Mutation
}
type Query{
users:[User]
userById(id:ID):User
}
type Mutation{
save(userInput:UserInput):User
}
#input types
input UserInput{
firstName:String!
lastName:String!
emailAddress:String!
ipAddress:String!
address:AddressInput!
}
input AddressInput{
addressLine1:String!
addressLine2:String!
addressLine3:String!
addressLine4:String!
addressLine5:String!
addressPostCode:Int!
}
#object types
type User{
firstName:String!
lastName:String!
emailAddress:String!
ipAddress:String!
address:Address!
}
type Address{
addressLine1:String!
addressLine2:String!
addressLine3:String!
addressLine4:String!
addressLine5:String!
addressPostCode:Int!
}
Mutation Query
mutation Save($userDto: UserInput!) {
save(userInput: $userDto) {
firstName
lastName
emailAddress
ipAddress
address {
addressLine1
addressLine2
addressLine3
addressLine4
addressLine5
addressPostCode
}
}
}
Variables
{
"userDto": {
"ipAddress": "192.168.0.124",
"firstName": "John",
"lastName": "Mark",
"emailAddress": "john#gmail.com",
"address": {
"addressLine1": "251 WC",
"addressLine2": "UC MAIN",
"addressLine3": "PB121",
"addressLine4": "New York",
"addressLine5": "USA",
"addressPostCode": 457821
}
}
}
Results
{
"errors": [
{
"message": "INTERNAL_ERROR for b6287602-fc10-6ecf-2091-b57ceaeb9f0a",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"save"
],
"extensions": {
"classification": "INTERNAL_ERROR"
}
}
],
"data": {
"save": null
}
}
When I run the GraphQL query, it throws NullPointerException in console.
Console Error
java.lang.NullPointerException: Cannot invoke "com.graphql.sample.dto.UserDto.getEmailAddress()" because "userDto" is null
I'm answering my question because I have already solved it. I had made a small mistake in controller near #Argument UserDto user as below:
#MutationMapping(name = "save")
public UserDto save(#Argument(name = "userInput") UserDto user) {
return userService.save(user);
}
The name in #Argument should match the name of parameter in Mutation type as below:
type Mutation{
save(userInput:UserInput):User
}
type User{
firstName:String!
lastName:String!
emailAddress:String!
ipAddress:String!
address:Address!
}
Reason 1:
Your save mutation result is returned to this entity. But it can be possible that a property that you are receiving might be null that's why this error is thrown, as you are using ! with each property. You can remove ! if a value can/is null
Reason 2:
I couldn't see your resolver so it might be possible that the result is not an object or the property names that you are receiving don't match with the property names inside type User. It should be same or use resolver to provide their values

springboot mongodb crud update only changed fields

Hello i have springboot with mongodb (spring-boot-starter-data-mongodb)
My problem is if I send only one or only the fields I want to change so the other values are set to null. I found something on the internet like #DynamicUpdate but not working on mongodb can you help me with this problem. I'm a beginner, I don't know how to help and it's quite important for me, if you need more code or more information, I'll write in the comment. I hope I have described the problem sufficiently. :)
MY POJO:
#Data
#Getter
#Setter
#NoArgsConstructor
public class Person {
#Id
private String id;
private String firstName;
private String lastName;
private boolean enabled;
private String note;
Repo
#Repository
public interface PersonRepository extends MongoRepository <Person, String> {
}
i have this call
#PutMapping("/{id}")
#ResponseBody
public void UpdatePerson (#PathVariable String id , #RequestBody Person person) {
personRepository.save(person);
}
#GetMapping(path = "/{id}")
public Person getPersonByid(#PathVariable String id ){
return personRepository.findById(id).orElseThrow(PersonNotFound::new);
}
sample:
get call before update :
{
"id": "5fc940dc6d368377561dbb02",
"firstName": "Rambo",
"lastName": "Norris",
"enabled": true,
"note": "hello this is my first note from you",
}
put call :
{
"id": "5fc940dc6d368377561dbb02",
"firstName": "Chuck"
}
get call after update :
{
"id": "5fc940dc6d368377561dbb02",
"firstName": "Chuck",
"lastName": null,
"enabled": false,
"note": null,
}
what I would like
get call before update :
{
"id": "5fc940dc6d368377561dbb02",
"firstName": "Rambo",
"lastName": "Norris",
"enabled": true,
"note": "hello this is my first note from you",
}
put call :
{
"id": "5fc940dc6d368377561dbb02",
"firstName": "Chuck"
}
get call after update :
{
"id": "5fc940dc6d368377561dbb02",
"firstName": "Chuck",
"lastName": "Norris",
"enabled": true,
"note": "hello this is my first note from you",
}
You are inserting a new collection instead of updating. First, you need to get the old value from mongodb, then you need to update the collection, then save to DB.
Use the below code in #putmapping.
#PutMapping("/{id}")
#ResponseBody
public void UpdatePerson (#PathVariable String id , #RequestBody Person person) {
Person personFromDB = personRepository.findById(person.getId());
personFromDB.setFirstName(person.getFirstName());
personRepository.save(personFromDB);
}
Try updating like this
#PutMapping("/{id}")
public ResponseEntity<Person> UpdatePerson (#PathVariable String id , #RequestBody
Person person) {
Optional<Person> personData = personRepository.findById(id);
if (personData.isPresent()) {
Person _tutorial = personData.get();
if(!StringUtils.isEmpty(person.getFirstName())) {
_tutorial.setFirstName(person.getFirstName());
}
if(!StringUtils.isEmpty(person.getLastName())) {
_tutorial.setLastName(person.getLastName());
}
if(!StringUtils.isEmpty(person.getNote())) {
_tutorial.setNote(person.getNote());
}
if(!StringUtils.isEmpty(tutorial.isEnabled())) {
_tutorial.setEnabled(tutorial.isEnabled());
}
return new ResponseEntity<>(repo.save(_tutorial), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}

How to query nested objects from MongoDB using Spring Boot (REST) and TextQuery?

I am writing RESTful API to search MongoDB collection named 'global' by criteria using TextQuery. My problem is that I cannot access nested object fields when doing query.
For example this works:
GET localhost:8080/search?criteria=name:'name'
And this does not:
GET localhost:8080/search?criteria=other.othername:'Other Name'
I have MongoDB json structure (imported from JSON into 'global' collection as whole nested objects)
[{
"name": "Name",
"desc": "Desc",
"other" {
"othername": "Other Name",
}
},
{
"name": "Name",
"desc": "Desc",
"other" {
"othername": "Other Name",
}
}
]
And classes (with getters & setters & etc):
#Document(collection="global")
public class Global{
#TextIndexed
String name;
#TextIndexed
String desc;
Other other;
...
}
public class Other{
String othername;
...
}
My controller has method
#GetMapping("/search")
public Iterable<Global> getByCriteria(#RequestParam("criteria") String criteria) {
...
}
And I am trying to write text search with
public Iterable<Global> findByCriteria(String criteria) {
TextCriteria criteria = TextCriteria.forDefaultLanguage().matching(criteria);
TextQuery query = TextQuery.queryText(criteria);
return mongoTemplate.find(query, Global.class);
}
You need to add #TextIndexed to your other field.
public class Global{
#TextIndexed
String name;
#TextIndexed
String desc;
#TextIndexed
Other other;
...
}
Note: All nested object fields are searchable
or you may add #TextIndexed for each nested object field:
public class Other {
#TextIndexed
String othername;
...
}

Convert a pojo variable to another bean which takes it as list of name and value

I have a bean with set of variables. I want to convert them to another bean say Parameters which has just name and value. I need to make the list of parameters of those all variables in name-value pair.
I am thinking of Dozer or mapstruct but this seems to be not really helpful.
Today, using objectmapper to convert it to maps,iterating over maps and creating the list of parameter.
Any help would be appreciated.
class TestClass{
private String str1;
private String str2;
private String str3;
}
Class Paramters{
private String name;
private String value;
}
**Bean1:**
'[
{
"str1": "string",
"str2": "string",
"str3": "string"
},
{
"str1": "string1",
"str2": "string1",
"str3": "string1"
}
]'
To Convert **Bean2**
'[{
"parameters": [
{
"name": "str1",
"value": "string"
},
{
"name": "str2",
"value": "string"
},
{
"name": "str3",
"value": "string"
}
]
},
{
"parameters": [
{
"name": "str1",
"value": "string"
},
{
"name": "str2",
"value": "string"
},
{
"name": "str3",
"value": "string"
}
]}]'
Mapstruct and the like generally convert from one bean to another, your are essentially trying to convert to a map and wrap that to a bean.
Something like BeanMap would be more appropriate.
Untested sample code:
class Bean2 {
private final Map<String, Object> properties;
public Bean2(Map properties) { this.properties = properties }
public static class Entry { String name, String value /* getters and setters */}
#JsonProperty
public List<Map<String, Object>> getProperties() {
// build a map of maps here, each map would have
}
}
Then just:
new Bean2(new BeanMap(bean2))

how to serialize multi-level json using jackson in spring?

This is the response body that is expected out the endpoint /foo/bar.
As you can see, this is nested json and hence for each level do I require a Java object. what is the efficient way to construct this?. I am using Spring 4.1 which in turn uses Jackson to serialize POJOs.
{
"user": {
"status": {
"state": "active",
"message": [
"registered on 01.10.2015"
]
}
},
"features": {
"xbox": {
"state": "enabled",
"message": [
"foo",
"bar"
]
},
"playstation": {
"state": "disabled",
"message": [
"hello ",
"world"
]
}
}
}
Here is something I have thought
#RequestMapping("foo/bar")
#ResponseBody
public Result getData(long id){
Result result = getUserData(id);
return result;
}
public class Result {
private User user;
private List<Feature> features;
//getters and setters
}
public class Status {
private State state;
private Message messages;
//getters and setteers
}
public class State {
private String state;
//getters and setters
}
public class Message {
private List<String> messages;
//getters and setters
}
Similarly for "features" node, I will construct Java POJO for each level of Json object. I am aware of using objectMapper and JsonNode but wondering if it is possible to effectively construct nested json using java objects.
Classes like State could be an enum, if you know for sure there will only be a limited domain of values. And Message shouldn't be a separate class- just embed List<String> message directly in Status.
If you want a more compact representation, you can always provide your own serializer/deserializer classes to customise the translation.

Resources