#java #servlets #jaxb #xerces
Вопрос:
Я читаю XML-данные из запроса HttpServletRequest в моих сервлетах doPost() и передаю считыватель из req.getReader() в JAXB unmarshaller. Я пробовал несколько разных входных XML, но всегда получаю это исключение.
SEVERE: Servlet.service() for servlet RESTPhotoAdmin threw exception
java.lang.ArrayIndexOutOfBoundsException: 8192
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.peekChar(XMLEntityScanner.java:491)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2672)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:647)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:508)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:195)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:168)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:194)
at com.cantorva.gigcalendar.servlets.rest.RESTPhotoAdmin.doPost(RESTPhotoAdmin.java:41)
Это происходит только на моем живом веб-сервере, а не на локальной машине разработки. Каким бы ни был ввод (хотя я пробовал только около 90 тыс. входов), часть сообщения трассировки стека всегда читается как «8192». Я поднял глаза XMLEntityScanner.java строка 491 и может видеть считываемый буфер, и буфер действительно является массивом. Для меня имеет смысл, что буфер 8k не может быть прочитан с использованием нулевого индекса 8192, так что это, должно быть, ошибка, но в чем причина и что я могу сделать?
Я спрашиваю об этом, уже найдя ответ на множество детективных работ. Я хотел избавить следующего бедолагу от лишних хлопот, так как Apache уже отказался это исправить.
Ответ №1:
Я нашел непонятную ошибку XERCESJ-1275, которая сама по себе является дубликатом XERCESJ-1015. В отчете не упоминается моя трассировка стека, но упоминается a ArrayIndexOutOfBoundsException
. Ключом к разгадке был комментарий о том, что 0 является допустимым (или несколько допустимым) ответом от метода чтения читателя, но не от входного потока в соответствии с JavaDoc. XMLEntityScanner предполагает, что 0 никогда не может произойти — отсюда и ошибка.
Майкл Главассевич по-разному интерпретирует документацию и отмечает дефект недействительным, но обходной путь заключается в том, чтобы просто предоставить отправителю без подписи входной поток, используя req.getInputStream()
, а не считыватель, и скрестить пальцы, чтобы какая — то неясная часть реализации более точно выполняла различные интерфейсные контракты, что они и делают.