Почему JCA предписывает equals & hashCode для компонентов ResourceAdapter и ManagedConnectionFactory?

Это не настоящая проблема, а скорее вопрос к экспертам JCA, чтобы я увидел свет в отношении одного аспекта спецификации JCA. Я пытаюсь понять, почему JCA предписывает, чтобы bean-компонент адаптера ресурсов и фабрики управляемых соединений реализовывали equals() и hashCode().

IMO адаптер ресурсов или управляемая фабрика соединений — это объекты, управляемые сервером приложений, по крайней мере, в управляемой среде. Таким образом, они не так уж далеки от EJB, сервлетов, управляемых компонентов CDI, где сервер приложений отвечает за управление экземплярами. А количество экземпляров класса адаптера ресурсов или класса фабрики управляемых соединений напрямую определяется их развертыванием.

Так зачем кому-то нужны equals() и hashCode() в этих классах? Я никогда не делал никаких других реализаций, кроме вызова суперреализаций, которые до сих пор работают вполне нормально. Но, конечно, сонар этого не очень ценит.


person Robert Panzer    schedule 19.10.2014    source источник


Ответы (2)


Чтобы процитировать спецификацию JCA (версия 1.0, но 1.5 имеет тот же текст, и я предполагаю, что в более новых версиях он также есть):

Адаптер ресурсов необходим для реализации интерфейса ManagedConnectionFactory.
Требуется, чтобы класс реализации ManagedConnectionFactory расширял реализацию методов hashCode и equals, определенных в классе java.lang.Object. Эти два метода используются сервером приложений для структурирования пула соединений в зависимости от реализации. Реализация методов equals и hashCode должна основываться на полном наборе свойств конфигурации, которые делают экземпляр ManagedConnectionFactory уникальным и специфичным для экземпляра EIS.

и

Сервер приложений может использовать дополнительные параметры для поиска и критерии сопоставления, используемые при управлении его пулом соединений. Эти параметры могут быть специфическими для EIS или сервера приложений. Методы equals и hashCode, определенные как для ManagedConnectionFactory, так и для ConnectionRequestInfo, упрощают управление и структурирование пула соединений сервером приложений.

В спецификации больше ничего об этом не сказано (кроме указания того же требования для некоторых других интерфейсов).

Поскольку общая идея состоит в том, что реализации управляемого соединения предоставляются поставщиками (например, поставщиками баз данных) и что сервер приложений может объединять ресурсы (например, ManagedConnection экземпляров), то предложение "Эти два метода используются приложением сервера для структурирования своего пула соединений в зависимости от реализации" Я могу только предположить, что это было сделано для упрощения реализации, например, для использования в HashMap или HashSet и т. д. Например, создание двух экземпляров ManagedConnectionFactory с идентичными свойствами приведет к имеют одинаковый результат для equals и hashCode и, следовательно, могут использовать один и тот же пул.

Кажется, это подтверждается следующей цитатой из той же спецификации:

Сервер приложений может разбивать свой пул на ManagedConnectionFactory экземпляров (и, таким образом, на каждый экземпляр EIS). Сервер приложений может гарантировать (специфическим для реализации способом), что он всегда будет разделять пулы соединений с точностью не менее ManagedConnectionFactory экземпляров.

Спецификация JCA, по-видимому, подразумевает, что соединения с одной системой должны обрабатываться одной управляемой фабрикой соединений (хотя я полагаю, что это не указано явно). Для этого потребуется найти один единственный ManagedConnectionFactory на основе его свойств.

Например, ядро ​​Jaybird (JDBC-драйвер Firebird, который я поддерживаю) представляет собой реализацию JCA (что, кстати, может быть настоящей головной болью). Первоначальная реализация Jaybird была разработана Дэвидом Дженксом, который также написал JCA-реализацию JBoss. В драйвере equals и hashCode используются несколькими способами:

  1. ManagedConnectionfactory хранит статический WeakHashMap, указывающий экземпляр на самого себя. Это используется для канонизации экземпляра (если экземпляр уже существует с такими же equals и hashCode, возвращается этот экземпляр).
  2. Реализация java.sql.Driver org.firebirdsql.jdbc.FBDriver сохраняет WeakHashMap от ManagedConnectionfactory до (без пула) реализации javax.sql.DataSource. Когда создается новое соединение, этот источник данных извлекается (или создается иным образом) для создания фактического соединения.
  3. Когда ManagedConnectionFactory десериализуется, метод readResolve возвращает канонизированную версию (см. 1), если она уже была на карте.

