3
votes

I have an App-Engine app that compile fine and i test the methods calls using the Google Apis Explorer on localhost (https://developers.google.com/apis-explorer/?base=http://localhost:8888/_ah/api#p/) It works fine and i can test my api method using the Apis Explorer interface but as soon as i add a new Apimethod like

@ApiMethod(name = "users.insertrandomuserv4")
public User insertrandomuserv4() {
    User user = new User("234","myfirstname","mysecondname");
    return user;
}

and i redeploy locally my application, the Apis Explorer didn't show me the list of the different api method. Why? (FYI:When i remove the new method, it works again)

Edit: Here is the rest of my class(yes I use PersistentManager and DataStoreService but it just for testing):

public class UserEndpoint {
@ApiMethod(name = "users.get")
public User get(@Named("key") String key) {
    //Key k = KeyFactory.createKey(User.class.getSimpleName(), key);
    PersistenceManager pm = getPersistenceManager();
    User user = pm.getObjectById(User.class, key);
    pm.close();
    return user;
}

@ApiMethod(name = "users.list")
public List<User> list() {
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();

    Query query = new Query("User");
    //query.setKeysOnly();
    PreparedQuery pq = datastore.prepare(query);
    List<Entity> ls = pq.asList(FetchOptions.Builder.withLimit(500));
    List<User> flist = new ArrayList<User>();
    for (Entity user : ls) {
        User u = new User(user);
        flist.add(u);
    }
    return flist;
}



@ApiMethod(name = "users.insert")
public User insert(User user) {
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    Entity ent = user.toEntity();
    datastore.put(ent);
    return user;
}

@ApiMethod(name = "users.insertrandomuserv4")
public User insertrandomuserv4() {
    User user = new User("234","myfirstname","mysecondname");
    return user;
}




@ApiMethod(name = "users.getuserswithsamehometown")
public List<User> getUsersWithSameHometown(@Named("home")String home) {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    Query query = new Query("User");
    //query.addProjection(new PropertyProjection("firstname", User.class));
    query.setFilter(new Query.FilterPredicate("hometown",FilterOperator.EQUAL,home));
    PreparedQuery pq = datastore.prepare(query);
    List<Entity> ls = pq.asList(FetchOptions.Builder.withLimit(500));
    List<User> flist = new ArrayList<User>();
    for (Entity ent : ls) {
        User u = new User(ent);
        flist.add(u);
    }
    return flist;       
}


private static PersistenceManager getPersistenceManager() {
    return JDOHelper.getPersistenceManagerFactory("transactions-optional").getPersistenceManager();
}
}
1
There's most likely a path collision between your other API methods and the one you added. Can you post the entire class?Dan Holevoet
the others API methods don't have a similar name(another method's name is 'insert', I hope there is no conflict because of this...)VinceFR
(I learned how to use App Engine with your Google I/O video and your slides Dan ;) )VinceFR

1 Answers

5
votes

Yeah, there are path collisions going on here. From my review of your code, I believe there are two collisions: users.get collides with users.getuserswithsamehometown and users.insert collides with users.insertrandomuserv4.

The naming conventions you are using prevent collisions in the API client libraries, but not in the actual paths used to call the APIs. For example, both .get calls map to GET users/{string} and both .insert calls map to POST users.

What you should do is add a path parameter to one of the conflicting methods in each pair. For instance, users.getuserswithsamehometown you could update to:

@ApiMethod(
  name = "users.getuserswithsamehometown",
  path = "users/hometown/{home}",
  httpMethod = "GET"
)

This will give the method a path that no longer conflicts with your other users.get method. You can repeat the process for your conflicting .insert calls, e.g.:

@ApiMethod(
  name = "users.insertrandomuserv4",
  path = "users/random/",
  httpMethod = "POST"
)

I've added httpMethod declarations for good measure. It's generally a good idea to declare these when you start modifying other parts of the path.