Изучаю/работаю с Google App Engine для Java.
Выбрал Java и JDO как среду разработки из-за удобного описания структуры данных прямо в коде (для проектов средней сложности более чем удобно), но, похоже именно это создает больше проблем чем удобств.
Помимо самих особенностей и 'неудобств' по работе с datastore (это все таки key-value база данных) столкнулся с тем что похоже нет никаких гарантий, что записанное несколькими секундами ранее будет доступно сейчас, мало того, без каких либо ошибок запись может вообще не произойти.
* Простейший пример: объект Test {id, amount}, необходимо создать 1 экземпляр, если он еще не был создан, и при каждом вызове сервлета увеличивать amount на 1.
Версия sdk 1.5.2, windows 7. Проект создается по умолчанию в eclipse с установленным google appengine plugin + создаем файл Test.java и изменяем TestServlet.java, код тут
paste.ly/B44n
Вот какой вывод получается:
# curl localhost:8888/test
Test is empty
OK
# curl localhost:8888/test
Test length:1
Test[1]: 1
OK
# curl localhost:8888/test
Test length:1
Test[1]: 1
OK
# curl localhost:8888/test
Test length:1
Test[1]: 2
OK
# curl localhost:8888/test
Test length:1
Test[1]: 3
OK
# curl localhost:8888/test
Test length:1
Test[1]: 4
OK
# curl localhost:8888/test
Test length:1
Test[1]: 4
OK
А в логах сервера:
22.08.2011 14:29:13 com.google.appengine.tools.development.DevAppServerImpl start
INFO: The server is running at localhost:8888/
22.08.2011 14:29:17 test.TestServlet doGet
WARNING: new amount: 1
22.08.2011 14:29:18 test.TestServlet doGet
WARNING: add amount: 2
22.08.2011 14:29:20 test.TestServlet doGet
WARNING: add amount: 2
22.08.2011 14:29:22 test.TestServlet doGet
WARNING: add amount: 3
22.08.2011 14:29:23 test.TestServlet doGet
WARNING: add amount: 4
22.08.2011 14:29:24 test.TestServlet doGet
WARNING: add amount: 5
22.08.2011 14:29:30 test.TestServlet doGet
WARNING: add amount: 5
Обратите внимание, между вызовами было прилично времени, секунды… компьютер совсем не нагруженный, достаточно мощный (4-ядерный феном с 8гб озу), но по каким то причинам, далеко не при каждом вызове информация об увеличении Test.amount сохранялась.
К тому же во время тестов у меня встречались ситуации, когда созданная ранее запись просто не отображалась в результате запроса select, соответственно в данном случае создавались несколько записей. Понятно в правильной реализации конкретно этой задачи можно было бы заранее (в коде) самостоятельно определить уникальный ключ объекта, но само собой это не всегда возможно!
p.s. почти наверняка я в коде допустил какую то совершенно нубскую ошибку, но не могу понять какую.
p.p.s. использование метода класса Test — public void addAmount() {this.amount++;} не решило проблемы, явно причина где то в сохранении данных в базе, но я не пойму как принудительно сохранить изменения, по документации это должно происходить при pm.close() или pm.makePersistent(...)