Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Динамическая регистрация бинов в Spring, Во время работы зарегестрировать бины 
V
    Опции темы
MisterCleric
Дата 8.9.2008, 10:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



Доброе всем времени суток.

Постала у меня задача, которую пока решить не могу.

1. Есть у меня куча филиалов, у которых стоит одинаковая база данных, но, естественно, с разным наполнением.
2. В каждом филиале я поставил по JBOSS с приложением для обращения к этой базе
3. Работаю с данными через EJB3+JPA+Hibernate. Ну эт, собственно й не важно. 
4. Есть Remote Interface у бина фасада
5. В главном приложении Spring Context, в котором я определяю такие два бина:

Код

<bean id="jndiEnvironment" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="properties">
            <props>
                <prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
                <prop key="java.naming.provider.url">${app.server.host}:${app.server.port}</prop>
            </props>
        </property>
    </bean>
 <bean id="facade" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="????/??????????????/remote"/>
        <property name="proxyInterface" value="???????????????????????????"/>
        <property name="jndiEnvironment" ref="jndiEnvironment"/>
    </bean>


Но это хорошо работает, если мне заранее известен ${app.server.host}

6. в главном приложении есть табличка в базе, в которой лежит инфа о филиалах (ID филиала, его IP). Т.е. если руками лукапить фасады филиалов, то все отлично работает.

Вопрос заключаеться в следующем:
Как динамически при старте приложения сконфигурить Spring на регистрацию бинов для всех фасадов по данным из таблицы.
Т.е. у меня будет список однотипных бинов (JndiObjectFactoryBean), которые будут отличаться только по ИД (что бы я корректно мог их потом инджектить в экшены по залогиненому юзеру) и IP машины филиала с JBOSS
Вторая сторона медали заключаеться в том, что бы админ мог во время работы приложения регистрировать новые филиалы, а также их грохать из Spring Context


--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
Asal
Дата 8.9.2008, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 288
Регистрация: 26.12.2006
Где: Минск

Репутация: 4
Всего: 7



осмелюсь предложить такой вариант
Код

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.ContextLoader;
import org.springframework.beans.factory.config.PropertiesFactoryBean;

import javax.servlet.ServletContextListener;
import javax.servlet.ServletContextEvent;
import java.util.Properties;

public class ContextListener implements ServletContextListener {
  private ContextLoader contextLoader;
  public ContextListener() {

  }

  public void contextInitialized(ServletContextEvent servletContextEvent) {
    contextLoader = new ContextLoader();
    WebApplicationContext context = contextLoader.initWebApplicationContext(servletContextEvent.getServletContext());
    PropertiesFactoryBean bean = (PropertiesFactoryBean) context.getBean("jndiEnvironment");
    Properties prop = new Properties();
    prop.setProperty("java.naming.provider.url", "mySuperServer");
    bean.setProperties(prop);
  }

  public void contextDestroyed(ServletContextEvent servletContextEvent) {
    controller.destroy();
    contextLoader.closeWebApplicationContext(servletContextEvent.getServletContext());
  }
}



--------------------
PM MAIL ICQ   Вверх
MisterCleric
Дата 8.9.2008, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



Цитата

   осмелюсь предложить такой вариант


Предположение не верное
У меня должен быть набор таких бинов:

Код

    <bean id="facade1" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="????/??????????????/remote"/>
        <property name="proxyInterface" value="???????????????????????????"/>
        <property name="jndiEnvironment">
            <props>
                <prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
                <prop key="java.naming.provider.url">${app.server.host1}:${app.server.port}</prop>
            </props>
        </property>
    </bean>


где переменная часть ИД самого бина и урл на java.naming.provider.url

а ты в своем примере просто меняешь свойства существующего бина...



Я могу, конечно, зарегистрировать factoryBean с коллекцией нужных мне JndiObjectFactoryBean и при нужден получать их из этой коллекции (или мэпа?) по ИД филиала из базы...

Но может, есть какой-то иной способ регистрировать бины...



--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
Asal
Дата 8.9.2008, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 288
Регистрация: 26.12.2006
Где: Минск

Репутация: 4
Всего: 7



Цитата(MisterCleric @  8.9.2008,  13:50 Найти цитируемый пост)
Предположение не верное

из Вашего первого поста я именно так и понял.
Второй пост пролил вет на ситуацию.

Цитата(MisterCleric @  8.9.2008,  13:50 Найти цитируемый пост)
Я могу, конечно, зарегистрировать factoryBean с коллекцией нужных мне JndiObjectFactoryBean и при нужден получать их из этой коллекции (или мэпа?) по ИД филиала из базы...

жаль, но мне то же ничего другого не приходит в голову.


--------------------
PM MAIL ICQ   Вверх
MisterCleric
Дата 8.9.2008, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



Также я понимаю, что надо сделать реализацию BeanFactory и в нем провести конфигурацию нужных мне бинов... 
Но как? хотя бы маленький примерчик, как реализовывать свою фабрику что-то типа такого

Код

<bean id="remoteInterfacesBeanFactoryService" class="MyBeanFactory">
        <property name="facade" ref="localFacade"/>
    </bean>


А в нем прочитать данные из базы и в цикле законфигурить JndiObjectFactoryBean столько, сколько надо по базе


--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
ivg
Дата 8.9.2008, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Autonomous R&D
**


Профиль
Группа: Участник
Сообщений: 686
Регистрация: 8.2.2006
Где: Екатеринбург

Репутация: 32
Всего: 81



Цитата(MisterCleric @  8.9.2008,  19:01 Найти цитируемый пост)
цикле законфигурить JndiObjectFactoryBean столько, сколько надо по базе

