2016-05-16 24 views
5

Tôi đang cố gắng tạo ứng dụng Android tương tác với Google App Engine để tải và lưu các thực thể trong kho dữ liệu của google. Tôi nghĩ rằng tôi có cấu hình chính xác, nhưng tôi không biết liệu tôi có thể tải lên ứng dụng của mình để kiểm tra nó hay không, nó chỉ bị treo vĩnh viễn và sau đó cung cấp cho tôi lỗi này:Không thể kết nối Google Datastore với Ứng dụng Android trong Android Studio

SEVERE: Endpoints configuration not updated. The app returned an error when the Google Cloud Endpoints server attempted to communicate with it. 

Tuy nhiên, nếu tôi thay đổi số phiên bản sau đó phiên bản mới xuất hiện trong bảng điều khiển trực tuyến của tôi ngay cả sau khi nhận được thông báo này. Tôi đã đọc tất cả tài liệu của Google về Datastore và không thể tìm ra điều gì sai. Tôi đã gặp vấn đề này trong một tháng và không thể tìm được giải pháp. Tôi đọc ở đâu đó rằng nếu ứng dụng có lỗi, nó sẽ không được tải lên vì vậy tôi sẽ bao gồm tất cả các mã của tôi. Tôi cũng không thực sự biết những gì tôi đang làm một thậm chí không chắc chắn nếu tôi đang đi đúng hướng vì sao điều này không hiệu quả, vì vậy nếu bạn nhận thấy bất cứ điều gì ngu ngốc, bạn nên vui lòng cho tôi biết. Cảm ơn bạn trước, bạn sẽ là anh hùng của tôi và thần của tôi nếu bạn có thể sửa lỗi này cho tôi.

Đây là thiết bị đầu cuối của tôi:

package com.polo.backend.endpoints; 

/** 
* Created by sagesmith on 4/16/16. 
* 
* Is used to interact with the server 
*/ 

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 { 
    /** 
    * Registers the two entities used in this class 
    */ 
    public UserEndpoint(){ 
     ObjcfyService.register(User.class); 
     ObjcfyService.register(Event.class); 
    } 

    @ApiMethod(name = "insertUser") 
    /** 
     * Inserts a new {@code User} into the data store 
     */ 
    public void insertUser(User user) throws ConflictException, NotFoundException{ 
     if(getUser(user.getUsername()) != null){ 
      throw new ConflictException("Object already exists"); 
     } 
    } 

    /** 
     * 
     * @param user 
     * @throws NotFoundException 
     */ 
     @ApiMethod(name = "updateUser") 
     public void updateUser(User user) throws NotFoundException{ 
      if(getUser(user.getUsername()) != null) { 
       ObjcfyService.objectify().save().entity(user).now(); 
      } 
     } 

     /** 
     * 
     * @param username 
     * @throws NotFoundException 
     */ 
     @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(); 
      } 

     } 

     /** 
     * 
     * @param username 
     * @return 
     * @throws NotFoundException 
     */ 
     @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; 
    } 
} 

Đây là thực thể của tôi User:

package com.polo.backend.entities; 

