Discussions

J2EE patterns: Semi-Singleton

  1. Semi-Singleton (44 messages)

    The Singleton pattern for me is an extreme statement of an ideal situation where you only ever want one instance of a class. I find myself more often in a situation where it is desirable to have one shared instance but not essential, a good example being that of an InitialContext.

    It does not break anything to have more than one InitialContext instantiated, but there are performance and memory savings, when the InitialContext is threadsafe, in having only one instance. InitialContexts may become 'stale' and the Semi-Singleton approach can recover gracefully from this situation.

    The core reliance of the pattern is on the fact that all reference-altering operations in Java are atomic. Say you have a Context variable:

        static Context _context;

    Any use of this variable from any thread will either return a reference to an object or a null pointer, in a well written VM there will at no time be an indeterminate stage.

    Using this fact one can now write a semi-singleton Context factory looking like:

    public class SemiSingletonContextFactory
    {
        private static Context _context = null;

        ...

        public static Context getInstance() throws javax.naming.NamingException
        {
            Context ctx = _context;
            if(ctx == null)
            {
                ctx = getNewContext();
                _context = ctx;
            }
            return ctx;
        }

        protected static Context getNewContext() throws javax.naming.NamingException
        {
            // Get new instance of Context or InitialCOntext
            // here.
            ...
        }

        public static void invalidateContext()
        {
            _context = null;
        }
        ...
    }

    To complete this pattern I always put this class behind either a lookup cache/factory or a facade using a method like:

    private static final Object lookupObject(String lookup, Class objectClass, int retries) throws javax.naming.NamingException
    {
        Object obj = null;
        try
        {
            obj = SemiSingletonContextFactory.getContext().lookup(lookup);
        }
        catch (javax.naming.NamingException ne)
        {
            SemiSingletonContextFactory.invalidateContext();
            if(retries < MAXRETRIES)
                return lookupObject(lookup, objectClass, retries + 1);
            else
                throw ne;
        }
        catch (RuntimeException re)
        {
            SemiSingletonContextFactory.invalidateContext();
            if(retries < MAXRETRIES)
                return lookupObject(lookup, objectClass, retries + 1);
            else
                throw re;
        }
        obj = javax.rmi.PortableRemoteObject.narrow(obj, objectClass);
        return obj;
    }

    The important part to note is the getInstance() method where the static _context variable is copied into the method ctx variable - this is where the atomic behaviour is relied upon. If the ctx variable is null, then a new instance is retrieved. While a reference to this new instance is placed back in the _context variable the method variable is always used for the return.

    This ensures that even if another Thread has overlapped and called invalidateContext() after the original Thread has got a new context, the new context is still returned to the original Thread. This may mean that at certain times more that one context may be in existence, but the vast majority of the time all Threads are sharing the same context.

    This pattern gives most of the performance/memory benefits of the singleton pattern and it achieves lazy instantiation and staleness recovery without any direct manipulation of Threads which would break the EJB specification. In worst case scenarios it is fractionally slower than an implementation in which a new Context is retrieved for every lookup, in best case scenarios it is nearly as fast as a pure singleton implementation. It is possible to generalise this pattern to any OO language with atomic reference writes/reads, but the simplest implementation is in a garbage-collected language like Java.

    Threaded Messages (44)

  2. Semi-Singleton[ Go to top ]

    This is not thread safe.

    http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html

    You need to synchronize the getInstance() method. This will not be a performance bottleneck. Trust me. Worry about bigger things first.

    Bob
  3. Semi-Singleton[ Go to top ]

    It's not thread safe, but you don't care for the purpose!
    If several threads are there, they all have a local ctx that is returned to the caller with a (the) valid Context. If several enter the if(ct==null) , they all write the static _context and the last write overrides others, but it is also a (the) good Context. At worst, you have done several getNewContext() and not only one to get this Context. what's the problem ? I think it's still a good idea.
     
  4. Semi-Singleton[ Go to top ]

    Pierre,

    Your idea is intuitively right, and that is why many people, even though they know double-checked locking is flawed, still use it thinking the only problem that can result is duplicate instanciation. This is not the case. In fact, double checked locking does not allow duplicate instanciation (AFAIK from my analysis of the current JMM, please correct me if I'm wrong). The problem that we do *know* double-checked locking has is that one thread may access the Context created by another thread before the constructor of the Context has even been run. And even if the constructor has allready run, the JMM does not require that the second thread "see" the values assigned by the contructor unless it has entered a synchronized block (and the thread that ran the constructor exited a synchronized block). Again, you can see the links posted above by myself and others for a full explanation of this problem, and other problems with double-checked locking.

    Gal
  5. Semi-Singleton[ Go to top ]

    So basically, what this means is that the design pattern 'service locator' as mentioned in J2EE patterns(Sun) is also flawed:
    <snip>
    private static ServiceLocator me;
    InitialContext ctx = null;

    private ServiceLocator <snip>{
      try{
        ctx = new InitialContext();
    <snip>
    }

    public static ServiceLocator getInstance(){
      if (me == null){
        me = new ServiceLocator();
      }
      return me
    }
    <snip>

    obviously two (or more) clients can pass the if(me == null) at the same time with all the above mentioned problems.
      
  6. Semi-Singleton[ Go to top ]

    So basically, what this means is that the design

    > pattern 'service locator' as mentioned in J2EE pattern
    > (Sun) is also flawed:

    I think it is. I fail to see any good justification for habitually doing lazy instantiation of re-usable infrastructure objects (ie Flyweights, Singletons) in an EJB application.

    If you need to create an object, or a pool of objects, and share them among threads then it seems that whereever possible you should create them at startup (ie force a classload and set it up, not just use static initializers).

    Sean
  7. Semi-Singleton[ Go to top ]

    I am not sure if it is legal to create an InitialContext from outside the context of an EJB method or callback (and expect the EJB environment to be loaded, anyway).

    Anyway, AFAIK the code mentioned by Sven is indeed flawed. I see very little overhead in synchronizing the method, and I seriously doubt that overhead merits this level of attention and thought. Even if it does, I have yet to see a single technique which complies with the specs completely.

    Gal
  8. Semi-Singleton[ Go to top ]

    This seems like a good place for this question! :-) It has to do with the Service Locator pattern. My implementation closely resembles the implementation prescribed by Sun's J2EE Pattern Catalog. However, this statically cached naming context causes some issues. The problem I'm talking about deals with resolving lookups properly to the calling component's environment naming context (ENC). Consider an enterprise application which contains two session beans, A and B. Both of these session beans declare ejb references named ejb/other which points to the other's home object (ejb/other points to B for A and ejb/other points to A for B). Anyway, in Sun's reference implementation, all works fine. However, when using JBoss, it doesn't work properly! It seems that the naming implementation in Sun's RI decides which component's ENC to use at LOOKUP time. But, JBoss' implementation decides which component's ENC to use at CREATION time! So, in JBoss, if session bean A calls ServiceLocator.getInstance() first, a naming context is created representing session bean A's ENC. So, a lookup of ejb/other returns a reference to session bean B's home object. Now, session bean B calls ServiceLocator.getInstance() and it merely returns the cached instance (which represents session bean A's ENC). So, a lookup of ejb/other will again return a reference to session bean B's home object! Nasty! I have confirmed this with the folks at JBoss and this is intentional for performance reasons (although the told me that I could provide a patch that could be turned on in jboss.xml). The easiest way to keep track of which component's ENC to use is with Thread Local variables. The JBoss folks chose to check the thread local variable at creation time as opposed to each time a lookup is performed.
  9. Semi-Singleton[ Go to top ]

    I guess I forgot to put my question at the end! Duh! Does this follow the J2EE spec? Is the spec ambiguous enough so as to allow such a variance in functionality?
  10. Semi-Singleton[ Go to top ]

    One thing I am not sure or: the argumentation against this pattern is about how allocation is done; it claims that it in:

      x = new X();

    memory could be allocated and x assigned before X() is executed; however, shouldn't the priority of operators plays a roles here ?

    the operator new, which atomatically allocate memory then call X(), is executed before the "=" ? In this case, I guess the pattern is good.


    Loïc
  11. Semi-Singleton[ Go to top ]

    The problem occurs in multiple-thread situations. There is a relatively large amount of independency between the order of "logical" operations performed by a thread (which is allways as you described) and the order in which these operation are performed in the main memory, i.e the order in which they are conceived by other threads. This is neccesary to allow reasonable performance and performance optimizations, including:
    - register caching of memory
    - per-CPU cache memory
    - ...

    Just because you changed two parts of the memory doesn't mean another thread will see both. It's enirely possible for it to see new values for one memory location, but read a stale cached version of the other.

    Gal
  12. Semi-Singleton[ Go to top ]

    This pattern does not work, as Bob has indicated. If you want a good technical review of this issue, you might want to take a look at:
    http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
    For a more "high-level" overview, the JavaWorld article (listed by Bob) is probably easier to understand.

    The two references actually describe a slightly different pattern called "double checked locking" where a synchronization occurs inside the "if" statement. However, this pattern is also broken.
    What's basically wrong in this pattern is a very common mistake regarding ordering of memory operations in Java. When no synchronization occurs, Java memory operations performed by one threads may be seen "in different order" by another thread. In this particular case, a thread may see the value assigned to "_context", but not see the values assigned by the Context constructor. Thus, the second thread will see the "default" values for the fields of the Context object, which are quite probably invalid. ctx will not be null, but it will be invalid.

    Several attempts have been made at fixing this (and other) problems using volatile variables, double-checked locking, etc. It just doesn't work in the current Java Memory Model. Adding one synchronization on "getInstance" will probably make absolutely no difference performance-wise. It also does not break the spec, as some people argue. EJBs use synchronized methods all the time. Whenever you add an item to a Vector, you use a synchronized method. That's certainly not forbidden by the EJB spec.

    Gal
  13. Semi-Singleton[ Go to top ]

    Hmmm... you're quite right about the memory ordering, thank you for putting it so nicely. I've yet to run with this pattern in a production system though it so far has worked in various JVMs I've tried it on. (I know, I know. So far is no good, it's the millionth time when it blows up spectacularly that is the problem.)

    Synchronizing would mean that we may as well use a true Singleton pattern as this approach would end up with near identical performance to Singleton without the memory advantages.

    I am well aware of Double Check Locking's issues, this wasn't particularly an attempt at 'fixing' double check locking as you will note that nowhere am I attempting to use a non-synchronized gate variable though my approach falls down in an extremely similar way.

    My reading of the EJB 1.X specs was that any form of intra-thread activity was to be avoided including synchronization. In the case of using a Vector in EJBs, it is usually a thread local instance so the Synchronized block has no intra-thread behaviour. I'd be interested to hear if my understanding of that is wrong.
  14. Semi-Singleton[ Go to top ]

    I believe the pattern you are looking for is flyweight. The singleton can be thought of as a flyweight with a pool size of 1
  15. Semi-Singleton[ Go to top ]

    "Synchronizing would mean that we may as well use a true Singleton pattern as this approach would end up with near identical performance to Singleton without the memory advantages."
    Well, what you would get would not be a *real* singleton, in the sense that multiple instances may be instanciated in your application (i.e, across multiple nodes of a cluster) or even in a single VM (i.e, with different class loaders, depending on the App server's class loading facility). In that sense it would be a "semi-singleton", which I do consider to be a very useful construct.

    "I am well aware of Double Check Locking's issues, this wasn't particularly an attempt at 'fixing' double check locking as you will note that nowhere am I attempting to use a non-synchronized gate variable though my approach falls down in an extremely similar way."
    I realize that. I ment to say that since these two patterns are similar, efforts to "fix" this pattern are likely to fail for the same reasons they failed with double-checked locking.

    "My reading of the EJB 1.X specs was that any form of intra-thread activity was to be avoided including synchronization. In the case of using a Vector in EJBs, it is usually a thread local instance so the Synchronized block has no intra-thread behaviour. I'd be interested to hear if my understanding of that is wrong."
    This is where things get a little complicated, maybe even philosophical. From the EJB spec:
    "An enterprise Bean must not use thread synchronization primitives to synchronize execution of multiple instances."
    The question is, what exactly does "to synchronize execution of multiple instances" mean. I think it would be very unlikely for anybody (i.e, App server makers) to interpret this rule as "you can't use synchronization to synchronize threads alltogether". The main reason is that many Java libraries use constructs such as Singletons, which require synchronization at some level. It seems quite restrictive to rule out all such libraries (my bet is it would essentially rule out atleast 90% of the libs, but I can't say that for sure :)). Therefore, I interpret this rule to mean "don't use synchronization to make multiple instances of a bean block each other" - that will obviously not work with clusters or even within a single VM in some cases. This interpretation is also consistent with the spec's rationale for the rule:
    "...Synchronization would not work if the EJB Container distributed enterprise bean’s instances across multiple JVMs."

    You can read that rule to mean both these things (and probably other variations as well). My interpretation is certainly more useful for you as a programmer... I hope it's not too risky :)

    Gal
  16. Semi-Singleton[ Go to top ]

    I see what you mean about philosophical...

    "Well, what you would get would not be a *real* singleton, in the sense that multiple instances may be instanciated in your application (i.e, across multiple nodes of a cluster) or even in a single VM (i.e, with different class loaders, depending on the App server's class loading facility). In that sense it would be a "semi-singleton", which I do consider to be a very useful construct."
    Yes, this semi-singleton pattern could have useful/interesting behaviour (if properly synchronized) on certain appservers under specific JVM/Classloader configurations. Having used BAS, EAS and WL in anger I know how their specifics of JVM/Classloader implementation can make for interesting optimization differences. Which is why nowadays I keep a permanent Context and Lookup Factory toolkit so I can completely alter the threadsafety / caching / optimization behaviour of my code using configuration options depending on the appserver I'm using.

    I would propose fixing this pattern (from the point of view of exploring the JVM/Classloader behaviour) by making the Context getting line look like:

        Context ctx;
        Synchronized(_context)
        {
            ctx = _context;
        }

    So now that is done - what useful techniques/tricks do you think we could do with this? I'm developing a few ideas, but they're not full formed yet.
  17. Semi-Singleton[ Go to top ]

    What exactly do you propose in order to fix this pattern?

    "I would propose fixing this pattern (from the point of view of exploring the JVM/Classloader behaviour) by making the Context getting line look like:

        Context ctx;
        Synchronized(_context)
        {
            ctx = _context;
        }
    "

    Perhaps I don't understand your intention. If you just replaced the "Context ctx = _context" line with this code, your code will fail completely: you attempt to synchronize on the monitor of a null reference. A null pointer exception will be thrown.
    Could you please post the complete code you would use, so that there would be no misunderstandings?

    Gal
  18. I have a couple of questions.

    1-Why are you worried that your InitialContexts would become stale? How would this happen?

    2-Isn't the entire point of JNDI cacheing to re-use the stubs that are being downloaded from the JNDI tree? In which case a singleton based cacheing mechanism would be sufficient as long as you were not programmatically modifying the JNDI tree. The only things that would invalidate the cached stubs would be a redeployment or a non-transparent failure of a server hosting a non-clustered resource. And that's a different set of problems best solved by having some facility to refresh the contents of your singleton-based cacheing mechanism.

  19. Also note that the InitialContext instance is not necessarily thread safe.

    Bob
  20. Initial Context not Thread safe[ Go to top ]

    Hi

    Is that true? I often cache the initial context and reuse it. I have a class that deals with all the look ups using a singleton pattern (initialised statically when the class is loaded - standard java approach). We haven't had any problems with it , I assumed it was thread safe because I've seen so many examples talk about reusing the context because it is expensive to initiate. Should I be using a pool of contextx instead?

    Nick
  21. Initial Context not Thread safe[ Go to top ]

    Your particular InitialContext implementation may be thread-safe, however the InitialContext javadoc says:

    "An InitialContext instance is not synchronized against concurrent access by multiple threads. Multiple threads each manipulating a different InitialContext instance need not synchronize. Threads that need to access a single InitialContext instance concurrently should synchronize amongst themselves and provide the necessary locking."
  22. Semi Singleton[ Go to top ]

    PErsonally I use a plain

    protected InitialContect ctx = new InitialContext();


    with no static. This is not a big memory hit in SessionBeans if they are reentrant, cause they are pooled, and only 1 or 20 exist. Sadly it is a bit worse for StatefulSessionBEans or EntityBeans.

    Advantage 1: no concurrent usage
    Advantage 2: no static / no synchronized
  23. Semi-Singleton[ Go to top ]

    Sorry about the time to respond, I was a touch ill over the w/e.

    I re-read what I wrote and it would never work, I evidently was not paying proper attention.

    The thing is that any proper synchronization would turn this into a variation on the classical (GOF) singleton pattern, no bad thing as it is a stable pattern. It has always been in the back of my mind however that any implementation of the GOF singleton in Java would depending on which classloader it was loaded in lead to either singleton on a JVM or singleton on a classloader hierarchy branch. Is this what you were thinking of in your previous post? - "Well, what you would get would not be a *real* singleton, in the sense that multiple instances may be instanciated in your application (i.e, across multiple nodes of a cluster) or even in a single VM (i.e, with different class loaders, depending on the App server's class loading facility). In that sense it would be a "semi-singleton", which I do consider to be a very useful construct"

    Bob B.
  24. Semi-Singleton[ Go to top ]

    I think we've almost all been down that exact road ourselves at one time or another. I know that I have at least. ;)
  25. Semi-Singleton[ Go to top ]

    Yes, that's exactly what I said.
    While this situation (multiple class loaders) is generally possible in Java applications, it is much more concrete in the EJB context. Most "normal" Java applications are loaded by the same classloader, or, at the very least, you have control over the class loading hierarchy. In EJB you have no control over the class loading strategy your App server will use (atleast not portably). Further, it is a normal and standard practice for EJB App servers to use different class loaders from different beans. So this issue is "concrete".

    Gal
  26. Semi-Singleton[ Go to top ]

    The only time it would really blow up is if the first couple requests come at the same time. The chances are slim, but possible.

    If you really want to avoid synchronization, you can initialize your value statically or from a startup class (in the event that it depends on app. server resources).

    Bob
  27. Semi-Singleton[ Go to top ]

    Yes that is exactly what I did, I used to static initialisation straight off to give the _context variable a valid initial variable.

    That also explains why I was able to say 'So far' on it working. However I think that you would still end up in the same bad place if some thread had later called the invalidate method setting the _context variable back to null.
  28. Semi-Singleton[ Go to top ]

    If it is acceptable to have more than one instance, you could also use ThreadLocal. Multi-thread issues are avoided. You end up with one instance per thread. Of course, if your server creates a new thread for each request you have no benefit, but this is bad design anyway.

    JCG
  29. Semi-Singleton[ Go to top ]

    I suggest to fix the pattern by this way :

    "
    public class SemiSingletonContextFactory {

    private static Context _context = null;

        ...

        public static Context getInstance() throws javax.naming.NamingException
        { if ( _context == null )
            Context ctx = _context;
            synchronized(SemiSingletonContextFactory.class) {
               if(ctx == null)
               {
                ctx = getNewContext();
                _context = ctx;
               }
            }
            return ctx;
        }
    "
    What do you think about this ?
  30. Semi-Singleton[ Go to top ]

    It doesn't work either. Would you people please just drop the whole double-checking thing??? :)

    Seriously, read the sites I linked above for an explanation of some potential problems.

    Gal
  31. Semi-Singleton[ Go to top ]

    How about this one:

    public class SemiSingletonContextFactory {

    private static Context _context = null;

        ...

        public static Context getInstance() throws javax.naming.NamingException
        { if ( _context == null )
              synchronized(SemiSingletonContextFactory.class) {
               if(_context== null)
               {
                 Context tempContext = getNewContext();
                _context = tempContext;
               }
            }
            return _context;
        }
    isnt reference assignment threadsafe?
  32. Semi-Singleton[ Go to top ]

    No, this is not thread safe.
    The most obvious of the errors in this code is that threads may see an uninitialized context object. I suppose you are trying to avoid this using the tempContext local variable. That would fail for several different reasons:
    1. Prescient store operations by the VM can store the _context reference before the initializer runs.
    2. The order of "assign" operations is not bound to be the same as the order of "store" operations. A thread might assign values in the right order, but write them to the main memory in the wrong order (usually occurs in multi-CPU environments only). Only a synchronization point forces the thread to write it's local cache to main memory.
    3. A thread which accesses the reference without performing synchronization doesn't have to see the real values of stored variables even if they were allready written to the main memory: only a synchronization point forces it to clear it's local cache (i.e local-CPU cache memory, register cache, etc).

    Gal
  33. Semi-Singleton[ Go to top ]

    OK, Can any one point me to code that *tests* the various approaches mentioned ?..So as to illustrate that the pattern actually fails under the right mix of conditions.
    Raja
  34. Semi-Singleton[ Go to top ]

    Generally these problems are hard to detect, which is why they are elusive enogth to sneak into a lot of code and many popular books.
    The code doesn't *have* to work under the Java Memory Model semantics. That doesn't mean it won't work under a particular implementation, only that it is not guaranteed to work on *all* implementations.

    To see these problems in practice you probably have to use a multiprocessor machine, and also have some luck. Note however that correctness is not guaranteed even under single-CPU machines. For more information see Pugh's java page (link posted in my first message).

    Gal
  35. Semi-Singleton[ Go to top ]

    How about this solution:

    import javax.naming.*;

    public class SemiSingletonContextFactory {

        private static Context context = null;

        ...
        private static class Flags extends ThreadLocal {
                 boolean flag1 = false;
        };

        private static Flags init = new Flags();
     
        public static Context getInstance() throws javax.naming.NamingException
        {
             if(!init.flag1)
             {
                  init.flag1 = true;
                  synchronized(SemiSingletonContextFactory.class)
                  {
                     if(context == null)
                     {
                        context = getNewContext();
                     }
                  }
             }
            return context;
        }
    }
     
    Ok, it just handles the initialization part, but at least it avoids to
    synchronize every time and the JVM could optimize the thread locale storage access.
  36. Semi-Singleton[ Go to top ]

    Indeed, the ThreadLocal class can definitely help, but storage need to be accessed through its get and set methods, as opposed to inheritance of the class.
    In the Windows server jvm (activated by using "java -server") version 1.4.1, my test app runs about 7000 times faster than without using ThreadLocal.

    The code to use would then have to look like this:

    private class SemiSingletonContextFactory {
        private static Context context = null;
        private static ThreadLocal initHolder = new ThreadLocal();
        ...
        public static Context getInstance() throws javax.naming.NamingException
        {
             if(initHolder.get() != null){
                  synchronized(SemiSingletonContextFactory.class) {
                     initHolder.set(Boolean.TRUE);
                     if(context == null)
                        context = getNewContext();
                  }
             }
            return context;
        }
    }
  37. Semi-Singleton[ Go to top ]

    Yes, this strategy is described in William Pugh's page. However last time I checked (on HotSpot 1.3 I think) it didn't improve performance because of ThreadLocal's not-so-efficient implementation. Has anyone checked this on 1.4? They were supposed to improve ThreadLocal performance...

    Gal
  38. Semi-Singleton[ Go to top ]

    Hey Wolfgang, I didn't notice you said you tested it and it turned out this fast... I'll try to also run a test of my own and post it here.

    Thanks for the info.
    Gal
  39. Semi-Singleton[ Go to top ]

    Thanks for your reply.
    There was a small error in the example.
    Of course, it would need to test for == to null:

    private class SemiSingletonContextFactory {
        private static Context context = null;
        private static ThreadLocal initHolder = new ThreadLocal();
        ...
        public static Context getInstance() throws javax.naming.NamingException
        {
             if(initHolder.get() == null){
                  synchronized(SemiSingletonContextFactory.class) {
                     initHolder.set(Boolean.TRUE);
                     if(context == null)
                        context = getNewContext();
                  }
             }
            return context;
        }
    }

    As to speed, results will vary greatly depending on processor cashing.

    w.g.
  40. Semi-Singleton[ Go to top ]

    Usually this is what I'm using and it works always with no problem ...


    ///////////////////////////////////////////////

    public interface IEJBLocalFactory
    {
      EJBLocalHome getEJBLocalHome( String param ) throws NamingException;
    }


    ///////////////////////////////////////////////

    public class EJBLocalFactory implements IEJBLocalFactory
    {

     private InitialContext ejbContainerContext;

     private void setEjbContainerContext( InitialContext param )
        {
          ejbContainerContext = param;
        }

     private InitialContext getEjbContainerContext()
        {
      return this.ejbContainerContext;
        }


     protected EJBLocalFactory() throws NamingException
        {
          setEjbContainerContext( new InitialContext() );
        }

        public static EJBLocalFactory getInstance() throws NamingException
        {
                if ( instance == null )
                {
                    synchronized( EJBLocalFactory.class )
                    {
                        if ( instance == null )
                        {
                            instance = new EJBLocalFactory();
                        }
                    }
                }
                return instance;
            }

     public EJBLocalHome getEJBLocalHome( String param ) throws NamingException
     {
      return ( EJBLocalHome ) ( getEjbContainerContext() ).lookup( param );
     }

    }


    ///////////////////////////////////////////////
    and in-ejb usage

    private static IEJBLocalFactory ejbFactory;

     private static IEJBLocalFactory getEjbFactory() throws NamingException
        {
      if( ejbFactory == null )
            {
               ejbFactory = EJBLocalFactory.getInstance();
            }
            return ejbFactory;
        }

    regards,
  41. Semi-Singleton[ Go to top ]

    sorry I forgot to add ...

    private static EJBLocalFactory instance = null;

    regards again ...
  42. Semi-Singleton[ Go to top ]

    This is double checked locking. It is flawed. It is not a proper use of Java synchronization primitives, and leaves room for race conditions. I would explain why, but I allready did - in this thread. And I allready linked two web pages explaining the various different errors in this code (yes, there is more than one).

    Gal
  43. Semi-Singleton[ Go to top ]

    Yes, you are totally right I don't need to argue about "Double-Checked Locking" well known paradigm
    I just tried to show a pattern what I use when I try to decrease the possibility of "Double-Checked Locking" occurrence.
    When you use tread safe support offered by basic java architecture over objects and you try to "catch" in the same
    time the requirement from the ejb container to offer a tread safe access to class instances I think you minimize
    a lot the chances to succeed to this situation. That's all, it's a workaround and I think that in 99,999% of situations
    will work ...
    regards,
  44. Semi-Singleton[ Go to top ]

    It's a workaround for what? Why not just use normal synchronization? Simply replace:
    public static EJBLocalFactory getInstance() throws NamingException {
        if ( instance == null ) {
          synchronized( EJBLocalFactory.class ) {
            if ( instance == null ) {
              instance = new EJBLocalFactory();
            }
          }
        }
        return instance;
    }

    With:
    public static *synchronized* EJBLocalFactory getInstance() throws NamingException {
      if (instance == null) instance = new EJBLocalFactory();
      return instance;
    }

    This code is simpler and more readable then the code you posted. It is just as compliant with the EJB spec. And, of course, there are no multithreading *bugs* in it. The only advantage of the double checked locking version that I can see is that it's potentially faster, and even that will not be noticable in practice, I suspect.

    Gal
  45. Semi-Singleton[ Go to top ]

    First, is just a workaround because as you mentioned is not eliminating completely the ... ;-) problem. I assumed that cheeking first at the bean level where the server should offer a thread safe access, and after in the factory the request will appear as a server thread safe request, because this design basically will create one instance per container at the moment when the first ejb will be in a ready state doesn't matter if after creation, activation bla bla bla ... so thinking that always in a system will exist a first call this first call will instantiate correct the attribute ... and after, as you pointed, all will be especially much faster exactly because the class it-self is not * synchronized * and the * synchronized * request will appear only once when there is a null reference.