ResponseEntity returns null list of objects - spring

I am able to consume an API who returns a json object. What I am trying to do is to get a list of objects instead. Below is my code for the same:
ResponseEntity<List<Entity>> responseEntity = restTemplate.exchange(dataUrl, HttpMethod.GET, entity,new ParameterizedTypeReference<List<Entity>>() {});
where Entity of an object of which I am expecting a list to be populated with data from json. But when I print it, all fields from Entity has null value set. What am I missing?
Thanks
Sach

Can you try with this
ResponseEntity<List<Entity>> responseEntity = restTemplate.exchange(dataUrl, HttpMethod.GET, entity, Entity.class);
p.s. sorry don't have reputation for comment :(

Why don't use restTemplate.getForEntity?
ResponseEntity<Entity[]> response = restTemplate.getForEntity(dataUrl, Entity[].class)
Entity[] entities = response.getBody();
The above case returns an object of type Entity[], which is an array.
If you want to use the List interface, you will need to create a wrapper class.
The wrapper:
public class EntityList {
private List<Entity> entities;
public EntityList() {
entities= new ArrayList<>();
}
// standard constructor and getter/setter
}
The RestTemplate call:
Here you will use restTemplate.getForObject
EntityList response = restTemplate.getForObject(dataUrl, EntityList.class);
List<Entity> entities = response.getEntities();
Even a simpler alternative is to use List.class as the return type of getForObject.
List<Entity> response= rest.getForObject(dataUrl, List.class);

It is hard to give a correct answer due to a missing json example. Could you please provide a sample of the json that will be returned.

RESOLVED
Below is the code change I did which was returning correct list of Entity objects.
ResponseEntity<Entity[]> responseEntity = restTemplate.exchange(dataUrl, HttpMethod.GET, entity, Entity[].class);
Even after making this change didnt really solved my issue. I also had to add
#JsonProperty("fieldName") on each field in Entity class which had to match Json properties.

Related

Why can't I use .orElseThrow() method on an Entity?

