Не удалось десериализовать результат из удаленного сервиса HTTP invoker [...]; вложенное исключение java .lang.ClassNotFoundException: - PullRequest
0 голосов
/ 09 января 2020

Я получаю следующую ошибку только при добавлении общей библиотеки в мое приложение на экземпляре IBM WebSphere (версия 8.5.xx). Цель состоит в том, чтобы переместить много общих библиотек (jar-файлов) между некоторыми приложениями в общую библиотеку на сервере, чтобы уменьшить размеры приложений. Однако из того, что я видел, не имеет значения, уменьшается ли размер файла war или нет, при каждом добавлении этой общей библиотеки мы видим следующие ошибки.

org.springframework.remoting.RemoteAccessException: Could not deserialize result from HTTP invoker remote service [<URL>]; nested exception is java.lang.ClassNotFoundException: com.example.models.ExampleModel
    at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.convertHttpInvokerAccessException(HttpInvokerClientInterceptor.java:221)
    at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.invoke(HttpInvokerClientInterceptor.java:153)
    at com.example.configuration.LoggingHttpInvokerProxyFactoryBean.invoke(LoggingHttpInvokerProxyFactoryBean.java:28)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
    at com.sun.proxy.$Proxy305.getSomeListOfObjects(Unknown Source)
...
...
...
Caused by: java.lang.ClassNotFoundException: com.example.models.ExampleModel
    at java.lang.Class.forNameImpl(Native Method)
    at java.lang.Class.forName(Class.java:403)
    at java.io.ClassCache$FutureValue.get(ClassCache.java:177)
    at java.io.ClassCache.get(ClassCache.java:148)
    at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:834)
    at org.springframework.core.ConfigurableObjectInputStream.resolveClass(ConfigurableObjectInputStream.java:78)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2017)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1900)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2194)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1722)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2439)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2363)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2221)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1722)
    at java.io.ObjectInputStream.readObjectImpl(ObjectInputStream.java:540)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:475)
    at org.springframework.remoting.httpinvoker.AbstractHttpInvokerRequestExecutor.doReadRemoteInvocationResult(AbstractHttpInvokerRequestExecutor.java:291)
    at org.springframework.remoting.httpinvoker.AbstractHttpInvokerRequestExecutor.readRemoteInvocationResult(AbstractHttpInvokerRequestExecutor.java:242)
    at org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor.doExecuteRequest(HttpComponentsHttpInvokerRequestExecutor.java:248)
    at org.springframework.remoting.httpinvoker.AbstractHttpInvokerRequestExecutor.executeRequest(AbstractHttpInvokerRequestExecutor.java:137)
    at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.executeRequest(HttpInvokerClientInterceptor.java:202)
    at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.executeRequest(HttpInvokerClientInterceptor.java:184)
    at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.invoke(HttpInvokerClientInterceptor.java:150)

Ниже приведен аналогичный пример того, как класс модели выглядит в меньшем масштабе. Прежде всего, я хотел бы отметить, что он действительно реализует Serializable (с использованием serialVersionUID по умолчанию):

package com.example.models.ExampleModel;

public class ExampleModel implements Serializable {
    private static final long serialVersionUID = 1L;
    private String customerNumber = "";
}

Любые идеи отладки даже будут высоко оценены как минимум. Я также хотел отметить, что вызов этого метода удаленного взаимодействия работает хорошо, когда разделяемая библиотека не добавляется в приложение на сервере, но, похоже, не работает при добавлении разделяемой библиотеки. Кроме того, общая библиотека на сервере не имеет jar, содержащий класс, который не может быть найден. Jar с классом, который не может быть найден, находится в моей папке WEB-INF / lib, и я проверил, чтобы он был установлен на сервере.

Ответы [ 2 ]

1 голос
/ 09 января 2020

Это похоже на проблему иерархии загрузчиков классов, в которой классы, загружаемые загрузчиком классов приложения (EAR), пытаются загрузить классы, упакованные в загрузчик веб-модуля (WAR). Я полагаю, что метод resolClass () ObjectInputStream использует загрузчик классов своего вызывающего для неудачной загрузки классов, и я также предполагаю, что ваши классы Spring входят в класс общей библиотеки.

В Java Приложение EE, EAR и WAR имеют отдельные загрузчики классов, причем родительский загрузчик выполняет EAR. Когда общая библиотека связана с приложением в WebSphere, ее содержимое добавляется в путь классов загрузчика EAR. Это проблема, если классы в общей библиотеке нуждаются в видимости для классов, упакованных в WAR, потому что родительские загрузчики не могут «видеть» своих потомков. WebSphere позволяет связывать разделяемую библиотеку либо с приложением, либо с одним или несколькими веб-модулями в приложении, и это меняет, к какому загрузчику классов добавляется путь к классу библиотеки.

Предполагается, что я понимаю упаковку и поведение resolClass правильно, я думаю, что решение должно быть довольно простым - вместо того, чтобы связывать разделяемую библиотеку с приложением, вместо этого свяжите ее с веб-модулем, который содержит класс, который не найден (обратите внимание, что вам нужно удалите также ассоциацию уровня EAR, иначе она просто загрузит классы Spring оттуда и возникнет та же проблема). Это позволит получить пути WAR и пути к общей библиотеке в одном загрузчике классов, что устраняет проблему иерархии.

Обратите внимание, что даже если мои предположения верны, это решение не будет работать, если вы выбрали «использовать Параметр «Изолированный загрузчик классов» для общей библиотеки - этот параметр создает отдельный загрузчик классов, который действует как своего рода родительский элемент для WAR / EAR, с которым он связан, поэтому он все равно не сможет видеть классы в WAR, даже если это связано с войной соответственно. Если есть jar-файлы, требующие поведения изолированной загрузки классов, вам придется либо переместить классы WAR в разделяемую библиотеку, либо вернуть Spring в WAR.

0 голосов
/ 10 января 2020

@ Джарид подробно описал решение. Пожалуйста, прочитайте его решение, если вы ищете другие шаги отладки.

Короче говоря, у меня была общая библиотека, включающая jar-файлы Spring Framework, прикрепленные как к приложению, так и к веб-модулю. После того как общая библиотека была удалена из приложения и подключена ТОЛЬКО к веб-модулю, приложение начало работать правильно и смогло десериализовать результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...