EJBean Class Initialization Hooks

Discussions

J2EE patterns: EJBean Class Initialization Hooks

  1. EJBean Class Initialization Hooks (37 messages)

    As per EJB specs, EntityBean and SessionBean classes already contain a lot of helpful hook methods that are called by the container during different states of client-server interaction. Some of these methods include setEntityContext, ejbActivate and ejbFindByPrimaryKey. What I found missing from the specs, though are overridable hook methods that denote the various initialization stages of my beans in relationship to the container. If I had my way with the specs, I would also include the following methods in an abstract bean super-class:

    public abstract class AbstractEJBean
    {
        public void intializeOncePerBeanClass();
        public void initializeOncePerInstance();
        public void initializeEveryContextSwap();
    }

    Unfortunately, the last time I checked, I am not under Sun's payrole nor do I have much direct influence in the ejb specs. And even if I do have a indirect voice through the JCP, I'm afraid the process is so bureacratic and laborious that by the time these simple hook methods are standardized, we will be on EJB 4.0! Hence I've taken matters into my own hand and implemented these hook methods by "tricking" the container to call them. My implementation does not break the current EJB spec (well, all but one minute detail, although it's debatable.. more on that later), and more importantly, my implementation works on any vendor that abides by the current EJB 1.0, 1.1 or 2.0 spec.

    My first method, initializeOncePerBeanClass(), is analogous to a static block for initializing services rendered useful to all bean instances of a specific class. So why not simply use a static block to do this, you may ask? Such as:

    class MyBeanClass
    {
        private static Service service1;
        ...

        static
        {
            service1 = jndiContext.lookup();
            ...
        }
    }

    Well, you can, but you will find two shortcomings by using the static block; shortcomings which are fixed by my pattern:

    1) The static block gets called sequentially, from top to bottom, the moment your bean class is classloaded. This may not be the right time, or order, in which you want your static block called!
    2) The static block is not polymorphic. If a class has a static block, this block will get called when the class is loaded! You do not have an opportunity to override a static block.

    The second method, initializeOncePerBeanInstance(), is basically a default-no-args bean constructor. Since EJB specs prevents you from implementing a bean class constructor, this is a nice way to get around it. And besides, an initialization method, unlike a constructor, is polymorphic.

    And finally, the third method, initializeEveryContextSwap() is a no-brainer: it will be invoked every time the bean Context changes.

    Now you have three new hook methods. So where and when do they get invoked? The trick is to implement a FOURTH hook method that will call the first three hook methods, and here it is:

    public abstract class AbstractEJBean
    {
        private boolean isInstanceInitialized = false;
        private static Set initializedBeanClasses = new HashSet();

        protected void onSetEJBContext()
        {
            if (!isInstanceInitialized)
            {
                //This block of code needs to be synchronized because the sequence of execution is critical,
                //and HotSpot 2.0 mangles the order if synchronized block is removed!

                synchronized(this.getClass())
                {
                        if(!initializedBeanClasses .contains(this.getClass()))
                        {
                                initializeOncePerBeanClass();
                                initializedBeanClasses.add(this.getClass());
                        }
                        initializeOncePerInstance();
                        isInstanceInitialized = true;
                }
            }
            initializeEveryContextSwap();
        }
    }

    And finally, you will have to call onSetEJBContext() from both your abstract entity and session bean classes. I will provide one as an example:

    public abstract class AbstractEntityBean
        extends AbstractEJBean
        implements EntityBean
    {
        public void setEntityContext(EntityContext context)
        {
            this.context = context;
            onSetEJBContext();
        }
    }

    There you have it, your own set of overridable initialization hooks for all your beans! Note you can specify in your own architecture and documentation whether you want these init methods to be purely polymorphic (complete override) or semi-polymorphic (Delegate pattern where each init() first calls super.init(), e.g. HttpServlet.init() ). Furthermore, if you do not want a specific bean class which extends AbstractEJBean to exhibit any of these initialization overheads, then override onSetEJBContext() as a no-op method.

    And finally, to address the issue I mentioned initially that my implementation may not fully comply with EJB specs, I bring to your attention the part of onSetEJBContext() which uses a synchronization block, locking on this.getClass() mutex. Depending on how much a stickler you are of the EJB specs, you may condemn this as an absolute no-no, or you can casually overlook it as long as your container vendor does not complain, and I believe most vendor bean compilers do not! The reason why I synchronize this block of code is because I expect initializeOncePerBeanClass() to always be called before initializeOncePerInstance() for I have services in the former method that will be used by the latter. And without this synchronization block, in a multi-threaded SMP environment, I've seen some heinously mangled call orders! If you do not have this restriction, or you consider using "synchronized" keyword in EJB heresy, then omit the block!

    I think these hook methods are a nice, clean and uniform way to provide initialization services to all your beans at various stages of their nascent lifecycle. I hope you find great use for them in your architecture as we have in ours!

    Threaded Messages (37)

  2. I really like this pattern. It's a great place to put your bean's initialization calls in. For example, in this article: http://www.javaworld.com/javaworld/javatips/jw-javatip110.html I assumed a call to the registry on ejbActivate/ejbCreate. This pattern really improves the process of initialization. Of course, it's just one of the many cases where this pattern is convenient. Thank you Gene!
  3. Thanks to all those who commented on my pattern, both positively or negatively. Both types only needs to further refinement and community development, which is the whole intent of this site!

    I realize that both of my "patterns" I've posted on theserverside (FatKey being the other), aren't truly patterns, but temporary "workarounds" for EJB spec deficiencies. True Patterns, such as those in GoF, endure the test of time and remain relevent across not just slight language modifications, but across languages all together. (Another example of an almost-pattern is the Double Checking Lock for Singletons... it sounded good at the time!) But most of us are not patient enough to wait for the EJB specs, so I hope these pseudo-patterns provide temporary relief!


  4. EJBean Class Initialization Hooks[ Go to top ]

    Gene

    A question about the initializeEveryContextSwap(); method.
    As I understand the ejb spec setEntityContext is only called once per bean instance (?) - so does this not mean that effectively initializeEveryContextSwap() will only be called the same time as initializeOncePerInstance(); ??

    Is this the behaviour you see in your own App server?

    Luke
  5. EJBean Class Initialization Hooks[ Go to top ]

    Hi Luke,

    Good point, set/unsetEntityContext is only called once in a bean instance lifecycle. Hence initializeOnceEveryContextSwap() would be the same as initializeOncePerBeanInstance().

    The hook method I was thinking of that's called frequently throughout the lifespan of a bean instance is ejbActivate()/ejbPassivate(). Hence if you want to do (re)initialization procedures whenever, say, the client of the bean switches, then its best to put the hook procedure here.

    Gene

  6. EJBean Class Initialization Hooks[ Go to top ]


    Gene,

    I have to wonder if you and I are reading the same spec.

    More than anything else I mentor to my customers is to read
    the spec and then understand the life-cycle of the bean
    being used. Understanding the points as to where the
    container and the client interact with the particular bean
    in its life-cycle determine how it behaves.

    My I be so bold as to suggest the same? The caveat in all
    of this is based on the particular implementation of the spec.

    All of what your are suggesting is already there...

    Cheers,

    Noel.
  7. EJBean Class Initialization Hooks[ Go to top ]

    Hmm, your message seem to insinuate I'm completely incompetent and unfamiliar with the ejb specs. My confidence is absolutely shot!

    If indeed, "all of what your suggesting is already there", then please point to a callback hook that gets called once per bean class... I would love to be further humiliated!

    Gene


  8. I think there is a slight danger in your implementation of
    initializeOncePerBeanClass(); . You suggest storing your set of initialized classes in a static variable. In a clustered environment or an environment with multiple class loaders you are not guarenteed that this code will execute only once. Using non final statics in your bean class is not permitted in the spec.

    Stu
                                
  9. Hi Stu,

    Yes, iOPBC() will be called once in each Node of a cluster. And for most people, this is what they want: to initialize class-specific services of a bean in each container of a cluster.

    True, multiple ClassLoaders exist in a single container. But only a single ClassLoader should load up your bean class; otherwise you'll have more problems than what this pattern expose! :-) The only scenario where I see you purposely want multiple ClassLoaders loading a single bean class is if you reuse a bean class in two different ejb components (jars). And in this case, it does make sense for iOPBC() to be called twice, for the two beans occupy entirely different namespaces and should be initialized independently, as if they are in different containers or different nodes all together.

    And finally, good catch, I do have a non-final static reference in my bean class. So I guess this pattern is only 90% spec-compliant! :-)

    Gene
  10. Hi Stu,

    Actually I take it back: my pattern doesn't have to be only 90% spec complaint! There's no reason why my sole static variable CAN'T be final, as in:

    private static final Set initializedBeanClasses = new HashSet();

    The reference to the HashSet will never change, but the HashSet itself is still mutable. Thanks for catching my mistake!

    Gene
  11. EJBean Class Initialization Hooks[ Go to top ]

    Gene,

    I like this pattern pretty well, but it is still disappointing. (but that's not your fault, it's Sun's)

    Any way I see it, I still have to do one of two things:

    1) Put code that calls the hook method in *every* EJB

    2) Make a base class to extend (such as your "AbstractEJBean"), and then loose the possibility of inheriting from the class that I really need to.

    ...I wish sun provided a "freebee" hook method or two.
  12. James -

    regarding point #2 - You could either have the class you really want your EJB to inherit from extend the "AbstractEJBean" (which is ugly) - or you could change the AbstractEJBean to not be abstract, and then just use an instance of the bean to call the onSetEJBContext method.
  13. I cannot think of an example - what 'once per class' initialization spec-legal EJB can possibly do?
  14. Hi Dimitri,

    How about initializing services that is shared by all bean instances of the same class? Now I know there's the stupid ejb spec rule that one cannot have a non-final static reference, hence you would think the once-per-class hook is useless because final static references need to be initialized at ClassLoading time. Buth there is always a way around this rule, which is to have a static final reference to, say, a Map, that holds all your class-global services. So here's an example:

    class MyBean
    {
        private static final Map CLASS_GLOBAL_SERVICES = new HashMap();

        public void initalizeOncePerClass()
        {
            CLASS_GLOBAL_SERVICES.put("service1", context.lookup(service1));
            ...
        }
    }

    Is that good enough for all you spec-sticklers? :-)

    Gene
  15. Gene Chuang, seemed to
    indicate in /his/ first reply to the discussion thread, that
    initializeEveryContextSwap is unnecessary because (a)?was he trying to say
    that there is an error and that it should be invoked by ejbActivate instead?
    or (b) that it is redundant since it is guaranteed to be called, in his
    implementation above, right after initializeOncePerInstance is called.

    First of all, isInstanceInitialized is not needed since this method is
    guaranteed to be called exactly once. The method initializeEveryContextSwap()
    is not needed too (see my comment above). As far as synchronization... it seems to me that he
    needed to synchronize not for the reason he said (HotSpot 2.0 weirdness),
    but because he is accessing a shared datastructure (the static
    initializedBeanClasses HashSet) in a multithreaded manner. I beleive his
    code to still be in error because if there are more than one subclasses of
    AbstractEJBean, then multiple threads might access that shared datastructure
    because each thread would aquire a different lock (being the class of the
    instance of the subclass extending AbstractEJBean).

    What I would do is this:

    public abstract class AbstractEJBean
    {
    // Collections.synchronizedSet is sufficient
        private static Set initializedBeanClasses =
    Collections.synchronizedSet(new HashSet());

    // added a final
       final protected void onSetEJBContext()
        {
                boolean added= initializedBeanClasses.add(this.getClass());
                if (added)
                    initializeOncePerBeanClass();
                initializeOncePerInstance();
        }
    }

    Disclaimer: I have read EJB specs but haven't programmed EJBs yet.
  16. Hi David,

    I agree with you on your first observation: the boolean flag isInstanceInitialized is redundant and can be removed.

    I partially agree with your second observation. I synchronize not because of "HotSpot Weirdness", but rather out-of-order multithread execution in an SMP environment. (My code comments are old, and I tried mentioning this in my pattern itself but forgot to update the comments! :-))

    However, my synchronization code DOES work as stated in my pattern. Note I am not locking on the shared datastructure (HashSet), but rather "this.getClass()", which equates to locking on different Mutexes for each possible subclass of AbstractEJBean. My purpose of synchronization is not only to ensure HashSet doesn't get corrupted, but more importantly, that initializeOncePerBeanClass always get called before initializeOncePerBeanInstance.

    Gene


  17. "I synchronize not because of "HotSpot Weirdness", but rather out-of-order multithread execution in an SMP environment. "

    Gene,

    I have seen the out-of-order multithread execution and thought it is "HotSpot Weirdness". Your comment on SMP now makes sense.

    I am still not convinced about the requirement for 'once per class' initialization. I can't think of a good example where we need to do this. Can you give us some example usage for it?

    .raja

    .raja
  18. Sure, lets say you got two type of beans, each requiring a different connection pool for some reason. You obviously want all instances of each bean class use the same DataSource, so the best place to initialize the DS would be in iOPBC():

    class AbstractEJB
    {
        private static final Map CLASS_GLOBAL_SERVICES = new HashMap();

        ...
    }

    class EJB1
        extends AbstractEJB
    {
        public void initializeOncePerBeanClass()
        {
            super.initializeOncePerBeanClass();
     
            CLASS_GLOBAL_SERVICES.put("datasource", context.lookup("oracleDataSource"));
        }

    }

    class EJB2
        extends AbstractEJB
    {
        public void initializeOncePerBeanClass()
        {
            super.initializeOncePerBeanClass();
     
            CLASS_GLOBAL_SERVICES.put("datasource", context.lookup("db2DataSource"));
        }

    }

    Does that help?

    Gene
  19. Is that good enough for all you spec-sticklers? :-)


    Hrm. No, static collection makes it possible for bean instances to share non-read-only data. For the datasource thing - why not use bean environment ?
  20. Hi Dimitri,

    Sticking whatever services into this "class-global cache" I shown as an example is up to the whim of the developer. I can only suggest that the service be either Thread-Safe or ThreadLocal. And what's wrong bean instances sharing non-read-only data?

    Actually I came up with pattern BECAUSE of the shortcomings of bean-environment! This was back in the early days when I migrated from WL 4.5.1 to 5.1 (no service pack) and found WL's bean-environment JNDI lookup to be excruciatingly slow, even on subsequent lookups of the same key. Perhaps performance has increased by the current sp, but I figured back then to create a protable bean-environment cache to circumvent this performance issue. Furthermore you can only retrieve from bean-environment and not insert at runtime, and you can only insert certain services into the bean-environment in the descriptors. My class-global bean cache is more flexible.

    Gene
  21. Hi Gene!

    >And what's wrong bean instances sharing non-read-only data?

    Because, I think that all EJB machinery is based on the fact that the container manages bean *instances*, which are completely independent - letting them to share RW data is pretty much the same as using non-final statics.

    Another thing - EJB deployments are not the same as Java classes deployments. For example, if the same bean is deployed several times using different deployment descriptors - most likely once-per-class initialization schema will require some code changes to work correctly - which is not right because EJBs are not supposed to require any code changes to be deployed.
  22. Hi Gene:
    David observation on the synchronize is correct. Since you synchronize on this.getClass(), "this" can be any sub-class, so subclass A, B both have a set. In this case, the set is not required, just a static boolean variable is enough.

    something like this:

    public abstract class AbstractEJBean{
    protected boolean isInstanceInitialized = false;
    protected static boolean initializedBeanClasses = false; protected void onSetEJBContext() {
    if (!isInstanceInitialized) { synchronized(this.getClass()) { if(!initializedBeanClasses)
     {
               initializeOncePerBeanClass(); initializedBeanClasses=true;
       }
                       initializeOncePerInstance(); isInstanceInitialized = true; } } initializeEveryContextSwap(); }}


    or it maybe:
    synchronized(AbstractEJBean.class) { // your original code


    BTW, how to print out the contents in your website? You are using table, which always cuts off the right side part.

  23. Hi:
       Regarding the synchronization, Gene is correct. Although this.getClass() is used as monitor, which means the monitor can be subclass A, subclassB, the static set indeed has only one instance per namespace. And the performance should be better than using AbstractEJBean.class as the monitor.
       I take back my earlier posting.

       Thanks, Gene.

       minjiang

  24. Gene Chuange said, "However, my synchronization code DOES work as stated in my pattern. Note I am not locking on the shared datastructure (HashSet), but rather "this.getClass()", which equates to locking on different Mutexes for each possible subclass of AbstractEJBean."

    Yes, you are locking on different mutexes, and that is exactly the problem because two threads could be locking on different mutexes (two subclasses), and then accessing your shared datastructure (since it's static) at the same time.

    Wang Minjiang said, "Although this.getClass() is used as monitor, which means the monitor can be subclass A, subclassB, the static set indeed has only one instance per namespace."

    That namespace is defined by the ClassLoader which is likely to be the same for all mentioned classes. Since the subclasses access the shared static datastructure using different mutexes, (a static in a subclass is the same field for all subclasses) the code is not thread-safe. By the way, the code you posted in your post prior to where I quoted you is not correct since the static boolean initializedBeanClasses flag is not per-subclass since it is static. Therefore, all subclasses to be initialized after the first one will see initializedBeanClasses as true --not the desired effect. That code is also not threadsafe since multiple threads could be instantiating that particular subclass at the same time causing a race condition where both subclasses see initializedBeanClasses as false.

    I maintain that my conclusions posted on this thread are correct--until proven otherwise.

    Synchronization is very complicated stuff. Before posting my first comment on synchronization to this discussion, I verified my findings at the Java-Memory-Model mailing list which is frequented by those who have a deeper understand of synchronization than I.
  25. Hi David,

    > Yes, you are locking on different mutexes, and that is exactly the problem because two threads could be locking on different mutexes (two subclasses), and then accessing your shared datastructure (since it's static) at the same time

    But what is the problem? This is exactly what I intended to do for my pattern!

    Picture the static HashMap as a global directory of subclass mutexes. Multiple threads can access different mutexes concurrently, and there's nothing wrong with that (for my pattern). However, multiple threads cannot access the same mutex concurrently because of the "synchronized(this.getClass())" block, hence multiple threads cannot concurrent check (Map.contains()) and/or add (Map.add()) the same mutex to this global directory, which once again, is the intent of my pattern.

    Perhaps I'm not understanding what you see as the problem. Or perhaps you don't understand what my pattern is trying to accomplish. Either way, please explain further, for I do not want to mislead others by posting broken codes!

    BTW, I use this pattern in our architecture on production (www.kiko.com) running on Weblogic 4.5.1 through 5.1 sp9 for over a year now, and I haven't seen any badly initialized beans yet! :-)

    Gene
  26. Gene said, "However, multiple threads cannot access the same mutex concurrently because of the "synchronized(this.getClass())" block, hence multiple threads cannot concurrent check (Map.contains())".

    It is true that multiple threads cannot access the same _mutex_ concurrently (since you are synchronizing those mutexes), but multiple threads /can/ indeed concurrently call Map.contains() because more than one thread can be in this synchronized section /because/ they locked on _different_ mutexes (i.e. different subclasses). If they had locked on the same mutex, then only one thread could be accessing the datastructure (the desired effect). Just because your looking at code inside a synchronized block, and all code that accesses a particular datastructure is in that block, _does_not_ /necessarily/ make your access of that datastructure threadsafe since what is being synchronized on (the mutex) could be different things.

    I don't think I can break it down any simpler than that without sounding condescending (which I don't want to do). I suggest showing what I have written here to another developer familiar with synchronization where you work. If that doesn't work, maybe I can get Doug Lea, Bill Pugh, or Allen Hollub to tell you that I am right. They are highly respected researchers on the topic of synchronization and the Java Memory Model. Java Memory Model: http://www.cs.umd.edu/~pugh/java/memoryModel/ The JMM doesn't directly have to do with what we're talking about, but lets just say they know a hell of a lot more about this topic than you or I :-)

    Gene said, "I do not want to mislead others by posting broken codes!"

    Good!

    Gene said, "BTW, I use this pattern in our architecture on production (www.kiko.com) running on Weblogic 4.5.1 through 5.1 sp9 for over a year now, and I haven't seen any badly initialized beans yet! :-)"

    This does not surprise me since your code only gets executed at start-up time.
  27. Hi David,

    OK, I'm beginning to see the crux of your concern, and I shall try to allay them!

    >but multiple threads /can/ indeed concurrently call Map.contains() because more than one thread can be in this synchronized section /because/ they locked on _different_ mutexes (i.e. different subclasses).

    That's the whole intent of my pattern: It's perfectly FINE if multiple threads attempt to concurrently check (Map.contains()) and/or add (Map.contains()) disparate mutexes in the Map. This is why I have multiple mutexes to begin with!

    Pseudo-Real World Example:

    Say you have 2 ejbs to deploy: A, B. The following scenarios occur when you restart your server.

    Scenario #1:
    2 clients (threads) concurrently try to access A. 1st thread will make it into the synchronization block (synchronized(A.getClass())), call all 3 init methods within the block, and releases the lock. 2nd thread enters block, sees that Map.contains() returns true, hence only calls the 3rd init method.

    Scenario #2:
    2 threads concurrently try to access A & B, respectively. BOTH threads enter the synchronization block for their respective mutexes, both threads concurrently invoke all 3 initialization for A & B respectively, and both threads release their mutexes.

    Hence you see, my pattern is threadsafe because it is designed to handle and expects concurrent access to the same datastructure (Map), but prevents critical-section concurrency for a SET of mutexes. In fact, I should start a different pattern discussion on this (or perhaps Holub or other thread guru has already discussed this): Multiple-mutexes for a single critical section.

    Gene


      
  28. I do understand that you are trying to avoid synchronization; in your case, by locking on different mutexes. Trying to avoid synchronization usually ends up in non-thread-safe code (as has been discussed in the JavaMemoryModel mailing list), unless well known techniques like copy-on-write are used.

    You state that it is perfectly fine for multiple threads to concurrently invoke Map.contains(). It is not fine since this map could be mutated by some other thread /while/ contains is being invoked.

    For your scenarios, I interpreted that A and B represent instances of two separate subclasses of your abstract EJBean.

    In your scenario #1, a synchronization problem doesn't happen coincidentally because the threads are accessing the same subclass (A).

    In your scenario #2, you didn't get into the details of the order of execution within the synchronization block between the two threads on the two instances. Lets say one thread made it all the way _into_the_implementation_ of "initializedBeanClasses.add(this.getClass())" when the threading policy decided to let the other thread do some work. This other thread is not locking on the same lock as the previous thread so it could make it all the way _into_the_implementation_ of "initializedBeanClasses.add(this.getClass())". At this point we have "multi-threaded access" to this datastructure because more than one thread is "in" (AKA is "accessing") this datastructure. The documentation of HashSet states, "Note that this implementation is not synchronized. If multiple threads access a set concurrently, and at least one of the threads modifies the set, it must be synchronized externally." One of your threads is modifying the set (actually /both/ of yours are), and that means, according to the documentation, that you "must" synchronize (it can be inferred that the this synchronization should be on the same lock as to not allow concurrent access).

    By the way, even if the other thread was accessing "initializedBeanClasses.contains(this.getClass())" (a method that does not mutate the datastructure), your code would still be in error since the other thread is in a mutating method. In this case, one could argue that the datastructure will not be corrupted and that the first thread will properly return true regardless, but that is not the point. That the docs say that it is not threadsafe if another thread is mutating while another is accessing (mutating or not) it is a sufficient requirement for requiring synchronization.

    I hope I have clarified things. If you do not understand, please do ask another senior developer in person; it takes a while for us to debate this on a message board.
  29. The underlying issue here is a logic flaw. The goal is to invoke a method once per subclass of AbstractBean. In order to accomplish this, static state for each subclass must accessible. If this is done in a repository external to the subclass, as in this example, access by all threads *must* be synchronized *on the repository monitor*, not, as in the example, on a thread-unique monitor.

    To avoid this global synchronization, the static state repository *must be contained within each sublass*. There is no alternative. The hoops required to accomplish this with registration of callbacks, or reflection upon callers in the AbstractBean, would probably cost more than the global synchronization option.

    To reiterate, the access model in this pattern is not thread-safe, since multiple threads synchronize on different monitors. If the underlying static collection is shared among multiple threads, they *must* synchronize on a common monitor. There is no magical way to get around this.

    The code used to illustrate this pattern will not throw a ConcurrentModifcationException, as an Iterator would, because HashSet.contains() assumes single-thread access. With multi-thread access, the collection has a chance of becoming corrupted under a rare set of access conditions, depending on the app server in question's management of EJBs.

    The JDK 1.3 documentation for HashSet says this best:

    Note that this implementation is not synchronized. If multiple threads access a set concurrently, and at least one of the threads modifies the set, it must be synchronized externally. This is typically accomplished by synchronizing on some object that naturally encapsulates the set. If no such object exists, the set should be "wrapped" using the Collections.synchronizedSet method. This is best done at creation time, to prevent accidental unsynchronized access to the HashSet instance:

         Set s = Collections.synchronizedSet(new HashSet(...));
     
    The iterators returned by this class's iterator method are fail-fast: if the set is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the Iterator throws a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

    Hope this helps.

    Kent Dorsey
    Seniot Systems Architect
    kentdorsey at objectfire dot com
  30. Corrections to the previous note...

    1. Substitute "sublass-unique" for "thread-unique" in the following sentence:

    If this is done in a repository external to the subclass, as in this example, access by all threads *must* be synchronized *on the repository monitor*, not, as in the example, on a subclass-unique [was: thread-unique] monitor.

    2. Substitute "Senior" for Seniot in sig :)

    Kent Dorsey
    Senior Systems Architect
    kentdorsey@objectfire.com
  31. 1. I think the ejb classloader is not multi-threaded, so two class initilazation won't happen at same time in one namespace. Which means "initializedBeanClasses.add(this.getClass())" won't get into concurrent situation.

    2. It is only add(), not one thread calling add(), another one calling remove(), so it SHOULD be no problem, even two threads call add()/contains() at same time.

    minjiang
  32. I've never seen a ClassLoader that was not designed for multi-threaded access. You could make one, but there isn't any point in doing so. That also isn't relevant to this situation because the code we've been talking about here is not in a static { ... } block, it is an instance method. I don't think you meant what you said... that is I think you meant to say that EJBs are not initialized at the same time, you think they are implemented serially. That is not so because (a) The spec does not indicate this behavior thus EJB containers could do initialization concurrently, and (b) Gene Chuang has observed concurrent initialization in practice.

    FYI, I agree with the comments from Kent Dorsey. In summary, he agrees with me and goes on to say that if you wanted to avoid the common datastrucutre and thus avoid synchronization, each subclass instance would have to store it's own static boolean initialized flag... and provide some protected accessor to it. Kent doesn't say that exactly, but that is how it would be done.
  33. Just curious, all my beans do some initilization jobs (set connection pool etc) in constuctor, and they run correctly in weblogic.
    For all java beans, not specifically EJB, the default no-args constuctor must be implemented. Since EJB is also a java bean, any classloader should run thr'u this part code, right?

    minjiang

  34. Wang, ClassLoaders provide a unique namespace for classes and when the class is loaded, static initializers (ex: static { /*code here */ } ) are run. Constructors and other methods (static or not) have nothing to do with the classloader. ClassLoaders don't "run through this part of the code", they load classes. I guess you could say "yes" if that part of the code was a static initializer... but definitely not otherwise since once the class is loaded, the ClassLoader is out of the picture. Note: instantiating an instance of the class is not considered part of class loading, that's after the fact... that is after the Class object is retreived.

    Regarding your initialization code in the constructor... I think initialization code in an EJB belongs in setEJBContext(). That is my understanding of EJBs, I have read the spec many months ago but I have no practical experience with them.
  35. Yes, David is right. The classloader does not care about the instantiate of the bean. But from the EJB1.1 spec 9.1.4, the life cycle of entity bean, before container calling setEntityContext(), it calls newInstance() first. And this is the step of normal java instantiate a object.
    Remember the default constructor in java is super(), which is fitted into any constuctor if no super(args[]) is specified. I think the basic java lauguage concept will not and should not break in EJB implementations. How can the container get around not calling the default constructor while instantiate the bean?
    But somehow I do feel EJB design is againest the normal java language, for example, the home methods, find methods, create methods, are actually static methods, but EJB spec does not allow us to put it as static. Ugly!
    Maybe even now the constructor/instantiate behavior will be broken by EJB spec, what else?

    minjiang
  36. You asked, "How can the container get around not calling the default constructor while instantiate the bean?" The answer to that is through deserializing the bean. Constructors are not called on deserialization. In your experience this hasn't happened, but from my understanding, an EJB container is allowed to do that (I don't know why one would want to though). Since the EJB spec guarantees that onSetEJBContext() will be called, that is the logical place for initialization.

    Unless there are any important new issues or someone doesn't understand what has been said, this thread is done; we're beating a dead horse.
  37. EJBean Class Initialization Hooks[ Go to top ]

    I am wondering if any one has encountered any app server problems using this pattern. In other words, will this work in any app server (for example, Web logic, Web Sphere, JBOSS).

    Thanks

    Sridhar
  38. Can I use this for initializing an EJB before any client calls the create() method? Basically what I am looking for is to have all EJB instances access a shared resource which is managed by a manager. I need to have this shared resource to be initialized before any client creates an instance. I don't want to put the initialization in the create() method because then this means for every new instance that is created, the shared resource will be initialized again. I only need to have this shared resource initialized once. This is kind of similar to the init() method of a servlet, where first access to the servlet will invoke the init() method, but subsequent accesses will not.

    I am using an EJB to create a server, and my server needs to initialize a shared resource before the EJB instance is created. Does anyone how I can go about doing this? Or should I be creating a RMI server using threads, rather than use EJB?

    Thanks.