ClassCastException при литье в один класс
У меня есть два разных Java-проекта, один из которых имеет 2 класса: dynamicbeans.DynamicBean2
и dynamic.Validator
.
В другом проекте я загружаю оба этих класса динамически и сохраняю их на Object
class Form {
Class beanClass;
Class validatorClass;
Validator validator;
}
Затем я создаю объект Validator
, используя validatorClass.newInstance()
и сохраняя его на Validator
, затем создаю объект bean, используя beanClass.newInstance()
и добавляю его в сеанс.
portletRequest.setAttribute("DynamicBean2", bean);
В течение жизненного цикла проекта Form
я вызываю validator.validate()
, который загружает ранее созданный объект bean из сеанса (я запускаю Websphere Portal Server). Когда я пытаюсь вернуть этот объект в DynamicBean2
, он завершится ошибкой с исключением ClassCastException.
Когда я вытаскиваю объект из сеанса, используя
faces.getApplication().createValueBinding("#{DynamicBean2}").getValue(faces);
и проверьте его класс с помощью .getClass()
. Я получаю dynamicbeans.DynamicBean2
. Это класс, который я хочу использовать, но когда я пытаюсь получить ClassCastException.
Любая причина, по которой я получаю это?
Ответы
Ответ 1
Я не совсем следую вашему описанию потока программы, но обычно, когда вы получаете ClassCastExceptions, вы не можете объяснить, что вы загрузили класс одним загрузчиком классов, а затем попытаетесь привести его к тому же классу, который загружен другим загрузчиком классов. Это не будет работать - они представлены двумя различными объектами Class внутри JVM, и приведение не будет выполнено.
Есть статья о загрузке классов в WebSphere. Я не могу сказать, как это относится к вашему приложению, но есть ряд возможных решений. Я могу думать по крайней мере:
-
Измените загрузчик класса контекста вручную. Требует, чтобы вы действительно могли получить ссылку на соответствующий загрузчик классов, что может оказаться невозможным в вашем случае.
Thread.currentThread().setContextClassLoader(...);
-
Убедитесь, что класс загружен загрузчиком классов выше в иерархии.
-
Сериализация и десериализация объекта. (Тьфу!)
Хотя, вероятно, есть более подходящий способ для вашей конкретной ситуации.
Ответ 2
Объекты класса были загружены в разные загрузчики классов, поэтому экземпляры, созданные из каждого из классов, рассматриваются как "несовместимые". Это обычная проблема в среде, в которой используется много разных загрузчиков классов, и объекты передаются. Эти проблемы могут легко возникать в средах Java EE и портала.
При передаче экземпляра класса требуется, чтобы класс, связанный с объектом, был тем же, что и тот, который был загружен текущим загрузчиком классов контекста потока.
Ответ 3
У меня возникла проблема с A2AClassCastException при попытке создать список объектов из XML с помощью Apache Commons Digester.
List<MyTemplate> templates = new ArrayList<MyTemplate>();
Digester digester = new Digester();
digester.addObjectCreate("/path/to/template", MyTemplate.class);
digester.addSetNext("/path/to/template", "add");
// Set more rules...
digester.parse(f); // f is a pre-defined File
for(MyTemplate t : templates) { // ClassCastException: Cannot cast mypackage.MyTemplate to mypackage.MyTemplate
// Do stuff
}
Как указано выше, причина в том, что варочный котел не использует тот же ClassLoader, что и остальная часть программы. Я запустил это в JBoss, и оказалось, что commons-digester.jar не находится в каталоге JBoss lib, а скорее в каталоге webapp lib. Копирование jar в mywebapp/WEB-INF/lib также решило проблему. Другое решение было для casll digester.setClassLoader(MyTemplate.class.getClassLoader()), но в этом контексте это похоже на довольно уродливое решение.
Ответ 4
У меня была такая же проблема при использовании нескольких экземпляров JBoss на разных машинах. К сожалению, я не наткнулся на это сообщение раньше.
На разных машинах были обнаружены артефакты, два из них объявили загрузчики классов с одинаковым именем. Я изменил один из имен загрузчика классов и все работало нормально = > Остерегайтесь копирования и вставки!
Почему класс ClassCastException не упоминает задействованных загрузчиков классов? - Я думаю, что это была бы очень полезная информация.
Кто-нибудь знает, будет ли в будущем что-нибудь подобное? Нужно проверить классные загрузчики 20-30 артефактов, это не так приятно. Или есть что-то, что я пропустил в тексте исключения?
EDIT: я отредактировал файл META-INF/jboss-app.xml и изменил имя загрузчика, идея состоит в том, чтобы иметь уникальное имя. На работе мы используем идентификатор артефакта (уникальный) в сочетании с версией, вставленной maven ({$ version}) во время сборки. Использование динамических полей является необязательным, но помогает, если вы хотите развернуть разные версии одного и того же приложения.
<jboss-app>
<loader-repository>
com.example:archive=unique-archive-name-{$version}
</loader-repository>
</jboss-app>
Информацию можно найти здесь: https://community.jboss.org/wiki/ClassLoadingConfiguration
Ответ 5
У меня была такая же проблема, и я наконец нашел обходное решение для java.net:
Скопируйте все org.eclipse.persistence jar
файлы с glassfish4/glassfish/modules
на WEB-INF/lib
. Затем зайдите в glassfish-web.xml
и установите class-delegate
на false
.
Работал для меня!
Ответ 6
У меня была аналогичная проблема с JAXB и JBoss AS 7.1. Проблема и решение описаны здесь: javax.xml.bind.JAXBException: класс ***, ни один из его суперклассов не известен в этом контексте. Исключением, которое было указано, является org.foo.bar.ValueSet не может быть добавлено в org.foo.bar.ValueSet
Ответ 7
У меня была такая же проблема на EJB wildfly, EJB возвращал список объектов и имел удаленный и локальный интерфейс. Я использовал Локальный интерфейс по ошибке, что работает, только до тех пор, пока вы не попытаетесь отобразить объекты в списке.
Локальный/удаленный интерфейс:
public interface DocumentStoreService {
@javax.ejb.Remote
interface Remote extends DocumentStoreService {
}
@javax.ejb.Local
interface Local extends DocumentStoreService {
}
EJB bean:
@Stateless
public class DocumentStoreServiceImpl implements DocumentStoreService.Local, DocumentStoreService.Remote {
Правильная обертка spring вокруг EJB:
<bean id="documentStoreService" class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<property name="jndiName" value="java:global/dpc/dpc-ejb/DocumentStoreServiceImpl!santam.apps.dpc.service.DocumentStoreService$Remote"/>
<property name="businessInterface" value="santam.apps.dpc.service.DocumentStoreService$Remote"/>
<property name="resourceRef" value="true" />
</bean>
Обратите внимание на $Remote, вы можете изменить это на $Local, и он найдет локальный интерфейс просто прекрасным, а также будет выполнять методы без каких-либо проблем (из отдельного приложения в одном контейнере), но объекты модели не маршалируются и загружаются из другого загрузчика классов, если вы используете локальный интерфейс по ошибке.
Ответ 8
Другая опция:
Случалось мне в weblogic, но я думаю, что это может произойти и на других серверах - если вы это сделаете (просто) "Опубликовать", и поэтому некоторые из ваших классов будут перезагружены. Вместо этого "Очистить", чтобы все классы были перезагружены вместе.
Ответ 9
У меня была такая же проблема с поиском EJB из другого EJB.
Я решил добавить @Remote (MyInterface.class) в конфигурацию класса EJB
Ответ 10
Если бы тот же my.package.MyClass cannot be cast to my.package.MyClass
в WildFly 10.1, и, насколько я понимаю, я сделал противоположное тому, что @Emil Lundberg описал в своем ответе.
Я добавил модуль (который содержит my.package.MyClass
) в my.war/WEB-INF/jboss-deployment-structure.xml
в качестве зависимости
<dependencies>
...
<module name="my.package"/>
</dependencies>
и удалил соответствующий jar из my.war/WEB-INF/lib
, повторно развернул WAR, а затем код my.war/WEB-INF/lib
как и ожидалось.
Таким образом, мы убедились, что это решает проблему. Теперь нам нужно убедиться, что проблема не вернется, например, когда обновленная версия WAR будет собрана и развернута.
Для этого в источниках этих WAR требуется добавить <scope>provided</scope>
для этих jar в pom.xml
, чтобы при следующей my.war
следующий раз с введенным кодом исправления/улучшения, он не будет my.war/WEB-INF/lib
этот jar в my.war/WEB-INF/lib
.
Ответ 11
Я получил эту проблему после добавления зависимости к spring-boot-devtools
в моем проекте Springboot. Я удалил зависимость, и проблема ушла. Мое лучшее предположение на данный момент состоит в том, что spring-boot-devtools
вводит новый загрузчик классов, и это вызывает проблему проблем приведения классов между различными загрузчиками классов в определенных случаях, когда новый загрузчик классов не используется некоторыми потоками.
Ссылка: исключение карты dozer, связанное с Spring boot devtools