Использование Spring для доступа к EJB через кластеры в WebSphere с использованием Grails - PullRequest
2 голосов
/ 09 июля 2010

Последние несколько дней я пытался интегрировать приложение Grails (версия 1.3.2) с приложением EJB 2.1, которое развернуто в WebSphere 6.1. Когда наши приложения Grails будут запущены, они также будут развернуты в WebSphere. Приложение EJB 2.1 широко используется в нашей компании и во всем, кроме локальной среды разработки, развертывается в своем собственном кластере. То, как мы справляемся с этим в наших существующих приложениях Java EE (все из которых не Spring, не Grails), заключается в связывании CORBA CosNaming Naming Context внутри каждого из наших других кластеров, которые затем можно использовать для получения ссылок на наш общий EJB 2.1 заявка Итак, до этого момента, если одному из наших приложений нужно было взаимодействовать с этим приложением, они делали бы это, используя такой подход:

String cosNameBinding = "ejbApp.HighAvail.cluster";
InitialContext initial = new InitialContext();
Context fedContext = (javax.naming.Context) initialCtx.lookup(cosNameBinding);

Затем выполните обычный поиск / сужение / вызов в стиле EJB с использованием федеративного контекста / CosNaming:

Object ejbHomeAsObject = fedContext.lookup(jndiNameOfService);        
EJBHome home = (EJBHome) PortableRemoteObject.narrow(ejbHomeAsObject, homeClass);
Object service = invokeMethod(homeClass, home, "create");

Как вы можете видеть, здесь есть уровень косвенности, чтобы перейти от InitialContext к контексту федеративного именования, который можно использовать для взаимодействия с общим приложением EJB.

Работая локально, у меня и приложение Grails, и приложение EJB, развернутые на одном и том же сервере (WAS развертывания вне сети, тот же профиль и узел) У меня Spring настроен так:

beans = {
        ejbJndi(org.springframework.jndi.JndiTemplate) {
            environment = ["java.naming.factory.initial" : 
                           "com.ibm.websphere.naming.WsnInitialContextFactory"]
        }
        crewMemberService(org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean) {
            jndiName="hotelService/ejb/HotelService"
            businessInterface="com.company.appName.hotel.HotelService"
            lookupHomeOnStartup="false"
            cacheHome="false"
            refreshHomeOnConnectFailure="true"
            jndiTemplate = ref("ejbJndi")
        }
}

И я могу успешно вставлять ссылки ejb в мои контроллеры Grails и вызывать их. Однако WebSphere может разрешить поиск JNDI только потому, что они оба развернуты на одном сервере. Когда мы переместим его в одну из наших сред разработки, нам понадобится поиск jndi, чтобы эти службы шли вразрез с контекстом федеративного именования.

Итак, мои вопросы:

  1. Есть ли способ сделать это с помощью классов, предоставляемых в Spring, и если да, то могли бы вы дать мне представление о том, как мне нужно изменить конфигурацию Spring для этого?
  2. Учитывая то, что нет гибкости в том, как мы развертываем другое приложение или получаем ссылки на его сервисы (мы должны использовать федеративный контекст), следует ли мне рассмотреть расширение JndiTemplate и выполнить необходимые подключения самостоятельно?

Если кто-то сталкивался с такой ситуацией, я был бы очень признателен за любые идеи, которые вы можете предложить.

1 Ответ

1 голос
/ 16 июля 2010

В случае, если у кого-то возникнет тот же вопрос, я в конечном итоге реализовал расширение для Spring JndiTemplate и использовал его.Вот код:

public class FederatedJndiTemplate extends org.springframework.jndi.JndiTemplate
{
    protected static final String JNDI_CONTEXT_BINDING_NAME = "fed.context.jndiName";

    /**
     * Obtain a JNDI naming context for the specified federated naming context.
     * 
     * @throws NamingException if no "fed.context.jndiName" has been specified in
     * the environment properties for the jndiTemplate or the container throws a naming
     * exception.
     */
    @Override
    protected Context createInitialContext() throws NamingException {
        Properties props = super.getEnvironment();

        if(!props.containsKey(JNDI_CONTEXT_BINDING_NAME)) {
            throw new NamingException("You must specify the federated naming context JNDI binding name");
        }

        String jndiBinding = props.getProperty(JNDI_CONTEXT_BINDING_NAME);
        InitialContext initCtx = new InitialContext();
        Context fedCtx = (Context) initCtx.lookup(jndiBinding);
        return fedCtx;
    }
}

Тогда внутри моих resources.groovy, я просто использовал этот JndiTemplate:

            ejbJndi(com.myCompany.spring.jndi.FederatedJndiTemplate) {
                    environment = [
                        "fed.context.jndiName":"myServices.HighAvail.Cluster"]
            }
            hotelService(org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean) {
                jndiName="hotelService/ejb/HotelService"
                businessInterface="com.mycompany.appName.hotel.HotelService"
                homeInterface="com.mycompany.appName.hotel.HotelServiceHome"
                lookupHomeOnStartup="false"
                jndiTemplate = ref("ejbJndi")
            }
...