I am using the SimpleRemoteStatelessSessionProxyFactoryBean to access a remote EJB on a WebLogic server. The server is setup to require authentication. I have found that the server is setup in such a way that not only does the EJBHome lookup require execution "inside" the context (i.e. with the context open and active in the current thread), but also the create, method invocation and remove calls also require execution "inside" the context.
However, looking through the Spring 1.2.5 classes, it appears that the only method that is called inside the context is the EJB home lookup. Once the home is looked up, the context is not used again. This means that the create call, invoke, and remove call all fail, giving the exception:
java.lang.SecurityException: Authentication for user weblogic denied in realm wl_realm
(note that the user defaults back to "weblogic" rather than using the value from the context)
For now I have worked around this by extending SimpleRemoteStatelessSessionProxyFactoryBean as follows:
Since the overrides use the jndiTemplate to execute the super method inside the callback, this resolves the issue.Code:import org.aopalliance.intercept.MethodInvocation; import org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean; import org.springframework.jndi.JndiCallback; import javax.ejb.EJBObject; import javax.naming.Context; import javax.naming.NamingException; import java.lang.reflect.InvocationTargetException; /** * The Spring classes do not seem to execute the create, invoke, and remove methods inside the scope of an InitialContext, * which is unfortunately required by WebLogic to properly pass authentication information. This class overrides the normal * create, invoke, and remove methods to run inside the scope of an initial context. */ public class WebLogicSimpleRemoteStatelessSessionProxyFactoryBean extends SimpleRemoteStatelessSessionProxyFactoryBean { protected Object create() throws NamingException, InvocationTargetException { try { return getJndiTemplate().execute(new JndiCallback() { public Object doInContext(Context context) throws NamingException { try { return WebLogicSimpleRemoteStatelessSessionProxyFactoryBean.super.create(); } catch (InvocationTargetException ite) { throw new RuntimeException(ite); } } }); } catch (RuntimeException re) { throw (InvocationTargetException)re.getCause(); } } protected void removeSessionBeanInstance(final EJBObject ejbObject) { try { getJndiTemplate().execute(new JndiCallback() { public Object doInContext(Context context) throws NamingException { WebLogicSimpleRemoteStatelessSessionProxyFactoryBean.super.removeSessionBeanInstance(ejbObject); return null; } }); } catch (NamingException e) { throw new RuntimeException(e); } } protected Object doInvoke(final MethodInvocation methodInvocation) throws Throwable { try { return getJndiTemplate().execute(new JndiCallback() { public Object doInContext(Context context) throws NamingException { try { return WebLogicSimpleRemoteStatelessSessionProxyFactoryBean.super.doInvoke(methodInvocation); } catch (Throwable t) { if(t instanceof NamingException) { throw (NamingException)t; } else { throw new RuntimeException(t); } } } }); } catch (RuntimeException re) { throw re.getCause(); } } }
However, this is kind of messy and I can't believe other WebLogic users have not run into this. Is there a better solution? Would anyone like to see a Spring issue created for this?
Cheers,
Raman Gupta


Reply With Quote