Java.lang.ArrayIndexOutOfBoundsException в com.sun.mail.imap.MessageCache.getMessage(MessageCache.java:123)

Я читаю электронные письма с emailServer и сохраняю их в базе данных. Я использую следующий код для чтения сообщений из папки ( "INBOX" ) на сервере электронной почты и получения сообщений, соответствующих им, но я получаю

"java.lang.ArrayIndexOutOfBoundsException: message number (621) out of bounds (620)
at com.sun.mail.imap.MessageCache.getMessage(MessageCache.java:123)
at com.sun.mail.imap.MessageCache.getMessageBySeqnum(MessageCache.java:153)
at com.sun.mail.imap.IMAPFolder.getMessageBySeqNumber(IMAPFolder.java:2795)
at com.sun.mail.imap.IMAPFolder.getMessagesByUID(IMAPFolder.java:1924)"

Я использую javax.mail.1.4.4, эта проблема возникает, главным образом, при переполнении папки "Входящие".

Используемый код:

folder = store.getFolder("INBOX");

folder.open(Folder.READ_WRITE);
// messageUID is uid of last message I saved in DB

 Message messages[] = ((UIDFolder) folder).getMessagesByUID(messageUID + 1, UIDFolder.LASTUID);

Я провел некоторое исследование и обнаружил, что messagecache установлен для папки, как только он открывается, предположим, что он установлен как 520 (размер папки). Если какое-либо сообщение поступит после того, как установлен кеш сообщений, то в последней последовательности сообщений число превышает общий размер кеша сообщений и генерирует исключение.

Может ли кто-нибудь сообщить мне, как получить абсолютное значение UId последнего сообщения в папке или как получить блокировку папки, чтобы после установки кеша папка не обновляла размер папки.

Ответ 1

Интересная проблема!

Во-первых, я думаю, что это ошибка в javax mail. Вероятно, должен быть вызов checkRange() в getMessageBySeqNumber() или просто Math.min() с размером вектора.

В любом случае проблема заключается в том, что код отправляется на сервер для получения последнего количества сообщений, но никогда не обновляет локальный MessageCache. Это означает, что messageCache имеет устаревшие данные по сравнению с методом, но метод по-прежнему предполагает, что он обновлен... как вы видели, радость обеспечивает.

Теперь, как избежать этого, пока он не будет исправлен?

К сожалению, я думаю, что вы застряли в довольно ужасном обходном пути, делая что-то вроде:

folder = store.getFolder("INBOX");

folder.open(Folder.READ_WRITE);
// messageUID is uid of last message I saved in DB

/* I apologize for all of the kittens that this code is about to kill */
boolean getMessagesWorked = false;
do {
  try {
    Message messages[] = ((UIDFolder) folder).getMessagesByUID(messageUID + 1, UIDFolder.LASTUID);
    getMessagesWorked = true;
   } catch (ArrayIndexOutOfBoundsException e) {
     /* Doing this should force the internal messagesCache to get updated
      * Unfortunately, this is also somewhat racy, depending on just how
      * hard the mail folder is being hit */
      try {
       folder.getMessage(folder.getMessageCount());
      } catch (ArrayIndexOutOfBoundsException e) {
        /* There really isn't much you can do here, except try again.
         * the good news is that this should hardly ever happen!!
         * Good in this case is a relative term! */
      }
   }
} while (! getMessagesWorked);