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

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

}

データ取得用サーブレット

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 に答える