I have a swing application that invokes stateless EJBs which deployed on WLS 10.3. The stateless EJB is secured via JAAS. Swing client get remote interface by JNDI lookup.
To improve performance, I want to cache the initialContext so that the initialContext is created only once at client side. For the same reason I want to cache the remote interface at client side.
I put the security principle and credential of current user in the initialContext. The first invocation of stateless EJB method succeeded. After that, every remote method invocation results 'javax.ejb.EJBAccessException: [EJB:010160]Security Violation: User: '<anonymous>' has insufficient permission to access EJB'.
I think this is not because of the caching of remote interface since If I creat initialContext before each invocation of stateless EJB method, the exception does not occur.
Is caching remote interface and initialContext wrong idea? If not, what is the right implementation?
I found that the singleton initialContext was first created in the login thread other than the main swing application thread.
The method invocation in the login thread was successful. After that the invocations in main thread throws exception about anonymous user.
And if I change the code so that the singleton initialContext was first created in the main swing application thread, the exception disappear....
I am wondering if it is about the initialContext thread safe problem? I cannot figure out why the principle of the context is changed to anonymous.
Still your error suggests that you passed in a context that does not have a user name set up. Maybe the code you are using to make the invocation has a problem or the problem is elsewhere perhaps even at server side.
As to whether this will improve performance or not a common answer is it depends but JNDI lookup is costly and Handles cache was almost a must for EJB 2.1. I would cache as part of ServiceLocator pattern anyway if it's EJB 3 but for 3.1 I would look at some statistics first before putting the caching solution into production.
I think the reason is the next call is made in different thread!
Everytime when create a InitialContext, a subject is associalted with current thread, so if you want to cache the InitialContext and remote interface ,then you should cache the subject too.
In my system, we use weblogic specific api to accomplish this:
when create the context,cache the subject :
Context context=new InitialContext(param);
Subject subject = weblogic.security.Security.getCurrentSubject();
after that ,use the cached subject to make the call:
obj = weblogic.security.Security.runAs(
public Object run() throws Exception
Object o =bizService.call();
} catch (InvocationTargetException e)
JNDI contexts are not thread safe. See the Javadoc.
As I hinted above, they are also implemented with a lot more intelligence than you seem to assume. There is nothing to be gained by using singleton Contexts. They already do connection pooling behind the scenes.