The
Java EE specs say that when you do a JNDI lookups, the object returned must be a unique instance (apart from very few exceptions, like shared connection factories, immutable objects etc). When you specify that a certain field / property needs dependency injection, the container performs injection after the constructor runs, and it is implemented as a JNDI lookup under the hood.
Now, the thing is that stateless objects (stateless session beans - SLSB or servlets) are not linked to any particular client, and for example, there is generally only one servlet instance per web context. So, if any SFSB (statefull session bean) was injected in a servlet, all requests would be able to put / get data into it, even the ones that are totally unrelated (not part of the same HTTP session). The same is for SLSB - when a bean is created, a SFSB would be injected for each SLSB in the pool (each would have its own instance), but you can never tell which bean serves requests of which client, so you could basically end up being able to read state that another client has set - just like in a case of a servlet.
However, there are ways to bypass this - and these are explicit JNDI lookups. For example, when each HTTP request comes in for a servlet, each would have a JNDI lookup call, and each request would get its very own instance of a SFSB (again, this is a requirement of Java EE specs). It could then store it in a HttpSession. The same for SLSB - explicit JNDI lookups in a method return new instances of SFSB, and these would be scoped for the given SLSB business method call - note there are
test cases where it is usefull to be able to call another bean's methods in a sequence, and be sure that the same instance is used.
Hope this is helpfull.