В качестве примечания: спасибо, что подняли этот вопрос; похоже, что текущая реализация в Jaybird имеет здесь ошибку, поскольку обе карты содержат прямую и косвенную сильную ссылку на фабрику управляемых соединений, что делает использование слабой хеш-карты довольно бесполезным.

person Mark Rotteveel    schedule 20.10.2014
comment
Спасибо за понимание реальной реализации. Как вы думаете, возможно ли, что сервер приложений создает несколько экземпляров одного развертывания MCF? Или, что еще хуже, создает несколько экземпляров развертывания RA и вызывает start() только в одном экземпляре? Или даже на всех экземплярах? (Я не могу сказать, какой путь вызовет у меня больше головной боли ;-)) - person Robert Panzer; 21.10.2014
comment
@RobertPanzer Честно говоря, я не знаком со всеми требованиями JCA (я унаследовал текущую реализацию, когда взялся за проект, и мне еще не приходилось слишком глубоко в нее погружаться). Насколько я понимаю, адаптер ресурсов загружается только один раз; я думаю, что это также может быть использовано в случае, когда два RA указывают на один и тот же ресурс; и, как указано выше, для поиска пула, связанного с RA. - person Mark Rotteveel; 21.10.2014

Если вы посмотрите на спецификацию, вы найдете причину: https://jcp.org/aboutJava/communityprocess/mrel/jsr322/index.html

6.5.3.2 Требования Адаптер ресурсов должен предоставлять реализацию интерфейса ManagedConnectionFactory. Требуется, чтобы класс реализации ManagedConnectionFactory расширял реализацию методов hashCode и equals, определенных в java.lang.Object. Эти два метода используются сервером приложений для структурирования пула соединений в зависимости от реализации. Реализация метода equals и hashCode должна основываться на полном наборе свойств конфигурации, которые делают экземпляр ManagedConnectionFactory уникальным и специфичным для экземпляра EIS.

person Simon Martinelli    schedule 20.10.2014
comment
Привет Саймон, спасибо за ваш ответ! Я уже нашел этот абзац в спецификации, так как большинство серверов приложений указывают раздел no в сообщениях об ошибках ;-) Мой вопрос был больше о том, почему спецификация требует этого? Я не вижу причин для использования этих методов в RA, которые не были бы в равной степени действительны для EJB, управляемых компонентов CDI и т. д. - person Robert Panzer; 20.10.2014
comment
Адаптер ресурсов — это нечто совершенно отличное от EJB или CDI. Поскольку компоненты JCA объединены в пул на сервере приложений. Таким образом, equals и hashCode используются, если сервер приложений хранит Factory в коллекции. - person Simon Martinelli; 20.10.2014
comment
Хм... Мнение IMO EJB скорее объединены в отличие от RA. Я напрямую определяю количество экземпляров моего RA или MCF через мое развертывание, по крайней мере, в управляемой среде. Я ожидаю, что для каждого развертывания создается и запускается только один RA, а не несколько, каждый из которых использует одни и те же свойства. Возможно, это имеет больше смысла в неуправляемой среде. - person Robert Panzer; 20.10.2014
comment
Вам обязательно следует прочитать спецификацию: 6.5.3.3 Реализация пула соединений и 9.1.8.2 Контракт для адаптера ресурсов. - person Simon Martinelli; 20.10.2014
comment
Я не согласен с 6.5.3.3, потому что в нем говорится об экземплярах фабрики управляемых соединений. Но вы меня достали с 9.1.8.2, там четко указано, что будет вызываться MCF.equals. Хотя мне все еще интересно, писал ли кто-нибудь когда-нибудь реализацию, которая не вызывает супер-реализации. - person Robert Panzer; 21.10.2014
comment
@RobertPanzer Ну, Jaybird (см. мой ответ) реализует их. - person Mark Rotteveel; 21.10.2014
comment
Отлично ;-) Я всегда рад поговорить с кем-то, кто использует JCA. JCA малоизвестен. - person Simon Martinelli; 21.10.2014
comment
@simas_ch В моем случае это больше то, что я унаследовал от Jaybird, я до сих пор не прочитал всю спецификацию JCA и стараюсь пока избегать этой части Jaybird; хотя близится день, когда я должен прикоснуться к нему, чтобы вырвать и заменить некоторые части фактического соединения с базой данных и реализации транзакции - person Mark Rotteveel; 21.10.2014