I am trying to create an Android application that interacts with the Google App Engine to download and save objects in google storage. I think I have the correct setup, but I donβt know if I can download my application to check it, it just freezes forever and then gives me this error:
SEVERE: Endpoints configuration not updated. The app returned an error when the Google Cloud Endpoints server attempted to communicate with it.
However, if I change the version number, a new version will appear in my console online even after receiving this message. I read all the google documentation in Datastore and couldn't figure out what was wrong. I had this problem for a month and could not find a solution. I read somewhere that if the application contains an error, it will not load, so I will include all my code. I also donβt know what Iβm doing, Iβm not even sure that I am on the right path, why this does not work, so if you noticed something stupid, please tell me. Thank you in advance, you will become my hero and my god, if you can fix it for me.
Here is my end point:
package com.polo.backend.endpoints; import com.google.api.server.spi.config.Api; import com.google.api.server.spi.config.ApiMethod; import com.google.api.server.spi.config.ApiNamespace; import com.google.api.server.spi.response.ConflictException; import com.google.api.server.spi.response.NotFoundException; import com.googlecode.objectify.Ref; import com.polo.backend.services.ObjcfyService; import com.polo.backend.entities.Event; import com.polo.backend.entities.User; import java.util.List; import javax.inject.Named; @Api( name = "userEndpoint", version = "v1", namespace = @ApiNamespace( ownerDomain = "backend.polo.com", ownerName = "backend.polo.com", packagePath = "" ) ) public class UserEndpoint { public UserEndpoint(){ ObjcfyService.register(User.class); ObjcfyService.register(Event.class); } @ApiMethod(name = "insertUser") public void insertUser(User user) throws ConflictException, NotFoundException{ if(getUser(user.getUsername()) != null){ throw new ConflictException("Object already exists"); } } @ApiMethod(name = "updateUser") public void updateUser(User user) throws NotFoundException{ if(getUser(user.getUsername()) != null) { ObjcfyService.objectify().save().entity(user).now(); } } @ApiMethod(name = "removeUser") public void removeUser(@Named("username") String username) throws NotFoundException{ User record = getUser(username); if(record != null){ ObjcfyService.objectify().delete().entity(record).now(); } } @ApiMethod(name = "getUser") public User getUser(@Named("username") String username) throws NotFoundException{ User user = ObjcfyService.objectify().load().type(User.class).id(username).now(); if(user != null) { List<Ref<User>> friendRefs = user.getFriendRefs(); List<Ref<Event>> repeatingEventRefs = user.getRepeatingEventRefs(); List<Ref<Event>> nonRepeatingEventRefs = user.getNonRepeatingEventRefs(); for (Ref<User> friendRef : friendRefs) { user.addFriend(friendRef.get()); } for (Ref<Event> repeatingEventRef : repeatingEventRefs) { user.addRepeatingEvent(repeatingEventRef.get()); } for (Ref<Event> nonRepeatingEventRef : nonRepeatingEventRefs) { user.addNonRepeatingEvent(nonRepeatingEventRef.get()); } } else{ throw new NotFoundException("User not found"); } return user; } }
Here is my custom object:
package com.polo.backend.entities; import com.google.api.server.spi.config.AnnotationBoolean; import com.google.api.server.spi.config.ApiResourceProperty; import com.googlecode.objectify.Ref; import com.googlecode.objectify.annotation.Entity; import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Index; import com.googlecode.objectify.annotation.Load; import java.util.ArrayList; import java.util.List; import javax.annotation.Nullable; @Entity public class User { @Id private String username = null; @Index private String firstName = null; @Index private String lastName = null; @Nullable private String status = null; @Nullable private String location = null; @Load @Nullable private List<Ref<User>> friendRefs = new ArrayList<>(); @Load @Nullable private List<Ref<Event>> nonRepeatingEventRefs = new ArrayList<>(); @Load @Nullable private List<Ref<Event>> repeatingEventRefs = new ArrayList<>(); @Nullable public List<User> friends = new ArrayList<>(); @Nullable public List<Event> nonRepeatingEvents = new ArrayList<>(); @Nullable public List<Event> repeatingEvents = new ArrayList<>(); public String getFirstName(){ return firstName; } public String getLastName(){ return lastName; } public String getUsername(){ return username; } public void setUsername(String username){ this.username = username; } public void setFirstName(String firstName){ this.firstName = firstName; } public void setLastName(String lastName){ this.lastName = lastName; } @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) public void addFriendRef(User user){ friendRefs.add(Ref.create(user)); } public List<User> getFriends(){ return friends; } public void addFriend(User user){ friends.add(user); } @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) public List<Ref<User>> getFriendRefs(){ return friendRefs; } @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) public List<Ref<Event>> getRepeatingEventRefs(){ return repeatingEventRefs; } @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) public List<Ref<Event>> getNonRepeatingEventRefs(){ return nonRepeatingEventRefs; } @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) public void setStatus(String status){ this.status = status; } public String getStatus(){ return status; } public String getLocation(){ return location; } public void setLocation(String location){ this.location = location; } @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) public void addRepeatingEvent(Event event){ repeatingEventRefs.add(Ref.create(event)); } @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) public void addNonRepeatingEvent(Event event){ nonRepeatingEventRefs.add(Ref.create(event)); } public List<Event> getRepeatingEvents(){ return repeatingEvents; } public List<Event> getNonRepeatingEvents(){ return nonRepeatingEvents; } }
and my Event object:
package com.polo.backend.entities; import com.googlecode.objectify.annotation.Entity; @Entity public class Event { private Integer startIndex; private Integer endIndex; private Byte[] color; public Event(Integer startIndex, Integer endIndex, Byte red, Byte green, Byte blue){ this.startIndex = startIndex; this.endIndex = endIndex; color = new Byte[]{red, green, blue}; } }
and my ObjectifyService:
package com.polo.backend.services; import com.googlecode.objectify.Objectify; import com.googlecode.objectify.ObjectifyFactory; import com.googlecode.objectify.ObjectifyService; public class ObjcfyService { public static void register(Class<?> eClass){ ObjectifyService.register(eClass); } public static Objectify objectify(){ return ObjectifyService.ofy(); } public static ObjectifyFactory objectifyFactory(){ return ObjectifyService.factory(); } }
Here is my appengine-web.xml, I replaced my my_id application for obvious reasons:
<?xml version="1.0" encoding="utf-8"?> <appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> <application>my_id</application> <version>1</version> <threadsafe>true</threadsafe> <system-properties> <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/> </system-properties>
Here is my web.xml
<?xml version="1.0" encoding="utf-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"> <servlet> <servlet-name>SystemServiceServlet</servlet-name> <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class> <init-param> <param-name>services</param-name> <param-value>com.polo.backend.endpoints.UserEndpoint</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>SystemServiceServlet</servlet-name> <url-pattern>/_ah/spi/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list>
Finally, here is the AsyncTask that I use to communicate with the data store from my Android application, I again replaced my application identifier my_id:
package com.polo.client; import android.os.AsyncTask; import android.util.Log; import android.widget.Toast; import com.google.api.client.extensions.android.http.AndroidHttp; import com.google.api.client.extensions.android.json.AndroidJsonFactory; import com.polo.StaticAssets; import com.polo.activity.Home; import com.polo.backend.userEndpoint.UserEndpoint; import com.polo.backend.userEndpoint.model.User; import java.io.IOException; public class UserAsyncTask extends AsyncTask<Void, Void, User>{ private static UserEndpoint userApiService = null; private Home context; private String username; public UserAsyncTask(Home context){ this.context = context; username = StaticAssets.getUserName(context); } @Override protected User doInBackground(Void... params){ if(userApiService == null){ UserEndpoint.Builder builder = new UserEndpoint.Builder( AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null ) .setRootUrl("https://my_id.appspot.com/_ah/api/"); userApiService = builder.build(); } User user = null; try{ user = userApiService.getUser(username).execute(); } catch (IOException e){ Log.e("User not found", e.getMessage()); } return user; } @Override protected void onPostExecute(User result) { if(result!=null) Toast.makeText(context, result.getFirstName(), Toast.LENGTH_LONG).show(); } }