/** 
* Created by sagesmith on 4/16/16. 
*/ 

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<>(); 

    /** 
    *Returns the first name from the {@code User} 
    * 
    * @return the first name of the {@code User} as a {@code String} 
    */ 
    public String getFirstName(){ 
     return firstName; 
    } 

    /** 
    * Returns the last name from the {@code User} 
    * 
    * @return the last name of the {@code User} as a {@code String} 
    */ 
    public String getLastName(){ 
     return lastName; 
    } 

    /** 
    * Return the username from the user 
    * 
    * @return the username of the user as a String 
    */ 
    public String getUsername(){ 
     return username; 
    } 

    /** 
    * Sets the username of the {@code User} 
    * 
    * @param username Username to set the {@code User}'s username to 
    */ 
    public void setUsername(String username){ 
     this.username = username; 
    } 

    /** 
    * Sets the firstName of the {@code User} 
    * 
    * @param firstName First name to set the {@code User}'s first name to 
    */ 
    public void setFirstName(String firstName){ 
     this.firstName = firstName; 
    } 

    /** 
    * Sets the lastName of the {@code User} 
    * 
    * @param lastName Last name to set the {@code User}'s last name to 
    */ 
    public void setLastName(String lastName){ 
     this.lastName = lastName; 
    } 

    @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) 
    /** 
    * Adds a friend to the {@code User}'s list of friends 
    * 
    * @param user User to add 
    */ 
    public void addFriendRef(User user){ 
     friendRefs.add(Ref.create(user)); 
    } 

    /** 
    * Returns the {@code User}'s friends 
    * 
    * @return {@code List<Users>} the friends of the {@code User} 
    */ 
    public List<User> getFriends(){ 
     return friends; 
    } 

    /** 
    * Adds a friend to the users {@code List} of friends 
    * 
    * @param user {@code User} to add as a friend 
    */ 
    public void addFriend(User user){ 
     friends.add(user); 
    } 

    @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) 
    /** 
    * Returns a {@code List<Ref<User>>} of references to the {@code User}'s friends 
    * 
    * @return {@code List<Ref<User>>} 
    */ 
    public List<Ref<User>> getFriendRefs(){ 
     return friendRefs; 
    } 

    @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) 
    /** 
    * Returns a {@code List<Ref<Event>>} of references to the {@code User}'s repeating 
    * {@code Event}s 
    * 
    * @return {@code List<Ref<Event>>} 
    */ 
    public List<Ref<Event>> getRepeatingEventRefs(){ 
     return repeatingEventRefs; 
    } 

    @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) 
    /** 
    * Returns a {@code List<Ref<Event>>} of references to the {@code User}'s non repeating 
    * {@code Event}s 
    * 
    * @return {@code List<Ref<Event>>} 
    */ 
    public List<Ref<Event>> getNonRepeatingEventRefs(){ 
     return nonRepeatingEventRefs; 
    } 

    @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) 
    /** 
    * Sets the {@code User}'s status to a given {@code String} 
    * 
    * @param status {@code String} to set an {@code Users}'s status to 
    */ 
    public void setStatus(String status){ 
     this.status = status; 
    } 

    /** 
    * Returns the {@code User}'s status as a {@code String} 
    * 
    * @return {@code String} status 
    */ 
    public String getStatus(){ 
     return status; 
    } 

    /** 
    * Returns the {@code User}'s location as a {@code String} 
    * 
    * @return {@code String} location 
    */ 
    public String getLocation(){ 
     return location; 
    } 

    /** 
    * Sets the {@code User}'s location to a given {@code String} 
    * 
    * @param location {@code String} to set an {@code Users}'s location to 
    */ 
    public void setLocation(String location){ 
     this.location = location; 
    } 

    @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) 
    /** 
    * Adds a repeating {@code Event} to the {@code User}'s schedule 
    * 
    * @param event {@code Event} to add to the {@code User}'s schedule 
    */ 
    public void addRepeatingEvent(Event event){ 
     repeatingEventRefs.add(Ref.create(event)); 
    } 

    @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) 
    /** 
    * Adds a non repeating {@code Event} to the user's schedule 
    * 
    * @param event Event to add to the the user's schedule 
    */ 
    public void addNonRepeatingEvent(Event event){ 
     nonRepeatingEventRefs.add(Ref.create(event)); 
    } 

    /** 
    * Returns a {@code List<Event>} of repeating {@code Event}s from the user's schedule 
    * 
    * @return List<Event> repeatingEvents from user's schedule 
    */ 
    public List<Event> getRepeatingEvents(){ 
     return repeatingEvents; 
    } 

    /** 
    * Returns a list of nonRepeatingEvents from the user's schedule 
    * 
    * @return List<Event> repeatingEvents from user's schedule 
    */ 
    public List<Event> getNonRepeatingEvents(){ 
     return nonRepeatingEvents; 
    } 
} 

