开发者

Using Spring to Access an EJB Across Clusters in WebSphere using Grails

开发者 https://www.devze.com 2023-01-06 00:57 出处:网络
I have spent the last few days attempting to integrate a Grails (version 1.3.2) application with an EJB 2.1 application that is deployed on WebSphere 6.1.Once our grails apps are in production, they w

I have spent the last few days attempting to integrate a Grails (version 1.3.2) application with an EJB 2.1 application that is deployed on WebSphere 6.1. Once our grails apps are in production, they will be deployed to WebSphere as well. The EJB 2.1 application is widely used across our company and, in anything except a local development environment, is deployed to its own cluster. The way we handle this in our existing Java EE applications (all of which are non-Spring, non-Grails) is to bind a CORBA CosNaming Naming Context within each of our other clusters that can then be used to obtain references to our shared EJB 2.1 application. So, up to this point, if one of our application needed to interact with this application, they would do so using an approach like this:

String cos开发者_如何学CNameBinding = "ejbApp.HighAvail.cluster";
InitialContext initial = new InitialContext();
Context fedContext = (javax.naming.Context) initialCtx.lookup(cosNameBinding);

Then do the normal EJB-style lookup/narrow/invoke using the federated/CosNaming context:

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

As you can see, there is a level of indirection that occurs here in order to go from the InitialContext to the federated naming Context that can be used to interact with the shared EJB application.

Running locally, I have both the Grails application and the EJB application deployed to the same server (non network deployment WAS, same profile&node). I have Spring configured like so:

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")
        }
}

And I can successfully inject ejb references into my Grails controllers and invoke them. However, WebSphere can only resolve the JNDI lookup because they are both deployed on the same server. When we move it to one of our development environments, we'll need jndi lookups for these services to go against the federated naming context.

So my questions are:

  1. Is there a way to do this with the classes that are provided within Spring and if so could you give me an idea of how I would need up modify my Spring config to do so?
  2. Given that there is no flexibility around how we deploy the other app or gain references to its services (we must use the federated context), should I consider extending JndiTemplate and do the necessary wiring myself?

If anyone has faced this situation I would be most appreciative for any insights you may be able to offer.


In case anyone has this same question down the road, I ended up implementing an extension to Spring's JndiTemplate and using that. Here is the code:

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;
    }
}

Then inside my resources.groovy, I just used this 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")
            }
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号