在GAE HRD中从Json创建的JDO在实例重新启动之前不会正确转换回Json

时间:2013-03-25 18:35:14

标签: java google-app-engine gson

我正在使用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;
        }
    }
}

DataType类

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}]

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

1 个答案:

答案 0 :(得分: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();
            }
        }
    }
}