3

I have a stateful session bean with the following annotations:

@Stateful
@Name("fooBar")
public class FooBarAction implements FooBar {

I noticed there are 2 ways to get my FooBar instance:

Seam lookup:

Component.getInstance(FooBarAction.class);

JNDI lookup:

(new InitialContext()).lookup("MYAPP/FooBarAction/local");

When I use the JNDI lookup, each time I execute the lookup, I notice a new instance of FooBar is created. The default constructor gets called, and setter methods are used to bring back the state (attributes) of my SFSB.

When I use the Seam lookup, no default constructor is called and no setter methods are called. I just have the instance. The same instance as the previous lookup.

So what's the difference? And what is the best way to use?

Jochen Hebbrecht
  • 733
  • 2
  • 9
  • 23

1 Answers1

2

From the doc: This method returns a singleton for the specified component, so calling it twice in a row with the same component name will return the same instance of the component.

Petr Mensik
  • 26,874
  • 17
  • 90
  • 115
  • @"Petr Mensik": yes, thanks. But why is the JNDI lookup also not returning the singleton? It's creating a new SFSB. – Jochen Hebbrecht Aug 27 '12 at 07:55
  • Because container is required to always return new instance. The reason is that `Statefull` beans are not pooled but created per users request. – Petr Mensik Aug 27 '12 at 08:09
  • @"Petr Mensik": so Seam creates a SFSB, and puts it in a pool/container. If we call it, it gets the SFSB from the pool. JNDI lookups only store the attributes of the SFSB in the EJB cache. If we call a SFSB, it will create a new instance and the attributes are retrieved from EJB cache and imported in the instance using setters method. Am I right? – Jochen Hebbrecht Aug 27 '12 at 08:52
  • @PetrMensik that's not correct. There is no such thing as the EJB cache. When you lookup a SFSB from JNDI you get a clean new instance. It will not magically be given state, since that's up to the client to do. Think about it: with 100 clients, how would the container know which state to restore? If a client holds on to an instance (a proxy) and doesn't use it for some time, the container may passivate the bean. If the client used the instance again, then that particular instance will have its state restored. If that same client did a JNDI lookup again, it would get a totally seperate instance – Mike Braun Aug 28 '12 at 08:25
  • @MikeBraun: so using JNDI, the state is stored by passivating the bean. But if I recover it, it's still a new instance? So what's the use of passivating the bean? The state will get lost? – Jochen Hebbrecht Sep 10 '12 at 15:22
  • No, using JNDI you get a new instance and a new proxy. The use of passivation is to save server memory if you don't use the bean via its proxy for some time. State will not get lost as long as you use the same proxy. – Mike Braun Sep 11 '12 at 08:30
  • @MikeBraun: ok, by using JNDI, a new instance and proxy is created of my SFSB. How does the container inject data of the private attributes? If it creates a new instance, where does it store the attributes? – Jochen Hebbrecht Sep 11 '12 at 10:37
  • There are no private attributes to take into consideration. When you inject a SFSB into something, you get a new instance whenever this something is created. As long as you have a reference to the same something, you have the same SFSB. If you're wondering how the container is able to inject into private attributes, then that's a generic question and not specific to a SFSB and passivation. If you're wondering how passivation and serialization works under the hood then that too is a seperate question. In both cases you can post a new top-level question here. – Mike Braun Sep 12 '12 at 08:36
  • @MikeBraun: no, you misunderstood my question I think. The moment I want to call a SFSB with a JNDI lookup, I want to know how the state is restored from the SFSB. Because when I attach my debugger to the SFSB, I can see the default constructor is ALWAYS called when asking for a SFSB, even if I just asked for it. But the private attributes are always restored, even after 2, 3, or 4, ... calls. It always calls the default constructor. So how can it the attributes IN my SFSB be restored? If it always creates a new instance? – Jochen Hebbrecht Sep 13 '12 at 06:41
  • ... by the way, there's ALSO a difference between a JNDI lookup and the annotation @EJB :p ... http://stackoverflow.com/questions/8616285/ejb3-how-jndi-lookup-works?rq=1 – Jochen Hebbrecht Sep 13 '12 at 08:39
  • If you request a new SFSB from JNDI, you will get a new instance and thus the ctor will be called. There has not been any state yet, so no state will be restored. Just think of it. My bean has a private propery "name". I just started the AS and request this SFSB. Will Java just invent a name and assign it to this property? Will it by itself come up with "Jochen" or "Mike"? ;) Of course this does not happen. If you still think this does happen, you are either doing something very wrong and it might be a topic for a new question, or you have a buggy EJB implementation. – Mike Braun Sep 14 '12 at 08:30
  • @MikeBraun: yes, that's correct. The first time you ask a SFSB, private attributes will not have any state. But 1) ask SFSB 2) call a method on the SFSB so a property "message" is set to value "hello world" 3) ask again for SFSB using JNDI lookup 4) constructor of SFSB is called 5) value "hello world" is restored in the property "message". Can you explain me why step 5) is executed? – Jochen Hebbrecht Sep 17 '12 at 06:37
  • That looks like an interesting case for a new question. It normally should not happen, unless the bean has an explicit scope. Can you post a new question with the full source of the bean and the code where you do the JNDI lookup? – Mike Braun Sep 17 '12 at 08:46