The following method works.
#GetMapping("/usuarios/{codigo_us}")
EntityModel<Usuario> one(#PathVariable Long codigo_us) { //HATEOAS way of forwarding resources
Usuario usuario = repository.findById(codigo_us)
.orElseThrow(() -> new UsuarioNotFoundException(codigo_us));
// Spring WebMvcLinkBuilder
return assembler.toModel(usuario);
}
But when I try a slightly different approach it doesn't work.
#GetMapping("/usuarios/{cedula_us}")
EntityModel<Usuario> getByCedula(#PathVariable Long cedula_us){
Usuario usuario = repository.findByCedula_us(cedula_us).get(0)
.orElseThrow(() -> new UsuarioNotFoundException(cedula_us));
return assembler.toModel(usuario);
Different classes have different methods available.
The first method returns an Optional<Usuario> which has method orElseThrow()
The second method returns some kind of Iterable/List/Collection, on which you call get(0) which grabs the first element Usuariobut no longer wrapped in Optional. Therefore there is no orElseThrow() available.
You can achieve the same thing for second method by wrapping it into optional:
Usario usario = repository.findByCedula_us(cedula_us).get(0);
usario = Optional.ofNullable(usario).orElseThrow(...
This is just an example to clarify how it works, a better approach would be to add a method in the repository itself to only return first result and return optional, something like:
Optional<Usario> findFirstByCedula_us(String cedula_us)
The return value of findByCedula_us method is not optional it should be like this
Optional<Usario> findByCedula_us(Long cedula_us);

Spring , update value if not null

I am working with Redmine API, and want to update an issue.
The issue has 30 variables, Subject, Description, Author, and Assignee ...
I have no problem updating the issue Subject and Description like this:
#RequestMapping(value = "/issues/update/{id}", method = RequestMethod.PUT)
public ResponseEntity<Object> issueUpdate(#RequestBody ObjectNode json, #PathVariable int id) throws RedmineException, RuntimeException, IllegalArgumentException {
String apiKey = json.get("API_KEY").asText();
RedmineManager mgr = RedmineManagerFactory.createWithApiKey("http://localhost:3001/", apiKey);
IssueManager issueManager = mgr.getIssueManager();
Issue issue = issueManager.getIssueById(id);
issue.setSubject(json.get("SUBJECT").asText())
.setDescription(json.get("DESCRIPTION").asText())
.update();
return new ResponseEntity<>(HttpStatus.OK);
}
The problem with this way is I am only allowed to change these 2 values and I have to include, SUBJECT and DESCRIPTION in my JSON request body.
If SUBJECT is not in JSON, then it will be considered as null and I get NullPointerException.
I want to make something more flexible and elegant, to allow the change of each value, and if not exist, don't set to null but keep the old values.
something logical to this but a bit smarter
if json.get("SUBJECT").asText() != null {
issue.setSubject(json.get("SUBJECT").asText()) //set if mentioned
} else {
issue.setSubject(issue.getSubject()) //set the old value
}
The idea is, now am available to have setSubject and all the other available setters in case it's mentioned in my JSON request or not.

I want to get the findAndModify return value of MongoTemplate as a modified value

I am currently using mongoTemplate in Spring boot like this:
public MyEntity update(MyDto dto) {
...
MyEntity result = mongoTemplate.findAndModify(
query, update, MyEntity.class);
return result;
}
query puts in the Criteria that finds the MyEntity to be modified, and update puts the contents to change. However, the returned value is the data before the update. How can I get the modified value right away?
When using findAndModify on the mongoTemplate, you have to explicitly configure it if the updated record shall be returned instead of the original one.
This may be done the following way:
FindAndModifyOptions findAndModifyOptions = FindAndModifyOptions.options().returnNew(true);
MyEntity result = mongoTemplate.findAndModify(query, update, findAndModifyOptions, MyEntity.class);
return result;
https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/

ResponseEntity return type wildcard with swagger generated interface

I want to know the difference between returning ResponseEntity<?> with wildcard VS ResponseEntity<ABC.class> as return type when Swagger generated API interface contains 2 different classes as return types, i.e one for an exception and another for normal flow.
My controller interface is :-
#Operation(summary = "Get user by user name", tags = { "user" })
#ApiResponses(value = {
#ApiResponse(responseCode = "200", description = "successful operation", content = #Content(schema = #Schema(implementation = User.class))),
#ApiResponse(responseCode = "400", description = "Invalid username supplied", content = #Content(schema = #Schema(implementation = Error.class)))
})
#GetMapping(value = "/user/{username}", produces = { "application/xml", "application/json" })
ResponseEntity<?> getUserByName(#PathVariable("username") String username);
the #Schema defines return type.
Can I use ResponseEntity<User> instead of the <?> for the getUserByName method ?
I have the the global exception handler #ControllerAdvice in my application which returns ResponseEntity<Error> .
Answer for your question is simply Yes. Since you are using a Controller Adviser, you can directly define the endpoint return type as User in ResponseEntity
Using a Wildcard(ResponseEntity<?>) as a return type, the symbol ? defines that the return value of the controller method can be any type of ResponseEntity.
Using as ResponseEntity<?> or simply keep it as ResponseEntity<> are considered as raw type of its usage.
But really it is not a good practice to do so. So, you have to declare the exact return type of the controller method in this format ResponseEntity<ABC>.
Let's take this example java of method returning a list of objects(List<Object>).
It is possible on this list to add a Car.class type, a Van.class type. But how ever the consumer of a method should not have to deal with such disruptive questions and we have to define an exact type.
Yes you can use ResponseEntity<User> if your method returns a User type ResponseEntity.
I hope this'll help you to solve the issue :)

Dropwizard deserializing generic list from JerseyClient

I wanted to implement a generic class to use for caching results from a REST API in a local MongoDB-instance. For this to work, I need to deserialize a collection I get from JerseyClient:
Response response = this.source.request().get();
List<T> list = response.readEntity( new GenericType<List<T>>() {} );
// ... do stuff with the list
Let's say I'm using this piece of code in a context of T relating to a class Foo. The really weird thing is, after the readEntity call, list is not a List<Foo>, instead is a List<LinkedHashMap>. How is that even possible, when I've clearly declared the Generic T to be Foo?
What do I have to do to get a proper List<T>, i.e. List<Foo> instead?
Note: If I remove the generic, and use
List<Foo> list = response.readEntity( new GenericType<List<Foo>>() {} );
directly instead, it works fine, but I really need that generic to be there!
Java's most popular excuse for Generics: Type Erasure
If you can pass your class type as Class<T> clazz, then you can use this:
GenericType<List<T>> genericType = new GenericType<>(new ParameterizedType() {
public Type[] getActualTypeArguments() {
return new Type[]{clazz};
}
public Type getRawType() {
return List.class;
}
public Type getOwnerType() {
return null;
}
});
response.readEntity(genericType);
You can use
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
import javax.ws.rs.core.GenericType;
GenericType<List<T>> genericType = new GenericType<>(
ParameterizedTypeImpl.make( List.class, new Type[]{classType}, null));

Resources