Dear j2ee users,
I'd like to share other's people experience about
a key point of j2ee architecture.
I have built several Factories in my j2ee application
for holding EJB Interfaces, Generating Unique Primary keys,
and other tasks...
These factories are singleton. It's a waste of memory to istantiate
a Factory for every user. On the other hand true singleton cannot
be guaranteed to exist in a Cluster Environment.
Reading newsgroups I have collected 3 main possible solutions.
The key is WHERE to store the Singleton's reference.
1) The Factories's reference is stored
in a SSB, in the setContext method. The number of Factory created depends
on the size of the SSB pool.Problem: waste of memory creating more istance
of the same class.
2) The Factories's reference is stored in the SSB but the pool size
is set to 1 so the Factories are istantiated only once. Problem: possible
bottleneck of the application.
3) The Factories' reference is stored in the web Context of the application,
ideally when the web's Context is created. Problem: the application is
tied to the web and isn't portable to other type of clients.
What's your opinion about this ?
Other possible solutions?
How about loading a factory in a static field when the factory class is loaded? This will give ~1 factory per VM (maybe more if different class loaders are used to load the factory, but that doesn't really matter).
I do not accept that this solution is in violation of the EJB specification. Practically every serious library I know uses singletons and factories, and they are all stored in static fields. If you do not depend on specific sharing semantics for the static fields (e.g, assume that all beans access the same static field) I don't think using static fields poses an issue.
The EJB specification doesn't even prohibit using read-only static fields, so if you define the factory instance field as:
private static final Factory instance = new Factory();
I don't think there's even a shadow of doubt as to whether or not this is allowed by the EJB spec.
thanks for your reply. Actually I'm unsure where to store the
references of factories....I might keep it in an EJB or in
the web tier...I could also serialize the handle...there are
many possible solutions all with pros and contros.
What do you think
If by Factory you mean an object that simply creates instances of other objects, it seems to me like you really don't need more than one instance per VM that uses the factory (and less is obviously not possible). So storing the factory reference in a static fields seems quite allright to me.
If by factory you mean something more complex, maybe a remote object or something, then of course I would have to rethink my answer. If this is the case, please specify exactly what you mean by "factory".
Well I agree with you Gal (my approach covers the first one you mentioned)
anyway are there any problems with declaring a static field in an EJB that is in a cluster?
Of course there would be problems in clustering environment because you deal with different JVMs here. JNDI or SFSB can sort out this problems on most of appservers (because JNDI trees and SFSB are usually replicated over cluster).
You approach with SLSB (by defining pool size to 1) will never guarantee the consistency of your singleton just because EJB spec says that EJB container can destroy its SLSB bean in every moment of a time when it wants - so you never know even when you have the only one bean in a pool. Plus, SLSB are not replicated over clusters.
Using static field seems to be dangerous because you never know how the classloaders of appserver will behave in each particular case.
I assume that storing factories in JNDI would be a better solution in EJB world (actually, that's the place where Sun themselves store their own "factories" like different DataSources, UserTransactions, EJBHomes, etc.).
I think you missed my point. I recommend using static fields to store factories only when it doesn't matter to have many instances lying around: i.e, when you don't assume anything about the number of loaded instances or the sharing semantics of different instances between the different beans. Under these assumptions, I see no problem with having a static field for a factory.
Access to a static field is blazingly fast compared to JNDI access. Besides, with JNDI you don't access a single instance either. You just have an instance serialized to each machine. So I usually prefer using a static field.
The fact is, static fields *are* used in allmost every EJB bean allready. A lot of basic IO, util classes, etc use static fields. I don't see how the distinction between what the library used uses and what the bean itself uses in this respect. IMO using a static field in a bean is just as safe as calling a class that uses it.