và đơn vị tổ chức sự kiện của tôi:

package com.polo.backend.entities; 

import com.googlecode.objectify.annotation.Entity; 
/** 
* Created by sagesmith on 5/3/16. 
*/ 
@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}; 
    } 
} 

và ObjectifyService tôi:

package com.polo.backend.services; 

/** 
* Created by sagesmith on 4/16/16. 
*/ 
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(); 
    } 
} 

Sau đây là tôi appengine-web.xml, tôi đã thay thế APPID tôi với my_id vì những lý do rõ ràng:

<?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> 

Đây là web.xml của tôi

<?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> 

Cuối cùng ở đây là AsyncTask tôi sử dụng để liên lạc với kho dữ liệu từ ứng dụng Android của tôi, tôi đã thay thế ID ứng dụng của mình bằng my_id lần nữa:

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; 
/** 
* Created by sagesmith on 4/17/16. 
*/ 
public class UserAsyncTask extends AsyncTask<Void, Void, User>{ 
    private static UserEndpoint userApiService = null; 
    private Home context; 
    private String username; 

    /** 
    * 
    * @param context 
    */ 
    public UserAsyncTask(Home context){ 
     this.context = context; 
     username = StaticAssets.getUserName(context); 
    } 

    /** 
    * 
    * @param params 
    * @return 
    */ 
    @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; 
    } 

    /** 
    * 
    * @param result 
    */ 
    @Override 
    protected void onPostExecute(User result) { 
     if(result!=null) 
      Toast.makeText(context, result.getFirstName(), Toast.LENGTH_LONG).show(); 
    } 
} 
+0

Tôi hỏi một đồng nghiệp và ông nghĩ rằng nó là một cái gì đó để làm với bất cứ điều gì tương đương với Java là cho app.yaml –

Trả lời

2

Nó giúp để có một cái nhìn tại các thông báo lỗi đầy đủ mà khuyên:

See the deployment troubleshooting documentation for more information: https://developers.google.com/appengine/docs/java/endpoints/test_deploy#troubleshooting_a_deployment_failure

Các tài liệu tư vấn để kiểm tra các bản ghi của bạn cho '/_ah/spi/BackendService.getApiConfigs' như một bước đầu tiên. Nếu tôi cố gắng để triển khai một backend thiết bị đầu cuối dựa trên mẫu tôi thấy như sau trong nhật ký của tôi:

javax.servlet.ServletContext log: unavailable 
java.lang.reflect.InvocationTargetException 
    at com.google.appengine.runtime.Request.process-b693af604777a85a(Request.java) 
    ... 
Caused by: java.lang.StackOverflowError 
    ... 
    com.googlecode.objectify.impl.translate.ClassTranslatorFactory.create(ClassTranslatorFactory.java:49) 
    ... 

Lỗi này chỉ xảy ra trên các cuộc gọi đến ObjectifyService.register(class), hmm ...

Có điều gì đó trong lớp User của bạn mà có thể gây ra đệ quy vô hạn khi làm thành khách quan cố gắng để đăng ký lớp học và kết quả là một StackOverflowError:

@Nullable public List<User> friends = new ArrayList<>(); 

Thay vì xác định một danh sách riêng của mình, bạn có thể sửa lỗi này bằng cách định nghĩa một danh sách các Ref<User> như được thực hiện ở những nơi khác trong lớp (có thể ở trên là một typo):

@Nullable public List<Ref<User>> friends = new ArrayList<>(); 

Ngoài ra, một vấn đề khác là do lớp Event thiếu một @ Id, có thể cố định như sau:

@Entity 
public class Event { 
    @Id private Long id; 
    ... 

Sau khi thực hiện những thay đổi này, tôi có thể triển khai các thiết bị đầu cuối ứng dụng mà không cần bất kỳ lỗi nào.

+0

Yup, đó là vấn đề của tôi \ @Entity public class Person { @ id dài id; Tham chiếu referBy; // chỉ là người được giới thiệu; } Cảm ơn bài đăng –

Các vấn đề liên quan