I am using Google App engine1.9.3, Eclipse, Objectify5.03. My Class is as follows:
import com.googlecode.objectify.Ref;
import com.googlecode.objectify.annot
ApiResourceProperty annotation does not work for Google Emdpoints+Objectify combinations as Ref or Key is Objectify specific class and Google Endpoints does not recognize them and will give a error when you try to generate the Client Libraries. I changed the User class as below.
@Id private Long userId;
@Index private String userName;
@Load private UserDetails userDetails;
@Load private UserPassword userPassword;
@Load private ArrayList<Account> userAccounts;
//getters and setters
When I retrieve the user by user name as below, I get the User, UserDetails, UserPassword and also the list of User accounts thru the getters (in one shot)
@ApiMethod(name = "getUserByName", path = "get_user_by_name")
public User getUserByName(@Named("userName") String userName) {
User user = null;
try {
user = ofy().load().type(User.class).filter("userName", userName).first().now();
if(user != null)
log.info("UserEndpoint.getUserByName...user retrieved="+user.getUserId());
else
log.info("UserEndpoint.getUserByName...user is null");
} catch(Exception e) {
log.info("UserEndpoint.getUserByName...exception="+e.getMessage());
}
return user;
}
When I use the Datastore Viewer on Google Console to view the data, I see some entries in the userDetails, userPassword and Accounts columns in the User table. I assume that these are references to the actual data in their respective tables and not a copy of the data itself. Hope this helps.
Google Cloud Endpoints is unable to serialise the Ref
object because it is an arbitrary object defined by objectify
, therefore not supported as the error indicates.
This is known limitation with Cloud Endpoints in that it does not allow custom objects to be used. There is a whole discussion thread on this point in particular if you're interested: Cloud endpoints .api generation exception when using objectify (4.0b1) parameterized key
You will have to annotate your methods with @ApiResourceProperty
and set its ignored attribute to true
as illustrated in the code below:
import com.googlecode.objectify.Ref;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Load;
import com.google.api.server.spi.config.AnnotationBoolean;
import com.google.api.server.spi.config.ApiResourceProperty;
@Entity
public class User
{
@Id private Long userId;
private String userName;
@Load private Ref<UserDetails> userDetails;
@Load private Ref<UserPassword> userPassword;
//getters & setters
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
public UserDetail getUserDetails(){
}
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
public UserPassword getUserPassword(){
}
}
If you still want to use the data held in those objects then consider adding some fields to your class to hold the data and initialise them after your User
class has finished loading like so:
@Ignore String firstName;
@OnLoad
void trackUserDetails()
{
this.firstName = getUserDetails().getFirstName();
// add more code here to set other fields, you get the gist
}
But in my opinion a better approach would be to reconsider the design of your class, or rather rethink what you're trying to do.