2

我正在开发一个使用 Google App-Engine 来存储和管理应用程序数据的 Android 应用程序。不幸的是,我遇到了一个我似乎无法解决的问题。

当用户创建一个新帐户时,会为他们创建一个新的“项目”。该项目包含任务,这些任务存储在 Project 类的一个 ArrayList 中。因此,在项目类的构造函数中,所有内容都被实例化,并且任务是使用 Gson2.2.2 从带有 Json 格式数据的文本文件创建的。
所有这一切都很好,如果我在 appengine 管理控制台中查看数据存储查看器,一切看起来都很好。创建帐户后,用户立即登录,当用户登录时,需要将任务发送到 Android 客户端。这就是它变得奇怪的地方。将任务序列化回 Json 格式时,它们似乎未初始化。所有字符串字段都是空的,并且整数都设置为 0,但是正在序列化正确数量的任务,因此会填充列表。这个问题一直存在,直到我在 GAE 中手动关闭了实例。当它通过新请求重新启动时,数据会正确序列化为 Json 格式,并且一切正常。显然这不好,每次新用户创建帐户时,我都不能让服务器关闭它的实例,只是为了能够为他们提供正确的数据。所以,请帮我解决这个问题。我已经为此苦苦挣扎了一段时间。下面是准确重现问题的代码。

public class CreateData extends HttpServlet{

    public void doGet(HttpServletRequest req, HttpServletResponse resp){
        if(req.getParameter("name").length() > 1){
            PersistenceManager pm = PMF.get().getPersistenceManager();
            User u = new User(req.getParameter("name"));
            pm.makePersistent(u);
            pm.close();
            try {
                resp.getWriter().print("User created with name "+req.getParameter("name"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else if(req.getParameter("name").length() <= 1){
            try {
                resp.getWriter().print("Please supply a name with at least 2 characters");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }else{
            try {
                resp.sendError(400);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

用户类

    public class User {
    public @interface Skip {
        // Field tag only annotation
    }

    @PrimaryKey
    @Persistent
    private String name;

    @Persistent
    private ArrayList<DataType> data;
    public User(String name) {
        this.name = name;
        data = new ArrayList<DataType>();
        createDataFromJSON();
    }

    public String getDatasAsJSON(){
        Gson gson = new GsonBuilder().setExclusionStrategies(new MyExclusionStrategy(Key.class)).create();
        Type taskType = new TypeToken<List<DataType>>(){}.getType();
        String json = gson.toJson(this.data, taskType);
        return json;
    }


    public void createDataFromJSON() {
        FileReader fr = null;
        try {
            fr = new FileReader(new File("WEB-INF/defaults.json"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if (fr != null) {
            Type taskType = new TypeToken<List<DataType>>(){}.getType();
            data = new Gson().fromJson(fr, taskType);
        }
    }

    public class MyExclusionStrategy implements ExclusionStrategy {
        private final Class<?> typeToSkip;

        private MyExclusionStrategy(Class<?> typeToSkip) {
            this.typeToSkip = typeToSkip;
        }

        public boolean shouldSkipClass(Class<?> clazz) {
            return (clazz == typeToSkip);
        }

        public boolean shouldSkipField(FieldAttributes f) {
            return f.getAnnotation(Skip.class) != null;
        }
    }
}

数据类型类

public class DataType {
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key key;

    @Persistent
    private String name;

    @Persistent
    private int points;

    @Persistent
    private int unique;

    public DataType() {
    }

    public DataType(String name, int points, int unique){
        this.name = name;
        this.points = points;
        this.unique = unique;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPoints() {
        return points;
    }

    public void setPoints(int points) {
        this.points = points;
    }

    public int getUnique() {
        return unique;
    }

    public void setUnique(int unique) {
        this.unique = unique;
    }

}

用于获取数据的 Servlet

public class GetData extends HttpServlet{
    public void doGet(HttpServletRequest req, HttpServletResponse resp){
        String name = req.getParameter("name");
        PersistenceManager pm = PMF.get().getPersistenceManager();
        User u = null;
        try{
            u = pm.getObjectById(User.class, name);
        }catch(JDOObjectNotFoundException e){
            try {
                resp.sendError(404);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }

        if(u != null){
            String response = u.getDatasAsJSON();

            try {
                resp.getWriter().print(response);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

和 JSON 数据

[ 
    {
      "name": "Hug",
      "unique": 1,
      "points": 20
    },
    {
      "name": "Tug",
      "unique": 2,
      "points": 40
    },
    {
      "name": "Rug",
      "unique": 3,
      "points": 50
    },
    {
      "name": "Jug",
      "unique": 4,
      "points": 100
    },
    {
      "name": "Smug",
      "unique": 5,
      "points": 20
    }
]

因此,创建一个名为“Arne”的新用户可以正常工作,并且在 HDR 中创建对象。以 Json 的形式从数据存储中请求返回对象会产生此响应

[{"points":0,"unique":0},{"points":0,"unique":0},{"points":0,"unique":0},{"points":0,"unique":0},{"points":0,"unique":0}]

在重新启动服务器实例时,相同的请求会给出此响应

[{"name":"Hug","points":20,"unique":1},{"name":"Tug","points":40,"unique":2},{"name":"Rug","points":50,"unique":3},{"name":"Jug","points":100,"unique":4},{"name":"Smug","points":20,"unique":5}]

很抱歉这篇文章很长,但希望有人能够向我指出我做错了什么。提前谢谢了!最好的问候, 伊瓦尔

4

1 回答 1

0

糟糕的是,似乎没有人能够回答这个问题,尽管我找到了解决方法。我仍然认为这需要一个适当的解决方案,但至少我现在通过循环遍历所有对象并使用对象中字段的值分配一个临时变量来让它工作。这似乎迫使它们进行初始化,并且返回的 JSON 实际上填充了正确的字段。

public class GetData extends HttpServlet{
    public void doGet(HttpServletRequest req, HttpServletResponse resp){
        String name = req.getParameter("name");
        PersistenceManager pm = PMF.get().getPersistenceManager();
        User u = null;
        try{
            u = pm.getObjectById(User.class, name);
        }catch(JDOObjectNotFoundException e){
            try {
                resp.sendError(404);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }

        if(u != null){
            //By adding this seemingly pointless loop
            //the objects will actually return populated fields
            //when converted back to JSON
            for(DataType dt : u.getData()){
                String temp = dt.getName();
            }
            String response = u.getDatasAsJSON();

            try {
                resp.getWriter().print(response);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
于 2013-04-13T13:18:39.800 回答