Hi have two related Entities: Customers and Cars. Each Customer can own several Cars
This is a summarized view of the entities:
public class Customer
{
//Inner classes for partial loads
public static class NoCars{}
@Id protected String id;
private String fullName;
@Load(unless=NoCars.class) private List<Ref<Car>> cars;
}
public class Car
{
@Id private Long id;
private String makeAndModel;
private String plateNumber;
}
And this is a method that retrieves a Customer from datastore and all the Cars he owns:
public Customer getCustomer(@Named("id") String customerId)
{
Customer customer = ofy().load().type(Customer.class).id(customerId).now();
if (customer==null)
throw new NotFoundException("customer not found");
else
return customer;
}
endpoints.sh cannot implement this, as the type List <Ref<Car>>
included in the return type Customer is not supported, but I found this funny workaround:
I created the class CustomerPOJO
public class CustomerPOJO
{
private String fullName;
}
and modified the class Customer
to extend from it
public class Customer extends CustomerPOJO
{
//Inner classes for partial loads
public static class NoCars{}
@Id protected String id;
@Load(unless=NoCars.class) private List<Ref<Car>> cars = new ArrayList<>();
}
and the getter method to be:
public CustomerPOJO getCustomer(@Named("id") String customerId)
{
Customer customer = ofy().load().type(Customer.class).id(customerId).now();
if (customer==null)
throw new NotFoundException("customer not found");
else
return customer;
}
Note that the method declares CustomerPOJO
as return type, but it actually returns a "full" Customer
!!!
This works in AppEngine 1.8.0 + Objectify 4.0 RC2. It gets the customer data and all the cars he owns with their properties (makeAndModel
and plateNumber
) in a single call.
The issue came after upgrading to 1.8.9. endpoints.sh still works, as the return type is fully compatible, but i get an exception at runtime, when parsing the Customer objecto to JSON.
java.io.IOException: com.google.appengine.repackaged.org.codehaus.jackson.map.JsonMappingException: Direct self-reference leading to cycle (through reference chain: entity.Customer["cars"]->java.util.ArrayList[0]->com.googlecode.objectify.impl.ref.LiveRef["key"]->com.googlecode.objectify.Key["root"])
Any other workaround that works in 1.8.9? Is @ApiTransformer the only choice?
The solution was pretty simple... Just hide the Ref field. It does now provide any value to the API consumer and it just create trouble to the parser:
I replaced the List<Ref<Car>>
getter and setter by:
public List<Car> getCars()
{
List<Car> ret = new ArrayList<>();
Iterator<Ref<Car>> it = cars.iterator();
while (it.hasNext())
ret.add(it.next().getValue());
return ret;
}
public void setCars(List<Car> newCars)
{
Iterator<Car> it = newCars.iterator();
while (it.hasNext())
addCar(it.next());
}
That's all
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With