I have a webapp on one Glassfish server (front-end) and an EJB 3.1 app (back-end) on another Glassfish server. The webapp communicates with the EJB 3.1 via remote invocation.
I would like to pass context data (user data i.e.) without having to define it as an input parameter of each business operation.
I have one idea, but not sure it will work: use a ThreadLocal to store data, but the ThreadLocal will only be available on one server (meaning JVM) => use the InvocationContext object and create interceptor to add user data to the ContextData Map.
What do you think about it? Any other ideas are more than welcome! ;-)
UPDATE
After first answer, I googled it a little bit and found the annotation #CallerPrincipal.
How can I set this object before the remote invocation?
The container will already handle this so you don't have to code it yourself.
In your EJB, you can access the EJBContext, which has a getCallerPrincipal() method which will give you the callers identity.
Related
I'm far from an expert of the intricacies of Resource Injection, and of indeed DataSources in Java, but I generally understand the process of doing a lookup for a predefined JNDI resource to get a datasource from.
Using Resource Injection as an alternate method, the below syntax works:
#Resource(name="jdbc/Foo")
private javax.sql.DataSource con;
However, I am using this in a servlet and as such wondering, how long this injected connection object's value will exist? Presumably, as it's simply an object within the servlet, it will inject when the servlet is first instantiated and exist for the same duration as the servlet (assuming I don't manually change it). Is this correct? Or does the servlet re-inject the resource everytime the servlet is used?
Thanks
A servlet container only ever creates one instance of your servlet. The IoC container you're using will then instantiate and inject the DataSource, so the value in con will remain the same for the life of your servlet, ie. the life of the application.
As to the underlying connection the DataSource is trying to make will, that's up to your datasource.
it will inject when the servlet is first instantiated and exist for the same duration as the servlet
Correct.
Or does the servlet re-inject the resource everytime the servlet is used?
No, this couldn't be happening because each request is served by a different thread. It wouldn't be good if those threads would modify the fields of the servlet. Request processing methods of the servlet must not modify its fields.
Generally container managed resources are injected using #Resources annotation. And container managed resources live as long as the container is running ( unless your are not manually kill it or any exception happens). Several applications can use the same resource object, provided that they live in the same application server ecosystem (same application server or cluster or server domain). But servlets are managed by your applications and lives within the application's scope as long as your application is running! So in terms of life span, if you compare resources are longer living than servlets.
And yes you are right, if you inject resources to a servlet, the reference of the resource will remain from the creation of the servlet to the end of the servlet's life cycle. The injection is not related with, how you are using the servlet or the resource.
Hope, this answers your question, Thanks!
JNDI is a mean to retrieve/store data or objects from string names. This feature is provided by the container running the application.
ApplicationContext allows the creation and retrieval of beans from their string name.
Both serve similar needs. Yet, Spring offers means to retrieve objects from JNDI. One can also access JNDI via the JndiTemplate.
Is there a real need to use JNDI in Spring? Which problem does it solve that ApplicationContext does not?
The Application Context would not help you in looking up a REMOTE object. It will only look for objects in the current application, which are not remote.
See the following "Context.PROVIDER_URL". You can get access to REMOTE objects like EJBs or RMI or JMS, etc. Also, you could access any resource managed by the Java EE Container such as a DataSource.
ht.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
ht.put(Context.PROVIDER_URL,"t3://HOSTNAME:PORT");
It's a question of scope. Spring's scope is limited to your application inside its container. JNDI is a global naming API that can plug into many different naming/directory architectures.
Is there a tutorial or a simple applet example with JSF? How do I perform a request to a Managed Bean from an applet?
Don't use a JSF managed bean. It is not suitable for this job. Use a servlet or a webservice. To exchange data, use the session scope with an unique autogenerated key which you pass as parameter to the applet beforehand. This way the data will be available to JSF as well.
JSF (and hence managed beans) executes on the server to produce HTML; An applet executes on the client's machine - so you can't just pass a reference to a managed bean to an applet.
If you just need to pass a value from a managed bean to an Applet at start time, you can use the <param> sub-element of the tag to pass this value.
If you need some kind of dynamic access to the managed bean, it's going to be a lot harder - basically, you'll need to build some kind of web service that's backed by the managed bean so that the applet can make http requests back to the server to get the values it needs.
In a J2EE application, we are using EJB2 in weblogic.
To avoid losing time building the initial context and looking up EJB Home interface, I'm considering the Service Locator Pattern.
But after a few search on the web I found that even if this pattern is often recommended for the InitialContext caching, there are some negative opinion about the EJB Home caching.
Questions:
Is it safe to cache EJB Home lookup result ?
What will happen if one my cluster node is no more working ?
What will happen if I install a new version of the EJB without refreshing the service locator's cache ?
Is it safe to cache EJB Home lookup
result ?
Yes.
What will happen if one my cluster
node is no more working ?
If your server is configured for clustering/WLM, then the request should silently failover to another server in the cluster. The routing information is encoded in the stub IOR.
What will happen if I install a new
version of the EJB without refreshing
the service locator's cache ?
Assuming you update the bean and not the component or home interfaces, then everything continues to work. EJBHome is effectively a stateless session bean, so the request can continue to be accessed from the same server if available or on a different server in the cluster if not.
Note that the #EJB injection in EJB3 effectively encourages home caching. (Though, admittedly, it also allows SFSB caching even though this is clearly incorrect, so perhaps #EJB isn't the best support of my claim :-)).
Is it safe to cache EJB Home lookup result ?
What will happen if one my cluster node is no more working ?
IMHO the purpose of ServiceLocator within J2EE is to cache EJB Home and reduce expensive JNDI look ups. It is safe on Weblogic since by default the EJB Home is load balanced across the cluster, and this will automatically allow failover to the next server.
This value is controlled by the home-is-clusterable value in weblogic-ejb-jar.xml, documented here which defaults to true.
What will happen if I install a new version of the EJB without refreshing
the service locator's cache ?
I havent tried doing such a change myself. However, I'm guessing as part of your build/deploy, your Service Locator class would also get redeployed along with a change to your EJBs - and thus do a fresh lookup?
If your client is unaffected during the changes to the EJB, then the cached EJBHome will return a stale reference when you call a method on it. So you will have to force the client to be refreshed.
What will happen if I install a new
version of the EJB without refreshing
the service locator's cache ?
Once your application goes live, new installations should become much less frequent than requests for an EJBHome.
So your focus and concern should lie with the frequent live operations, rather than the transient development operations.
Factor into your design the ability to invalidate caches when necessary.
I'm mantaining a EJB 2 CMP legacy app runing on a JBoss 4.0.4 GA application server with deployed entity/stateless session beans. All the EJB boilerplate code is generated via XDoclet from the EntityEJB/EntityEJBManager annotations.
I've noticed that when my GUI client invokes the facade create method, I have lots of cases of EJBException in my server log with the "Reentrant method call detected" message, which rollbacks the transaction.
What does this Exception means? How can I avoid having such error (which unfortunately, I wasn't able to reproduce yet)
Update: Found this link that explains what is meant by reentrancy, however, seems to me that it says my app cannot be accesed concurrently?
I've seen this before where EJB1 calls EJB2 which calls back to EJB1 within the container as part of the same transaction.
You can tell the container to allow this by marking EJB1 as reentrant which will allow it to be accessed multiple times in the same transaction.
This is done in the deployment descriptor with the following tag:
<reentrant>True</reentrant>
There should be a corresponding EntityEJB annotation that XDoclet can use to generate this for you.
we just came across the same problem and our solution was two-fold. Firstly we ensure that none of ejb's had transaction attributes of NotSupported within our ejb-jar.xml. We then used "instance per transaction" as our optimistic locking strategy. It's a bit of a belt-and-braces approach, but it works
It does mean that the Entity bean in question cannot be accessed concurrently, which makes sense since it would likely corrupt the data.