javaspringjakarta-eeejbspring-java-config

How to define Remote EJBs Beans in Spring using annotation-based configuration (ie: JavaConfig)


I'm trying to figure out the best way to define Remote EJB 3 beans in Spring 4.x using JavaConfig (annotation-based configuration).

I've looked at the Spring Docs for <jee:remote-slsb> and have hacked together a functional configuration, but it is terrible:

@Bean
public LoginManager getLoginManager(){
    SimpleRemoteStatelessSessionProxyFactoryBean factory = new SimpleRemoteStatelessSessionProxyFactoryBean();
    String beanName = "jndi.ejb3.LoginManager";
    factory.setJndiName(beanName);
    factory.setBusinessInterface(LoginManager.class);
    Properties p = new Properties();
    p.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory" );
    p.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces" );
    p.setProperty("java.naming.provider.url", "jnp:localhost:1099");
    factory.setJndiEnvironment(p);
    try {
        factory.afterPropertiesSet();
    } catch (NamingException e1) {
        e1.printStackTrace();
    }
    return (LoginManager) factory.getObject();
}

I shouldn't be calling afterPropertiesSet() in the bean definition, and I would have expected that the getObject() should be automatically called by Spring. Furthermore, it also means defining the factory for every Remote EJB that I want to load, which doesn't seem right. I would have liked/expected a way I could define a reusable factory and just pass it the Interface/JNDI name for each bean creation, but that doesn't work.

The spring docs indicate:

Also, with @Bean methods, you will typically choose to use programmatic JNDI lookups: either using Spring’s JndiTemplate/JndiLocatorDelegate helpers or straight JNDI InitialContext usage, but not the JndiObjectFactoryBean variant which would force you to declare the return type as the FactoryBean type instead of the actual target type, making it harder to use for cross-reference calls in other @Bean methods that intend to refer to the provided resource here.

So now I'm confused what to do.

The EJB Specific spring docs also recommend using the SimpleRemoteStatelessSessionProxyFactoryBean:

Defining explicit <jee:local-slsb> / <jee:remote-slsb> lookups simply provides consistent and more explicit EJB access configuration.

So how do I do this cleanly?


Solution

  • You don't need to call explicity the afterProperties method since that's part of spring bean lifecycle. Additionally if you declare the bean as a factory bean, spring will automatically use the getObject to get the real object when it is needed. Here is the modified code

        @Bean
    public FactoryBean getLoginManagerFactory(){
        SimpleRemoteStatelessSessionProxyFactoryBean factory = new SimpleRemoteStatelessSessionProxyFactoryBean();
        String beanName = "jndi.ejb3.LoginManager";
        factory.setJndiName(beanName);
        factory.setBusinessInterface(LoginManager.class);
        Properties p = new Properties();
        p.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory" );
        p.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces" );
        p.setProperty("java.naming.provider.url", "jnp:localhost:1099");
        factory.setJndiEnvironment(p);
    return factory;
    }