У меня есть сервлет, который сохраняет код, загружаемый людьми. Они могут загружать несколько файлов кодов, ключи которых затем сохраняются в коллекции кодов. Все работает ровно по одному запросу. После первого запроса класс 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();
}
Я присваиваю коду строковый хеш или что-то, а не дубликат. Я перепробовал почти все варианты, которые сохранились в нескольких последних строках, которые я могу придумать. Коллекция кода хранится каждый раз вместе с идентификаторами файлов неперспективного кода.
Спасибо
Также вот журналы от коммита, который терпит неудачу на уровне DEBUG:
мс = 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: загрузка страницыЗагрузка
I 2011-05-24 20: 54: 17,428
org.datanucleus.ObjectManagerImpl close: выдающееся nontx обновление фиксируется в хранилище данных
I 2011-05-24 20: 54: 17.482
org.datanucleus.ObjectManagerImpl close: выдающееся nontx-обновление фиксируется в хранилище данных
Вот журнал, который фиксирует (первый экземпляр всегда работает):
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();
}