I know exactly where you're looking in the spec...
The tables on page 80 or page 90 (for session beans, or whatever the equivalent is for entity beans). There is some confusion about this.
Here's what's going on (and there *will* be questions about this on the exam):
1) When the table says, "JNDI access to java:comp/env" it means ONLY that you can get a reference to that JNDI context. It does NOT mean that you can actually *do* anything with it (except for look up environment entries)
So when the table says that in your setSessionContext method you have access to java:comp/env, that's very misleading, because YES -- you can get a reference to the context (the JNDI context, not SessionContext -- talk about overloaded use of the
word 'context'), but you cannot USE it to get, say, a reference to another bean, or access to a resource manager (like a DataSource).
2) The java:comp/env is very special -- it is a single bean's own 'private' space. In other words, if an instance of Bean A does a lookup on "fred" in java:comp/env, that is a different "fred" than if an instance of Bean B does a lookup on "fred".
It is important to understand the SCOPE of java:comp/env. It is for each bean type, from a particular home. So it is not per instance, or per ejb-jar, or per application, or per container, but per BEAN type. So the CartBean will have one java:comp/env JNDI context that is shared by all instances of CartBean.
Remember, when you think of a JNDI context (including an InitialContext, or java:comp/env), you can imagine it as nothing more thana directory or entry-point into the big JNDI tree of stuff. It isn't necessarily representing an actual file structure directory, but you can certainly think of it that way. And each bean type gets its own "directory" where it's stuff is placed.
The naming convention suggests that you place sub-contexts (again, think: sub-directories) within the java:comp/env space, although you don't *have* to (but
you should).
As follows:
java:comp/env/ejb -- this is where references to another bean's home will go
In the deployment descriptor, it looks like this:
<ejb-ref>
<ejb-ref-name>ejb/Payroll</ejb-ref-name>
... more stuff
<ejb-ref>
And in bean code, it looks like:
Context ic = new InitialContext();
Object o = ic.lookup("java:comp/env/ejb/Payroll");
java:comp/env/jdbc -- this is for a
JDBC data source
java:comp/env/foo/discount -- this means that you have made a subcontext named "foo" and placed an environment entry named "discount" inside.
<env-entry-name>foo/discount>/env-entry-name>
And in code...
String s = (String) ic.lookup("foo/discount");
The cool thing about java:comp/env scope is that you do not need to worry about name collisions with other beans. Imagine how many beans might have environment entries with the same names, or that might register a DataSource under the same logical name. But you do not have to worry about that.
OK, so back to the exam and the tables on page 80 and 90...
The exam expects you to know, for example, that in the bean's constructor (which you shouldn't implement anyway!) you do NOT have access to anything about the bean's "beanness". In other words, in a constructor, the bean is becoming an OBJECT but it is not yet becoming a BEAN.
You need to know that in setSessionContext, it is too early to USE the JNDI access for access to another bean or to a resource manager, even though you can get a reference to the java:comp/env context. But when you actually get to ejbCreate or ejbRemove or a business method, etc. , then you CAN use java:comp/env to get access to a resource manager (like DataSource) or another bean.
Also, notice that you cannot get access to another bean or a resource manager inside a stateful session bean's "afterCompletion" method (if you implement SessionSynchronization). So in setSessionContext and afterCompletion, you have access to java:comp/env, but cannot USE it for resource manager or bean access. The reason is because setSessionContext and afterCompletion are not running in a 'meaningful transaction context' or with a client security context.
You must also know other parts of that table. For example, you do not have access to programmatic security in setSessionContext (i.e. you can't call getCallerPrincipal() and isCallerInRole()). But you DO have access to them in virtually everything else.
And know that in your setSessionContext method you cannot get access to your EJBObject! (But you *can* get access to your own home). This helps you remember that ejbCreate() is called AFTER setSessionContext, because by the time you get to ejbCreate(), you are free to use your own EJBObject reference, because it definitely exists. So the setSessionContext method is a little too early in session bean's life to do much, so you might as well wait for ejbCreate(), in which you can do almost anything.
What can you *not* do in ejbCreate()? You can't call setRollbackOnly and getRollbackOnly on your SessionContext! In fact, you cannot call these methods in ejbCreate, ejbRemove, ejbActivate, or ejbPassivate (but you CAN call them from business methods, afterBegin, and afterCompletion). Why? Because in the first four methods, there is no meaningful transaction context. But in a business method, or those two SessionSynchronization methods (afterBegin and afterCompletion), there IS a tx context.
But that explains why you can't call getRollbackOnly() and setRollbackOnly() inside the afterCompletion() method -- because afterCompletion is called only AFTER the transaction is complete. So, at that point, nothing to rollback!
Become familiar with these tables, which look very confusing at first, but if you study them... they really DO make sense. Ff you recognize what the lifecycle methods are (ejbCreate, afterBegin, business method, etc.) and under what circumstances they're invoked by the container, it will be pretty simple to figure out what you can and cannot do inside those methods.
OK, not so simple, but not as awful as it looks when you first look at these tables.
cheers,
Kathy
