#java #google-app-engine #web-applications #jdo
#java #google-app-engine #веб-приложения #jdo
Вопрос:
У меня есть сервлет, который сохраняет загружаемый людьми код. Они могут загружать несколько файлов кода, ключи которых затем сохраняются в коллекции кода. Все работает ровно для одного запроса. После первого запроса класс Code JDO не сохраняется без сбоев. Беззвучно, поскольку нигде в приложении нет ни одного исключения, даже при использовании транзакций он считает, что передача данных закрыта и зафиксирована.
Вот что я делаю:
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
List<Key> uploadedCodeKeys = new ArrayList<Key>();
List<Code> uploadedCode = new ArrayList<Code>();
if(req.getParameterValues("code") == null) {
resp.sendRedirect("/");
}
for(int i = 0; i < req.getParameterValues("code").length; i ) {
String pastedCode;
String language;
String fileName;
try {
language = req.getParameterValues("language")[i];
pastedCode = req.getParameterValues("code")[i];
fileName = req.getParameterValues("filename")[i];
if(pastedCode == null || pastedCode.equals("")) {
pastedCode = "";
}
if(language == null) {
language = "Plain Text";
}
if(fileName == null) {
fileName = "Untitled";
}
} catch (Exception e) {
}
Code code = new Code(pastedCode, language);
code.setFileName(fileName);
uploadedCodeKeys.add(code.getKey());
uploadedCode.add(code);
}
PersistenceManager pm = GAEModel.get().getPersistenceManager();
Transaction tx = pm.currentTransaction();
long id = 0;
try {
tx.begin();
log.info("Attempting to save " uploadedCode.size() " files");
pm.makePersistentAll(uploadedCode);
tx.commit();
if(tx.isActive()) {
log.severe("Failed to save code files!");
tx.rollback();
pm.close();
return;
}
CodeCollection cc = new CodeCollection(uploadedCodeKeys);
pm.makePersistent(cc);
id = cc.getKey().getId();
} catch(Exception e) {
log.log(Level.SEVERE, "Failed to save files!", e);
} finally {
pm.close();
}
Я присваиваю коду строковый хэш или что-то в этом роде, это не дубликат. Я перепробовал почти все варианты последних нескольких строк, которые сохраняются, о которых я могу думать. Коллекция кодов сохраняется каждый раз с идентификаторами файлов несуществующего кода.
Спасибо
Также здесь представлены журналы фиксации, которая завершается с ошибкой на уровне отладки:
ms = 115 cpu_ms = 168 api_cpu_ms = 98 cpm_usd = 0.004754 I 2011-05-24 20:54:17.424 com.mikehershey.paste.server.URLDispatcher doFilter: загрузка pageUpload I 2011-05-24 20:54:17.428 org.datanucleus.Закрытие ObjectManagerImpl: в хранилище данных I зафиксировано обновление, не связанное с tx 2011-05-24 20:54:17.482 org.datanucleus.Закрытие ObjectManagerImpl: в хранилище данных фиксируется ожидаемое обновление, не связанное с tx
Вот журнал, который фиксирует (первый экземпляр всегда работает):http://pastebin.com/xW6xbfzK
Если я помещаю оба коммита в tx, код никогда не сохраняется даже в первый раз:
PersistenceManager pm = GAEModel.get().getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
tx.begin();
log.info("saving code file!");
pm.makePersistentAll(uploadedCode);
tx.commit();
} finally {
pm.close();
}
pm = GAEModel.get().getPersistenceManager();
tx = pm.currentTransaction();
try {
tx.begin();
CodeCollection cc = new CodeCollection(uploadedCodeKeys);
pm.makePersistent(cc);
id = cc.getKey().getId();
tx.commit();
} finally {
pm.close();
}
Вышеописанное никогда не сохраняет список (код), но всегда сохраняет CodeCOllection.
Когда я комментирую транзакции, коллекция кодов по-прежнему всегда сохраняется, однако список (код) сохраняется только для первого запроса к экземпляру. Все последующие запросы не сохраняют код (без звука)
PersistenceManager pm = GAEModel.get().getPersistenceManager();
//Transaction tx = pm.currentTransaction();
try {
//tx.begin();
log.info("saving code file!");
pm.makePersistentAll(uploadedCode);
//tx.commit();
} finally {
pm.close();
}
pm = GAEModel.get().getPersistenceManager();
//tx = pm.currentTransaction();
try {
//tx.begin();
CodeCollection cc = new CodeCollection(uploadedCodeKeys);
pm.makePersistent(cc);
id = cc.getKey().getId();
//tx.commit();
} finally {
pm.close();
}
Комментарии:
1. Вот почему у вас есть журнал
на уровне отладки
2. Отрицательно. вот все журналы из appspot.com (добавлено в сообщение) они здесь не поместились.
Ответ №1:
ваше первое сохранение находится в txn, а второе — нет. Второй, скорее всего, не будет запускаться с той версией DataNucleus, которую использует GAE / J (т. Е. ancient). Поместите его в txn или запустите txn после него (tx.begin(); tx.commit();) для сброса оставшихся обновлений.
Комментарии:
1. Интересно, что вторая фиксация (codecollection) выполняется всегда. Это первый в tx, который не работает. Я обновил свой исходный пост дополнительной информацией.
Ответ №2:
App engine по умолчанию имеет значение Persistent, если аннотация не указана. У меня было поле в CodeCollection, которое использовалось для кэширования списка кода, app engine пытался сохранить это, и это выходило из себя. Добавленный @notpersistent все очистил.
Комментарии:
1. На самом деле JDO и JPA имеют значения по умолчанию для того, является ли что-то постоянным, а не GAE / J. Их документы полностью вводят в заблуждение, поскольку они подразумевают, что вы должны указывать @Persistent для всего.