I want to pass a List of objects to one of my functions.
Here's the code:
#RequestMapping(value = "/pages/generateReports")
public ModelAndView toGenerateReports(#ModelAttribute("forReports") #Valid Reports report){
List<Patients> patients = patientsDAO.listAllPatients(report.getDateFrom(), report.getDateTo());
//tried printing what's in patients and surely it contains something
GenerateReports reports = new GenerateReports();
reports.generateReports(patients);
return ...;
}
public class GenerateReports {
public void generateReports(List<? extends Patients> patients) {
....some checkings here and all I get is an empty list...
}
}
What do I have to do to make it work?
Your code looks good to me, it should work. You can change List<? extends Patients> patients to List<Patients> patients but that should not change anything.
Related
I have this class hierarchy:
#Data // Lombok
public class CarInfo {
private String brand;
private String model;
}
public class CarFullInfo extends CarInfo {
private Integer horsepower;
private String engineType;
}
I need to develop REST API, where I can ask for a list of all cars, where is only CarInfo fields are returned, and there is another extended query, that returns list of CarFullInfo - extended, with 4 fields total.
I store all data in memory (I need to do it this way for some reason) as a collection of CarFullInfo objects, and I'm trying to figure out how can I reduce two extra fields if I'm not asked to return full info.
First my assumption was to find some JSON appropriate annotation to do this some way, but I failed.
Another try was just to cast subclass to superclass and return list of superclass objects from rest controller, but that also didn't work. I assume that happened cause THEY KNOW actual objects class and THEY SEE all it's fields.
#GetMapping("/cars")
public ResponseEntity<List<? extends CarInfo>> getCars(...) {
List<CarFullInfo> select = ...
List<CarInfo> skimpy = select.stream().map(car -> (CarInfo)car).collect(Collectors.toList());
return new ResponseEntity<>(skimpy, HttpStatus.OK);
}
Thus, my last idea was to create a new list of CarInfo and copy only it's fields - excluding CarFullInfo fields, but when number of fields grows - it gets cumbersome to do this:
CarFullInfo cfi = ...
CarInfo carInfo = new CarInfo(cfi.getBrand(), cfi.getModel(), cfi.getCountry(), cfi.getGeneration(), cfi.getModification() and more, and more)
I'm feeling there is some elegant way to do what I need. Direct me please.
Thank you!
#JsonView should help you. Take a look at the examples here - https://www.baeldung.com/jackson-json-view-annotation
And you can use BeanUtils
#Service
public class CarService {
List<CarFullInfo> someCars = Collections.singletonList(new CarFullInfo("Opel", "Cadet", 75, "oil"));
public List<CarFullInfo> getFullCarInfo() {
return someCars;
}
public List<CarInfo> getCarInfo() {
return someCars
.stream()
.map(this::toCarInfo)
.collect(Collectors.toList());
}
private CarInfo toCarInfo(CarFullInfo carFullInfo) {
CarInfo carInfo = new CarInfo();
BeanUtils.copyProperties(carFullInfo, carInfo);
return carInfo;
}
}
I am hoping to get some direction on how to resolve this issue. I am working with a Third Party API get JSON data. It has a structure similar to:
{items: [
{attribute : Value},
{attribute : Value}]
count : value,
etc
}
The items array can hold different data, so I have a class:
public Items<T> {
private List<T> items;
// Others API Variables
public List<T> getItems(){
return items;
}
public void setItems(List<T> items){
this.items = items;
}
// Other Getters/Setters
}
What I am trying to do in the calling class is:
public CallingClass {
public void Method(){
//Code to get reader object
Items<User> userItems = Gson().fromJson(ReaderObject, Items.class);
//Other processing code
}
}
And I get the error:
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to User.class
I was reading through this post and I think the solution is similar to what I need but I don't know who to do it. My though was to have a single Items class that could be passed the different Types which are returned.
Thoughts, assistance, anything would be helpful.
EDIT:
OK So I feel like an idiot now, but some sleep helped. The solution was in the link I posted, I was just didn't need a list. My coded solution is as follows:
public CallingClass {
public void Method(){
//Code to get reader object
Items<User> userItems = Gson().fromJson(ReaderObject, new TypeToken<Items<User>>(){}.getType());
//Other processing code
}
}
OK So I feel like an idiot now, but some sleep helped. The solution was in the link I posted, I was just didn't need a list. My coded solution is as follows:
public CallingClass {
public void Method(){
//Code to get reader object
Items<User> userItems = Gson().fromJson(ReaderObject, new TypeToken<Items<User>>(){}.getType());
//Other processing code
}
}
I have a method in a Java class with signature like below and I want to add Swagger Rest documentation for it.
public List<List<MyCustomClass>> getMyCustomClasses(String id){
//
}
I want to know if there is a way to have either response or responseContainer to return List of List objects?
Something like below?
#ApiOperation(value = "find MyCustomClass objects by id", response =MyCustomClass.class , responseContainer = "List<List>")
I have no issues in generating swagger docs if the response of the method is just List
where I could specify response =MyCustomClass.class , responseContainer = "List" but having problem only if it is List of List as return type.
Thanks
Ravi
In order to do this you can simply create a template class like this:
public class TempClass {
private List<someClass> listOfClass;
public List<someClass> getListOfClass() {
return listOfClass;
}
public void setListOfClass(List<someClass> listOfClass) {
this.listOfClass = listOfClass;
}
}
or even more complicated like this:
public class TempClass {
private List<List<List<someClass>>> listOfList;
public List<List<List<someClass>>> getListOfList(){
return listOfList;
}
public void setListOfList(List<List<List<someClass>>> listOfList) {
this.listOfList = listOfList;
}
}
And at the end get this class as a response to the annotation above the method like this:
#ApiOperation(response = TempClass.class)
you should also specify the return type of the method as the TempClass
There is another issue that discussed a same issue here
I want to create an object of child class
more than 100 class extend MasterClass
MasterClass is
public class MasterClass{
int key;
String value;
String displayValue;
boolean status;
}
public class User extends MasterClass{
public User(){ }
}
public class Customer extends MasterClass{
String productName;
public Customer (){ }
}
etc...
i will get a MasterClass object from client, i wanted to type cast that object to respective one
if(masterClass instanceof User) {
User a_user = (User) a_ masterClass;
…
} else if(masterClass instanceof Customer) {
Customer a_customer = (Customer) a_ masterClass;
…
}
if i do this i will end up with 100s of else if.
Please let me know how i can achieve this without else if?
Thanks in advance.
Use polymorphism and generics, as Java intended.
Polymorphism lets you call a method on your object that behaves differently for every type. The easiest way to achieve this is to provide an abstract method in the base class MasterClass and then override it with different functionality in every extended class. You are probably looking for something like this:
class MasterClass {
int age;
// ...
public abstract void doWork();
public int getAge() { return age; }
// .. more methods
}
class User extends MasterClass {
// customize User here
#Override
public void doWork() { /* User does work in some way */ }
}
class Customer extends MasterClass {
// customize Customer here
#Override
public void doWork() { /* Customer does work in some other way */ }
}
// ...
If you are not too familiar with OOP, here is a good introductory tutorial.
If you are not allowed to alter your classes, you can populate a look-up table like HashMap<Class, MyFunctor> where you can assign a different functor for every type of person you have.
Also, you might want to use generics. Generics allow you to capture and restrict the type of objects passed to your methods.
Maybe you can use generics with the constraint T extends MasterClass?
Using basic concepts of Design Pattern you can create a constructor like this in the object where you try to initialize
MasterClass masterClass;
public MyCreatorOject(MasterClass masterClass)
{
this.masterClass = masterClass;
}
later when you create the object it can be
new MyCreatorObject(new User());
or
new MyCreatorObject(new Customer());
I'm working on a project where i have 3 different classes creating objects CommissionEmployee, SalariedEmployee and HourlyEmployee. I need to add these to an arraylist in the main class, but not sure where i'm going wrong.
public class Company {
public String companyName;
public SalariedEmployee owner;
public ArrayList<SalariedEmployee> salariedEmployee;
public ArrayList<HourlyEmployee> hourlyEmployee;
public ArrayList<CommissionEmployee> commissionEmployee;
public Company (String companyName, SalariedEmployee owner){
this.companyName = companyName;
this.owner = owner;
}
public void addSalariedEmployee (SalariedEmployee SalariedEmployee){
salariedEmployee.add(SalariedEmployee); **
}
public void addHourlyEmployee (HourlyEmployee HourlyEmployee){
//HourlyEmployee = new HourlyEmployee (name, position, ratePerHour);
hourlyEmployee.add(HourlyEmployee);
}
public void addCommissionEmployee (CommissionEmployee CommissionEmployee){
//CommissionEmployee = new CommissionEmployee (,, ratePerItem);
commissionEmployee.add(CommissionEmployee);
}
** = this is the line where my editor is telling me i'm going wrong.
Cheers, any help will be appreciated
You've attempted to name the parameter the same as your class name. A class name is not acceptable as a parameter name. Name the parameter something different. Even something of different case would be good, e.g.:
public void addSalariedEmployee (SalariedEmployee salariedEmployee){
Because you have two variables with the same name in that line (i.e. salariedEmployee). Here is the fix for you:
public void addSalariedEmployee (SalariedEmployee aSalariedEmployee){
salariedEmployee.add(aSalariedEmployee);
}
you are using class name as parameter name. it should be different case or any other name instead of class name.
but it is better to have camel case name.
just example:
public void addSalariedEmployee (SalariedEmployee salariedEmployee)
Your method parameter is SINGLE OBJECT. You are trying to put a LIST not an object. You have to change your method parameter
When youll changed, here's an example to deal with the iterator objects.
public static void main(String[] args) {
Curso curso=new Curso();
Evento evento=new Evento();
Publicacion publicacion=new Publicacion();
List objectList = new ArrayList();
objectList.add(curso);
objectList.add(evento);
objectList.add(publicacion);
for(Object o:objectList){
if(o instanceof Curso){
//do some thing
}
if(o instanceof Evento){
//do some thing
}
if(o instanceof Publicacion){
//do some thing
}
}
}
Remember that JAVA works with objects and everyting its a object. Regards