А вот вопрос: Какой смысл иметь эти бины в Спринговом контексте, если их кол-во и id заренее не известны на этапе конфигурации. Как вы будете на них ссылаться("инжектить")? Можно про эту связь поподробнее?
PM MAIL   Вверх
MisterCleric
Дата 8.9.2008, 17:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



да по-моему будет просто:

Код

  Facade facade = (Facade) beenFactory.getBean([ID from DB]);



--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
ivg
Дата 8.9.2008, 17:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Autonomous R&D
**


Профиль
Группа: Участник
Сообщений: 686
Регистрация: 8.2.2006
Где: Екатеринбург

Репутация: 32
Всего: 81



А beenFactory это объект какого класса? org.springframework.jndi.JndiObjectFactoryBean или MyBeanFactory?
PM MAIL   Вверх
MisterCleric
Дата 8.9.2008, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



MyBeanFactory
как я понимаю он должен иметь все возможные свойства стандартного BeanFactory, что бы была возможность в нем зарегистрировать бины любого типа, а потом их от туда получать


--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
ivg
Дата 8.9.2008, 19:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Autonomous R&D
**


Профиль
Группа: Участник
Сообщений: 686
Регистрация: 8.2.2006
Где: Екатеринбург

Репутация: 32
Всего: 81



Цитата(MisterCleric @  8.9.2008,  20:46 Найти цитируемый пост)
как я понимаю он должен иметь все возможные свойства стандартного BeanFactory

По моему, лучше сделать его обычным бином, без привязки к коду Spring'а. Инжектируете ему DataSource и что там ещё понадобится, во время инициализации бина лезете в базу, выгружаете иформацию о привязке IP-адресов, ну или во время запроса прокси фасада, тут можно по разному. То что делает org.springframework.jndi.JndiObjectFactoryBean можно реализовать и в коде, необязательно для этого регистрировать соответствующий бин в спринговом контексте. По сути он делает обычный lookup() к JNDI контексту и создание Proxy над полученным объектом для реализации интерфейса(который вы указываете в свойстве "proxyInterface"). Собственно в этом же бине можно реализовать и логику по добавлению/удалению филиалов. Ну и соответственно в Экшэны инжектируете этот бин, а получение Remote Interface нужного бина фасада будет делаться в одну строку, как вы, кажется, и хотели.
PM MAIL   Вверх
MisterCleric
Дата 9.9.2008, 11:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



Здравствуйте всем.
Спасибо за внимание и поддержку
Я нашел такое решение, хотя уверен оно не единственное smile

Код

public class RemoteFacadeBeanFactory extends JndiAccessor implements InitializingBean, ApplicationContextAware {
    private GenericApplicationContext context;
    
    private ApplicationContext parentContext;

    private LocalFacade facade;
    private String jndiName;
    private Class proxyInterface;

    public void setFacade(LocalFacade facade) {
        this.facade = facade;
    }

    public void afterPropertiesSet() throws Exception {
        List<Branch> branches = facade.getBranches();

        context = new GenericApplicationContext(parentContext);

        for (Branch branch : branches) {
            MutablePropertyValues asPvs = new MutablePropertyValues();

            asPvs.addPropertyValue("jndiName", jndiName);
            asPvs.addPropertyValue("proxyInterface", proxyInterface);

            Properties jndiProperties = new Properties();
            jndiProperties.putAll(getJndiEnvironment());
            jndiProperties.put("java.naming.provider.url", branch.getHost() + ":" + branch.getPort());

            asPvs.addPropertyValue("jndiEnvironment", jndiProperties);

            context.registerBeanDefinition(branch.getId(), new RootBeanDefinition(JndiObjectFactoryBean.class, asPvs));
        }
    }

    public Object getBean(String name) throws BeansException {
        return context.getBean(name);
    }

    public void setApplicationContext(ApplicationContext parentContext) throws BeansException {
        this.parentContext = parentContext;
    }

    public void setJndiName(String jndiName) {
        this.jndiName = jndiName;
    }

    public void setProxyInterface(Class proxyInterface) {
        this.proxyInterface = proxyInterface;
    }
}


в applicationContext.xml прописал так:

Код

 <bean id="jndiEnvironment" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="properties">
            <props>
                <prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
                <prop key="java.naming.provider.url">${app.server.host}:${app.server.port}</prop>
            </props>
        </property>
    </bean>
<bean id="remoteFacadeService" class="RemoteFacadeBeanFactory">
        <property name="facade" ref="localFacade"/>
        <property name="jndiName" value="[remoteEAR]/[RemoteJAR]/remote"/>
        <property name="proxyInterface" value="[MyRemoteInterface]"/>
        <property name="jndiEnvironment" ref="jndiEnvironment"/>
    </bean>

<bean id="remoteSessionFacadeInterceptor" scope="prototype"
          class="SessionFacadeInterceptor">
        <constructor-arg ref="remoteFacadeService"/>
    </bean>



И дальше у меня на экшенах висит интерцептор, который по залогиненному пользователю и ИД филиала этого пользователя делает инъекцию удаленного прокси таким простым куском кода:

Код

 protected void before(ActionInvocation actionInvocation) throws Exception {
      final ActionContext context = invocation.getInvocationContext();
        Map session = context.getSession();
        UserSession userSession = (UserSession) session.get(UserSession.ATRIBUTE_FOR_SESSION);
        Object action = actionInvocation.getAction();
        if (action instanceof SessionFacadeAware) {
            ((SessionFacadeAware) action).setSessionFacade(remoteFacadeService.getBean(userSession.getBranchId()));
        }
    }

Конечно, можно было все делать руками, но зачем тогда все эти фреймворки?..
Считаю тему закрытой


--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.0644 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.