Howdy -- just wanted to add a couple of things. Mark has a good explanation already, so I'm just filling in a few more things.
*Stateless session bean, ejbPassivate() will never be called, so ejbRemove() is your only place to remove resources assuming the container doesn't crash. But... is that *really* the best place to do that work? Depends on the resource and its value. For example, if the resource is easy to get but too scarce to hold on to (preventing others from using it), then you should
release resources at the end of every business method!
(this is also true for stateful session beans)
So you might have a scenario where you acquire a resource in ejbCreate() and release it on ejbRemove(), or you might have a scenario where you acquire and release the resource within every business method. This might be the best solution, in some cases, when you are using JDBC
connections. They are not expensive to acquire (assuming you've already done the JNDI lookup on the datasource), but they can be too valuable to hold onto, especially for stateless beans in a pool.
* Stateful session beans:
You must do the same things in both ejbPassivate() and ejbRemove() (by having both of those methods call a 'cleanUp()' method, for example), because remember (and this IS on the exam) -- if a bean is removed, while it is passivated, it will NOT be 'woke up' (in other words, activated via an ejbActivate() call)) only to be removed. It will go straight from a passivated state to 'does not exist', without ever getting an ejbRemove() call.
On the other hand, a bean may be removed (because the client calls ejbRemove() on the component interface) without EVER having an ejbPassivate() method called.
All of this does not cover the scenario where an ejbRemove() call is missed because of a server crash, for example, and you DO need to know that the ejbRemove() might not be called, and under what circumstances, but you do NOT need to know any strategy for coping with that. Even the spec just says something like, "Periodically you might need to go through and clean out the things that weren't closed properly or deleted because the ejbRemove() wasn't called..."
* Entity beans --
You have three options, again depending on how expensive/valuable/difficult/time-consuming it is to use those resources, which of course depends entirely on your application.
1) acquire in setEntityContext, release in unsetEntityContext
-- this holds the resource for the longest possible time. No overhead with each business method call, but you stop others from every getting access to that resource (unless you have a server that will just take it away from you anyway, but that's not in the spec).
2) acquire in ejbActivate and release in ejbPassivate
-- this can be somewhat less harmful to concurrency than option 1, but some servers really don't use ejbPassivate much on entity beans, so the end result might not be that different from option 1.
3) acquire and release in each business method
-- this is often the most effective and efficient. It *sounds* scary to do this with db connections, but remember, with a datasource you don't have the expense of physically opening and closing the connection -- you are merely returning the connection to the pool (and retrieving a connection from the pool).
Notice what's missing? Acquiring and releasing in ejbCreate() and ejbRemove() -- this is usually NOT the place to get and release resources, because as Rangarajan Suresh mentioned, create and remove have a different meaning for entity beans, and have NOTHING to do with the life of the actual object. An entity bean, remember, might never GET an ejbCreate call, since all entity beans might be made by the server and accessed only through finder or home methods. And an entity bean object may never get an ejbRemove call for the same reason -- ejbRemove is only for removing the underlying entity in the persistent store (i.e. the row in the DB) rather than removing the actual object.
Remember how ejbRemove() works overall:
1) stateful session beans
-- called as a result of the client calling remove() on the local or remote component interface or remove(handle) on the remote home interface
(can't remove a stateful bean using a local home interface, because there is no handle!)
2) stateless session beans
-- called ONLY when and if the container decides to 'kill' a bean, usually because there are too many in the pool. Chances are, this method is never going to be called on a stateless bean.
3) entity beans
-- called ONLY when and if the client invokes remove() on the component interface, or remove(pk) on the home interface, or remove(handle) on the remote home interface.
-- the container will NEVER decide to call ejbRemove() on an entity, since it has such drastic results.
When the client calls remove() on a session bean, the client says, "I'm done with this bean object".
When the client calls remove() on an entity bean, the client says, "EVERYBODY is done with this entity."
OK, probably way more than anyone wanted to hear, but hey -- I have to make up for lost time