Каков наилучший способ обмена экземплярами бизнес-объектов между веб-приложениями Java с помощью JBoss и Spring?
В настоящее время у нас есть веб-приложение, загружающее контекст приложения Spring, который создает экземпляр пакета бизнес-объектов, объектов DAO и Hibernate. Мы хотели бы поделиться этим стеком с другим веб-приложением, чтобы не иметь нескольких экземпляров одних и тех же объектов.
Мы рассмотрели несколько подходов; выставляя объекты с помощью JMX или JNDI или используя EJB3.
У разных подходов есть свои проблемы, и мы ищем легкий метод.
Любые предложения о том, как решить эту проблему?
Изменить: я получил комментарии с просьбой немного уточнить, так вот:
Основная проблема, которую мы хотим решить, заключается в том, что мы хотим иметь только один экземпляр Hibernate. Это связано с проблемами с недействительностью кэша второго уровня Hibernate при запуске нескольких клиентских приложений, работающих с одним и тем же источником данных. Кроме того, стеки business/DAO/Hibernate растут довольно большими, поэтому их дублирование просто не имеет смысла.
Сначала мы попытались посмотреть, как один бизнес-уровень может быть доступен для других веб-приложений, а Spring предлагает JMX-упаковку по цене небольшого количества XML. Однако нам не удалось привязать объекты JMX к дереву JNDI, поэтому мы не смогли найти объекты из веб-приложений.
Затем мы попытались привязать бизнес-уровень непосредственно к JNDI. Хотя Spring не предлагал никаких методов для этого, использование JNDITemplate для их связывания также было тривиальным. Но это привело к появлению нескольких новых проблем: 1) диспетчер безопасности отказывает в доступе к загрузчику классов RMI, поэтому клиент провалился, как только мы попытались вызвать методы на ресурсе JNDI. 2) После устранения проблем безопасности JBoss бросил IllegalArgumentException: объект не является экземпляром объявления класса. Немного чтения показывает, что нам нужны реализации заглушек для ресурсов JNDI, но это похоже на много хлопот (возможно, Spring может нам помочь?)
Мы еще не слишком много смотрели в EJB, но после первых двух попыток мне интересно, возможно ли то, что мы пытаемся достичь.
Подводя итог тому, чего мы пытаемся достичь: один экземпляр JBoss, несколько веб-приложений, использующих один стек бизнес-объектов поверх уровня DAO и Hibernate.
С уважением,
Нильс
Ответы
Ответ 1
Развертываются ли веб-приложения на одном сервере?
Я не могу говорить за Spring, но просто переместить вашу бизнес-логику на уровень EJB с помощью сеанса Beans.
Организация приложения прямолинейна. Логика переходит к сеансу Beans, и этот сеанс Beans объединяется в одну банку как артефакт Java EE с файлом ejb-jar.xml(в EJB3 это, вероятно, будет практически пустым).
Затем сгруппируйте классы Entity в отдельный файл jar.
Затем вы создадите каждое веб-приложение в своем собственном файле WAR.
Наконец, все банки и войны объединены в EAR EAR EE с соответствующим файлом application.xml(опять же, это, скорее всего, будет минимальным, просто перечисляя банки в EAR).
Этот EAR развернут на сервер приложений.
Каждая WAR фактически независима - свои собственные сеансы, есть собственные пути контекста и т.д. Но они имеют общий конец EJB, поэтому у вас есть только один кеш второго уровня.
Вы также используете локальные ссылки и вызываете семантику, чтобы разговаривать с EJB, так как они находятся на одном сервере. Здесь нет необходимости в удаленных вызовах.
Я думаю, что это довольно хорошо решает проблему, с которой вы сталкиваетесь, и это довольно просто в Java EE 5 с EJB 3.
Кроме того, вы все еще можете использовать Spring для большей части своей работы, как я понимаю, но я не человек Spring, поэтому я не могу говорить с деталями.
Ответ 2
Как насчет spring parentContext?
Ознакомьтесь с этой статьей:
http://springtips.blogspot.com/2007/06/using-shared-parent-application-context.html
Ответ 3
Terracotta может быть здесь хорошо подходит (раскрытие: я разработчик Terracotta). Terracotta прозрачно кластеризует объекты Java на уровне JVM и интегрируется как с Spring, так и с Hibernate. Это бесплатный и открытый источник.
Как вы сказали, проблема более чем одного клиентского веб-приложения с использованием кеша L2 заключается в синхронизации этих кешей. С Terracotta вы можете сгруппировать один кэш Hibernate L2. Каждый клиент node работает с ним копией этого кластерного кеша, а Terracotta синхронизирует его. Эта ссылка объясняет больше.
Что касается ваших бизнес-объектов, вы можете использовать Terracotta Spring интеграция для кластера beans - каждое веб-приложение может делиться кластерами bean, а Terracotta прозрачно синхронизирует кластерное состояние.
Ответ 4
Собственно, если вы хотите легкое решение и не нуждаетесь в транзакциях или кластеризации, просто используйте поддержку Spring для RMI. Это позволяет удаленно открывать Spring beans с помощью простых аннотаций в последних версиях. См. http://static.springframework.org/spring/docs/2.0.x/reference/remoting.html.
Ответ 5
Вы должны взглянуть на Terracotta Reference Web Application - Examinator. Он имеет большинство компонентов, которые вы ищете - он получил Hibernate, JPA и Spring с бэкэндом MySQL.
Он был предварительно настроен на масштабирование до 16 узлов, 20 тыс. одновременно работающих пользователей.
Посмотрите здесь: http://reference.terracotta.org/examinator
Ответ 6
Спасибо за ваши ответы. Мы все еще не совсем там, но сейчас мы кое-что пробовали и виднее. Здесь короткое обновление:
Решение, которое представляется наиболее жизнеспособным, является EJB. Однако для этого потребуется некоторое количество изменений в нашем коде, поэтому мы не будем полностью реализовывать это решение прямо сейчас. Я почти удивлен тем, что нам не удалось найти функцию Spring, чтобы помочь нам здесь.
Мы также пробовали маршрут JNDI, который заканчивается необходимостью заглушек для всех разделяемых интерфейсов. Это похоже на много хлопот, учитывая, что все равно на одном сервере.
Вчера у нас был небольшой прорыв с JMX. Хотя JMX определенно не предназначен для такого использования, мы доказали, что это можно сделать - без изменений кода и минимального количества XML (большое спасибо Spring для MBeanExporter и MBeanProxyFactoryBean). Основными недостатками этого метода являются производительность и тот факт, что наши классы домена должны совместно использоваться через папку JBoss/lib. I.e., мы должны удалить некоторые зависимости из наших WAR и перенести их на сервер /lib, иначе мы получим ClassCastException, когда бизнес-уровень возвращает объекты из нашей собственной модели домена. Я полностью понимаю, почему это происходит, но это не идеально для того, чего мы пытаемся достичь.
Я подумал, что пришло время для небольшого обновления, потому что лучшее, что кажется лучшим решением, займет некоторое время. Я опубликую наши результаты здесь, как только мы выполнили эту работу.
Ответ 7
Spring имеет точку интеграции, которая может вас заинтересовать: EJB 3 nterceptor. Это позволяет вам получить доступ к spring beans из EJB.
Ответ 8
Я не совсем уверен, что вы пытаетесь решить; в конце дня каждый jvm будет либо реплицировать экземпляры объектов, либо заглушки, представляющие объекты, существующие на другом (логическом) сервере.
Вы можете настроить третий сервер "бизнес-логики" с удаленным api, который могли бы назвать ваши два веб-приложения. Типичным решением является использование EJB, но я думаю, что spring имеет возможность удалять опции, встроенные в его стек.
Другой вариант - использовать некоторую форму архитектуры общего кэша... которая будет синхронизировать изменения объектов между серверами, но у вас все еще есть два набора экземпляров.
Ответ 9
Взгляните на JBossCache. Это позволяет вам легко делиться/реплицировать карты данных между экземплярами Mulitple JVM (одинаковыми или разными). Он прост в использовании и имеет множество параметров протокола на уровне провода (TCP, UDP Multicast и т.д.).