Нужна помощь в понимании JNDI и конкретного ClassCastException в J2EE
-
23-09-2019 - |
Вопрос
У меня развернуты корпоративные приложения A и B (в WLS 10.0).A - это "фреймворк", B - клиентское приложение.Клиент выдает следующие вызовы:
Object o = ctx.lookup(jndiName); // line 1
cf = (ConnectionFactory) o; // line 2
ConnectionFactory - это интерфейс, определенный как:
public interface ConnectionFactory
extends java.io.Serializable, javax.resource.Referenceable {
...
}
То , что происходит , это:
- Если jar, содержащий класс интерфейса, находится в пути к системному классу, строка 2 выполняется нормально
- Если класс интерфейса отсутствует в системном пути к классам, но упакован с приложениями отдельно, строка 2 выдает ClassCastException (в котором содержится информативный текст о том, что o является ConnectionFactoryImpl)
Почему это возможно?Я предполагаю, что поиск JNDI возвращает только заглушку для удаленного объекта (я прав в этом пункте?), Тогда почему это имеет значение, отличается ли classloader класса interface?
Именно такого ответа я и ожидаю:
- Да, это должно происходить так, как вы это переживаете, потому что ...
- Нет, так не должно происходить, потому что если ...тогда ..., значит, в вашей настройке есть что-то подозрительное
- Ситуация, которую вы описали, очень странная, вы уверены, что не упускаете какой-то момент где-то?
- ... :)
Также было бы неплохо, если бы кто-нибудь мог уточнить, как работают JNDI и заглушки, где происходит приведение (на стороне клиента в заглушке?или на исходном объекте на удаленной стороне?) и т.д.
Спасибо за вашу помощь!
Решение
Ответ, к сожалению, таков (1).
JNDI не диктует механизм того, как объект хранится в дереве или как он доставляется клиентам.Это просто API, который используется для выполнения операций.
Если оба приложения находятся в одной и той же JVM, как здесь, то Weblogic, скорее всего, просто передает объект непосредственно клиентскому приложению.Там нет заглушки и "удаленной стороны".Поскольку типы, реализованные этим объектом, не видны клиентскому приложению (помните, идентификатор типа определяется именем класса, а также загрузчиком классов, из которого он был загружен).
Вы можете подумать, что это странно, но имейте в виду, что приложения, разговаривающие между собой подобным образом, не являются нормой в разработке на JavaEE - приложения должны быть изолированы друг от друга, совместно используя только ресурсы системного уровня.