Google App engine продолжает беззвучно завершаться сбоем после первого сохранения

#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 для всего.