Discussions

News: Opinion: EJB Limitations. Can you break them? Can you not?

  1. Bob Lee and Cameron Purdy have been talking about the limitations with EJB. They are talking about rules in the EJB spec, such as section 25.1.2 on "Programming Restrictions".

    These are age old questions in EJB land. Can you use statics? Can you use thread synchronization primitives? The answer lies in the letter of the law versus the meaning behind it.

    Bob discusses a faux consulting engagement:

    "Case in point, I was recently called in to investigate crippling performance problems in another application at my company. Upon investigation I discovered the application was creating separate instances of every single object for each EJB instance, even the global configuration objects. They had taken the "no read/write statics" rule a little too seriously.

    One configuration object in particular parsed an XML file from the file system, queried an LDAP server and used some heavy DOM XML parsing (creating one instance took up to 20 seconds in a simple test). Each server in a cluster of N servers created M bean instances at startup. Each stateless session bean instance created one of these configuration objects. If you add it all up, we have M * N concurrent LDAP connections and queries and M * N DOM parsings at application startup. That's M times more load on the cluster than necessary.

    The funny thing is that one developer Chris Revelador originally implemented the application using a single static instance per VM, but Krista Arquitecto, an architect of a framework used by the project in crisis, stepped in citing the aforementioned rules from the EJB specification and made the developer gut his implementation. You see, the configuration could be refreshed at runtime constituting a read/write static. When I carefully explained the spirit of the "no read/write statics" rule and described a more efficient implementation to the architect in question, even going so far as to illustrate code examples on her whiteboard, she looked at me like I had absolutely no idea what I was talking about, repeated her naive interpretation of the rule, and retorted, "I've read the EJB specification." "Congratulations," I said and headed home for the day. My help was obviously not needed."


    Read Bob Lee exclaiming: EJB is not magic.

    Cameron then came up with a challenge: "So here's my challenge for the day: Figure out how many of the EJB limitations are violated if you use a String. Yup, that's right -- how many of the rules are broken by java.lang.String?"

    Read Cameron Purdy discussing: EJB limitations

    Threaded Messages (29)

  2. Too many "MUST NOT" in the ejb spec[ Go to top ]

    I had the same kind of experience that the author had.

    Just too many "MUST NOT" in that chapter, some of them are really confusing. If you strictly follow those rules, it is hard to get some real job done.

    I think as long as you know what you are doing and how app server implement ejb and behave during the runtime, it is OK to break some of rules sometimes.

    Rick
  3. Consequences?[ Go to top ]

    I remember an old Bill Burke post on TSS where he thought the only issue with creating your own thread in JBoss was that there were thread locals for transaction and security context.

    What cases are there of people breaking the rules in a reasonable way and suffering consequences be they bugs, poor performance, or vendor grief?
  4. Consequences?[ Go to top ]

    I remember an old Bill Burke post on TSS where he thought the only issue with creating your own thread in JBoss was that there were thread locals for transaction and security context.

    >

    Unless the container vendor provides a Thread creation API or you are using AOP(and know how container propagates tx/security), there is no way to propagate tx id or security credentials to another thread that I know of.

    My guess for the reason not to use static variables? My bet it is classloader issues. Hot Deployment is supported by more than one app server in JBoss and when you hot deploy, you lose the static variable. Also, you need to consider classloader hierarchies as well. You may have the same class loaded by different classloaders, and thus you can't guarantee that a static variable is truly global.

    For global static variables, I always suggest an JMX MBean if you want to be anal. Most app servers support them now, so it shouldn't be a proprietary issue.

    My beef with EJB's is that there is no concept of a service. Multi-threaded objects that can retain state.

    I say stop bashing EJB and think of it as an iteration of middleware standards. We know what's good about it, what's bad, what needs improving, and what features can be reused for the next big thing(JTA, JCA for instance). Look for Aspect-Oriented Middleware to hit the streets. Should be the next hot middleware breakthrough, IMO.

    Bill
  5. Were they opening a connection to the LDAP server directly, or were they using JCA or a similar pool?

    Sometimes you do have to break things, if things got this bad, and I had to cache something for performance like that, I'd just use an MBean in JBoss. Not as standard.

    We rarely use statics in our server, but we do in a couple of key places. If we change those few things, we are aware that we will probably have to restart our servers.

    Steve
  6. Here is my take.

    It seems to me that the majority of the restrictions (no reflection, JNI, etc.) have to do with the Java security constraints of the server. It should be reasonable to violate those rules if you can ensure that the you can safely alter the Java security policy of the server. Some of these rules, like "don't alter the security policy", just make could sense in general.

    The "no file I/O" restriction also has do with security. You can cheat on this one by loading files from the classpath, for example via Class.getResource(). I use this trick for bundling non-EJB config files with the EJB-Jar.

    As I read things, the "no read/write static fields" and the "no synchronization" rules really only apply to the EJB class itself. The EJB class should be able to use other classes that synchronize or have read/write static fields, so long as you are careful to make them thread-safe. I use this trick for Primary Key generators.

    For what I have seen, the main issue with the "no threads" rule is that the transaction and security contexts don't propogate. Even so, I am leary about starting background threads in the EJB server, and prefer to create them outside (e.g. in a servlet) when I can.

    That is about as few as I usually go in EJB-rule-breaking. I have not had any serious problems so far.
  7. Here is my take.

    >
    > It seems to me that the majority of the restrictions (no reflection, JNI, etc.) have to do with the Java security constraints of the server. It should be reasonable to violate those rules if you can ensure that the you can safely alter the Java security policy of the server. Some of these rules, like "don't alter the security policy", just make could sense in general.
    >
    > The "no file I/O" restriction also has do with security. You can cheat on this one by loading files from the classpath, for example via Class.getResource(). I use this trick for bundling non-EJB config files with the EJB-Jar.

    I don't think the main intent of the file I/O restriction is security. In order to handle security it would suffice to only deny access to certain key locations. I think this restriction is more about providing a consistent runtime environment, making sure that the App server can distribute a bean to several machines without changing the behavior of the program.
    I don't consider using Class.getResource "cheating", I think it is a perfectly legitimate solution. The App server is responsible for distributing the ejb JAR file to all of the machines where the EJB is deployed (or load that JAR file through some central location), and the bean provider can therefore safely assume that the JAR file is present and contains the relevant information. Contrast this with direct filesystem access, where the App server cannot generally make sure that all the filesystems of the different nodes contain the necessary files.

    By the way, I don't see any reason for the EJB spec to impose any security-related restrictions. EJB code is not untrusted code (and if it was, protecting databases for instance is just as important, and is not managed by the EJB spec). I think the restrictions in the EJB spec should only insure that the App server has maximal freedom in implementation (including clustering ability) while preserving the runtime semantics of the application. But that's a topic for a different discussion.

    >
    > As I read things, the "no read/write static fields" and the "no synchronization" rules really only apply to the EJB class itself. The EJB class should be able to use other classes that synchronize or have read/write static fields, so long as you are careful to make them thread-safe. I use this trick for Primary Key generators.

    My understanding is exactly opposite: all of the runtime environment restrictions apply to all code executed by a bean (except calls that explicitly change the runtime environment, such as calls to JCA connectors). Why should these restrictions apply only to the bean class? It makes absolutely no sense. If I make my bean class a simple delegate that delegates all calls to another class, can the other class now use all those nasty disallowed features? If that were the case, why make these restrictions at all?
    The reason restrictions are made by the spec, as far as I understand, is to allow the App server a certain amount of freedom in implementing features such as clustering. For the restrictions to have any effect, they must restrict all the code that the bean can potentially run, regardless of whether or not it is a part of the bean's class. Otherwise a delegate like I described above could circuvement all the restrictions, and the whole purpose of the restriction would be defeated.
    I concede that the EJB spec does not explicitly address this point. In fact it sais "The restrictions apply to the implementation of the business methods". This is probably wrong, as it does not address certain callbacks such as setXContext calls, which I assume should also follow the restrictions. Anyway, even though the spec is not clear, I think from the context you can clearly understand that the restrictions apply not only to the bean's class itself, but to all code executed by the bean.

    >
    > For what I have seen, the main issue with the "no threads" rule is that the transaction and security contexts don't propogate. Even so, I am leary about starting background threads in the EJB server, and prefer to create them outside (e.g. in a servlet) when I can.
    >
    > That is about as few as I usually go in EJB-rule-breaking. I have not had any serious problems so far.

    Gal
  8. I have to agree with Gal. That is my understanding as well, to ensure the environment is somewhat predictable. If you have an EJB mucking around with something goofy, it could gum up the works, or start a thread that takes up most of the CPU time.

    Steve
  9. I have to agree with Gal. That is my understanding as well, to ensure the environment is somewhat predictable. If you have an EJB mucking around with something goofy, it could gum up the works, or start a thread that takes up most of the CPU time.

    Unlike this ejb method:

    public void foo() {
      int i = 0;
      while (true) {++i;}
    }

    It's an imperative language. You can't prevent this.

    Peace,

    Cameron Purdy
    Tangosol, Inc.
    Coherence: Clustered JCache for Grid Computing!
  10. The EJB spec, as it relates to restrictions, is definitely over restrictive.

    For such common operations as File I/O, the spec should have provided an approach to retreive an Input and/or Output stream to a file and stated what the restrictions are. (Of course, now this could be done safely via a connector, but there should be a standard connector for this type of operation).

    Similarly, with regard to statics, the spec should not have stated that they MUST not be used. Instead it should have used language similar to what the reference article used stating that "when using statics, you will not be guaranteed to have a single instance of an object across the application".

    Same goes for the synchronized rules.

    Even the "don't create threads" rule is overly restrictive. There are often times when you need to have a background daemon thread to perform some routine activity such as resource reaping, timers to trigger events, etc. It is wasteful to resort to jumping through hoops just to adhere to the spec for these types of things. The spec should just have said that when using your own threads, you are not allowed to rely on features provided by the ejbcontext.

    But then again, one must consider the original intent of the first EJB spec. Ironically enough, the original EJB spec was intended to allow "coding services for dummies" and really only contained SLSB and SSB. Of course, then IBM forced entity beans into the original spec and things got all mucked up. But I digress.....
  11. But then again, one must consider the original intent of the first EJB spec. Ironically enough, the original EJB spec was intended to allow "coding services for dummies" and really only contained SLSB and SSB.


    I tend to agree with this, I rather get the feeling that Sun were taken by surprise by how fast EJB and J2EE became popular and never got around to revisiting a serious set of issues with the EJB specification.

    If the restrictions are blindly adhered to, then it can get be almost impossible to produce a performant EJB based application.

    I tend to get a bit interpretive in my approach to the spec. I look at whether the techniques I am using assume a particular environment, whether I am introducing dependencies between threads that could lead to deadlocks, or more generally, whether I am doing something that could interfere with server managed objects.

    Bob Boothby.

    <Pedantic Disgression>
    Pet peeve - anyone who relies on a singleton within even one JVM hasn't puzzled out the way classloaders work and hasn't thought that someone might use a type of classloader that overthrows the standard delegation model.
    </Pedantic Digression>
  12. \Robert Boothby\
    <Pedantic Disgression>
    Pet peeve - anyone who relies on a singleton within even one JVM hasn't puzzled out the way classloaders work and hasn't thought that someone might use a type of classloader that overthrows the standard delegation model.
    </Pedantic Digression>
    \Robert Boothby\

    One could make the argument that a POJO singleton is a very fundamental aspect of application development - a crucial piece of the developer's toolkit.

    If you look at things from this perspective, it's rather surprising that there's no way to do this in a universally standard and lightweight fashion using J2EE. Developers have to work surprisingly hard to create something which is trivial in a non-J2EE universe. For the most part, if J2EE had the simple facility for saying "this object should be considered a global JVM-wide accessible facility", many app developer's problems would be neatly solved. Many people confuse this issue with irrelevancies - classloaders, clustering, independent WAR/EAR spaces, etc, and entirely miss the point. Most of the time, you want some stuff to be global to the JVM, period - just like an app server's services are "global". Clustering is an irrelevancy - the vast majority of people want a singleton per JVM, clustering should be at a higher level. Classloader objections are a joke in this context - a J2EE developer shouldn't have to worry about it, the container should take care of it for you. And WAR/EAR seperation in this context is making a simple problem far too complex - there are many, many types of application developer developed services which naturally are shared across WAR/EARs and people really want to be considered first-class services along with the built-in container stuff. JMX and MBeans may be a partial answer, but this is again a rather heavy weight solution. App developers rightly say "I just want to access a freakin' global object".

    J2EE restrictions, _in the right context_, can be useful to allow app servers to provide value-added features. But right now it's over-generalized, and too much low level crap gets in the way of your garden variety application developer. It would be really nice and really slick to, say, jettison the entity bean concept and have a SingletonBean instead. You'd get a helluva lot more bang for the buck out of the latter, and the spec for it would probably only take a dozen pages or less (as opposed to the bulk freight needed for the entity spec).

    An individual who wants to use a singleton within a J2EE environment isn't stupid or naive - it's a very natural thing to wish to do. The real problem is that the J2EE standard makes it so devilishly difficult to do such a simple thing.

         -Mike
  13. Mike,

    > An individual who wants to use a singleton within a J2EE environment isn't stupid or naive - it's a very natural thing to wish to do. The real problem is that the J2EE standard makes it so devilishly difficult to do such a simple thing.

    I agree entirely, Singleton is an incredibly useful pattern for so very many reasons as are many others that are not 'permissible' due to the restrictions of the spec.

    I see you decided to quote my pedantic digression... I tend to get a bit depressed when so many very capable people in these forums propagate the myth that a Singleton is always scoped for a JVM.

    I would be much happier if people were clear that a Singleton is only a Singleton for an hierarchy of classloaders. In an application server a hierarchy of classloaders is usually scoped to a single application and so you end up quite reasonably with a Singleton instance per application in an application server.

    Admittedly to a lot of developers this is not of relevance, but I've come across occasions when a developer was surprised that his Singleton didn't work as advertised.

    Bob B.
  14. IMHO: Having a factory method which provides developers with access to objects is fine. Having big, heavyweight objects pooled so that different transactions can re-use them can be fine (if they're read-only or stateless and threadsafe or some such equivalent). And if the pool happens, for reasons of optimal performance, to have a size of 1 that's fine too.

    The problems occur when people who use them start thinking of them as Singletons. The switch is in mindset, not in code: it's just a factory method returning you an object, the rest is an implementation detail which you should not rely on.

    So I wince when things are called StartupConfigSingleton instead of StartupConfig, or when the public javadoc of says that its a singleton: that's not a public detail.


    Sean
  15. Ironically enough, the original EJB spec was intended to allow "coding services for dummies"....


    It shows.

    In general the EJB spec appears to be built by people who are saying "what can our app servers do for the developer", not "how can we enable developers do to things for themselves". I see two causes: vendors who want app servers to be bigger and more complex and do more, because that's how they make money, and a disdain for the abilities of the 'bean providers' on the part of some engineers who build commercial app servers.

    What I find very interesting and instructive is that this approach of trying to prevent developers from doing anything "complex", and encapsulating everything away from them, has resulted in a highly complex environment to develop in.

    A moral from my friend Tim Sturge: a RDBMS uses B-Trees and Hashed indexes, and the developers don't see these details and can't change this stuff. But that's fine because they don't need to know. But as soon as you need to know something like that, as soon as the implementation pokes out even a teeny little bit, suddenly developers would find themselves in situations where they wanted to query about those details, and change those details.

    Hence the failure of the EJB Spec in this: Developers MUST know about threads, and multi-threading, and sharing resources between threads - it is not possible for them to do otherwise. Given that, the EJB spec has been foolish in trying to prevent developers playing with threads, static variables, etc.


    Sean
  16. The EJB specification defines a contract between a component you develop and a managed environment. I don't think it makes that much sense to try guessing how the managed environment will do its work if you are not respecting the original contract. Actually, the only way to know if it harms to break an EJB rule is to have an intimate knowledge of how the container is implemented. In that aspect, what may be true for one container may not be for another one.
  17. I have answered variations of this question a number of times, and the key confusion seems to be that these limitations are from a containers point of view and not the bean providers point of view. In other words, the spec says that it is allowed to constrain how beans do IO etc. This means that a bean that wants to be as portable as possible should consider that it can be deployed in containers which do not, for example, have file systems. (Silly, I know, but this is just an example of what the EJB spec would allow for).

    In other words, if the bean provider wants to target a container that allows IO to happen (=all current containers AFAIK) then these "rules" can be violated and you'd still be compliant with the spec. What the spec rules means, really, is that the container may not make restrictions BEYOND those enumerated, i.e. if something is not restricted in the spec then a bean can perform that and KNOW that it will always work.

    The conclusion of all of this is that bean providers can effectively do whatever they want as long as they target containers that do not use security policies to disallow those actions.

    This is from the perspective of *what bean providers can do as it relates to the EJB spec*. Other than that, it is still the case that programmers are responsible for their code, e.g. if you make bad code that does IO it is still bad code even if it is allowed by the EJB container.

    /Rickard
  18. Static what?[ Go to top ]

    Using a static member variable in an EJB would probably be a bad idea. I think a better solution would to have a transient variable that references another resource to avoid your bean initialization issues. The variable could be initialized when the EJB is constructed or activated. I've run into the same issue when working with pooled taglibs.
  19. I have answered variations of this question a number of times, and the key

    > confusion seems to be that these limitations are from a containers point of view
    > and not the bean providers point of view.

    Ted Neward has responded here:
    http://www.neward.net/ted/weblog/index.jsp?date=20031223#1072249819640

    But it seems to tally with your observations on criticizing something without fully understanding it.

    --Dilip
  20. The EJB spec, like all technical specs, is an attempt by humans to document a contract between different groups of people or points of view, setting up some rules intended to ensure that things don't go off the rails. Very few specs achieve nirvana in this regard; all seem to have areas that, while well-meaning, end up with unintended side-effects.

    Bob's article seems to capture this tension fairly well. Yes, if you want to play it completely safe (and avoid thinking about what's really happening), don't use read/write statics in your EJBs. Follow that rule, and you won't have a problem (at least in that area...as the article clearly points out this may cause problems in other areas). But good developers/architects should always consider the _intent_ of what the specs are saying rather than just blindly follow the letter of the spec. Yes, don't write your app so it absolutely depends on statics to enforce the singleton pattern, for example...since as the spec says, you might not always be running within a single JVM. But if you write you app such that use of statics is an _optimization_, where things still work fine if you do end up with more than one "singleton", e.g. if your beans end up getting reused in a pool, or spread across JVMs, then go for it.

    Interestingly, in "real life" these are the things that happen in contracts between people, which judges and juries get to sort out. No contract is perfect, be it a human-to-human one or a code-to-code one. The best way to make it better is to revise, improve and clarify the contract.

    Randy Schnier
  21. I posted the following remark on my weblog:

    While it is certainly healthy to understand the rationale behind these kinds of decisions, Bob omits a very critical piece of information when he advises that these rules can be bent when you know what you are doing: these restrictions are also used by the container.

    For example, the fact that EJB's are not allowed to create threads makes it possible for the container to attach important information to ThreadLocal (such as clustering, transaction, security, etc...). After reading Bob's article, you might decide that since your application will only ever run in a single JVM, you can safely violate the rule and create threads in your EJB. But by doing that, you are going to break the container in disastrous ways.

    Bob gives the example of an over-zealous architect who decided to follow the rule literally but by doing so, introduced a big performance problem in the application. This is indeed unfortunate but there are better and more standard way to address this problem than by using a static (the two most obvious ways are to keep this information in the servlet session, or maybe a Stateful Session bean, if your application doesn't have a Web tier).

    That being said, Bob's entry is a must-read for anybody who has ever wondered where these odd limitations in the EJB specification came from.

    --
    Cedric
  22. I posted the following remark on my weblog:

    >
    > While it is certainly healthy to understand the rationale behind these kinds of decisions, Bob omits a very critical piece of information when he advises that these rules can be bent when you know what you are doing: these restrictions are also used by the container.
    >
    > For example, the fact that EJB's are not allowed to create threads makes it possible for the container to attach important information to ThreadLocal (such as clustering, transaction, security, etc...). After reading Bob's article, you might decide that since your application will only ever run in a single JVM, you can safely violate the rule and create threads in your EJB. But by doing that, you are going to break the container in disastrous ways.
    >
    > Bob gives the example of an over-zealous architect who decided to follow the rule literally but by doing so, introduced a big performance problem in the application. This is indeed unfortunate but there are better and more standard way to address this problem than by using a static (the two most obvious ways are to keep this information in the servlet session, or maybe a Stateful Session bean, if your application doesn't have a Web tier).

    I agree with most of your message, but here I think you are wrong. There is nothing wrong with using static fields in EJB to manage configuration data, as long as you don't *rely* on the information being shared between beans (or between multiple method invocations on the same bean). No sane application server designer would ever design his server in a way that would stop such static fields from working properly. There is a simple reason: such static fields are used in hundreds of places in the JDK and many libraries. Whenever you do String encoding/decoding you access a read/write static field (see java.lang.StringCoding, it is package-protected). Can any reasonable server afford to blow up whenever you use this field?

    I don't think you have made any reasonable suggestion to replace the use of a static field. Configuration objects can be very heavy-weight, including parsed DOM trees and other large objects. Moving it from the web tier to the EJB tier on every call is grossly inefficient. Placing it in a session bean means you have to load several instances of this large object for no reason, and also that you force single-threaded access to it. Your code is probably using dosens on static field anyway. I have never heard a single good argument against lazy-loaded read-only static fields in EJB.

    >
    > That being said, Bob's entry is a must-read for anybody who has ever wondered where these odd limitations in the EJB specification came from.
    >
    > --
    > Cedric

    Gal
  23. I posted the following remark on my weblog:

    > >
    > > While it is certainly healthy to understand the rationale behind these kinds of decisions, Bob omits a very critical piece of information when he advises that these rules can be bent when you know what you are doing: these restrictions are also used by the container.
    > >
    > > For example, the fact that EJB's are not allowed to create threads makes it possible for the container to attach important information to ThreadLocal (such as clustering, transaction, security, etc...). After reading Bob's article, you might decide that since yoGal:

    I don't think you have made any reasonable suggestion to replace the use of a static field. Configuration objects can be very heavy-weight, including parsed DOM trees and other large objects. Moving it from the web tier to the EJB tier on every call is grossly inefficient. Placing it in a session bean means you have to load several instances of this large object for no reason, and also that you force single-threaded access to it. Your code is probably using dosens on static field anyway. I have never heard a single good argument against lazy-loaded read-only static fields in EJB.

    Fair enough.

    You point out flaws in alternate approaches to this problem, but I'll point out that storing this information in a static field has very subtle limitations that even people who understand Bob's article (and more generally, why the EJB specification makes these limitations) might still be surprised at.

    As you say, it's safe to store information in static fields as long as you don't expect to find it there on your next invocation. Basically, this means that whatever information you are storing there must be a singleton, i.e., a value that once assigned, is not going to have a different value if computed a second time.

    The problem with the static field approach is that there are only two states: null and non-null. Bob's scenario will only work if the non-null state is always valid. It won't work if the value can become stale over time (and more generally, lazy-loading won't work in that scenario anyway).

    --
    Cedric
    ur application will only ever run in a single JVM, you can safely violate the rule and create threads in your EJB. But by doing that, you are going to break the container in disastrous ways.
    > >
    > > Bob gives the example of an over-zealous architect who decided to follow the rule literally but by doing so, introduced a big performance problem in the application. This is indeed unfortunate but there are better and more standard way to address this problem than by using a static (the two most obvious ways are to keep this information in the servlet session, or maybe a Stateful Session bean, if your application doesn't have a Web tier).
    >
    > I agree with most of your message, but here I think you are wrong. There is nothing wrong with using static fields in EJB to manage configuration data, as long as you don't *rely* on the information being shared between beans (or between multiple method invocations on the same bean). No sane application server designer would ever design his server in a way that would stop such static fields from working properly. There is a simple reason: such static fields are used in hundreds of places in the JDK and many libraries. Whenever you do String encoding/decoding you access a read/write static field (see java.lang.StringCoding, it is package-protected). Can any reasonable server afford to blow up whenever you use this field?
    >
    > I don't think you have made any reasonable suggestion to replace the use of a static field. Configuration objects can be very heavy-weight, including parsed DOM trees and other large objects. Moving it from the web tier to the EJB tier on every call is grossly inefficient. Placing it in a session bean means you have to load several instances of this large object for no reason, and also that you force single-threaded access to it. Your code is probably using dosens on static field anyway. I have never heard a single good argument against lazy-loaded read-only static fields in EJB.
    >
    > >
    > > That being said, Bob's entry is a must-read for anybody who has ever wondered where these odd limitations in the EJB specification came from.
    > >
    > > --
    > > Cedric
    >
    > Gal
  24. Oops[ Go to top ]

    Sorry for the extra quoting in my reply above.

    --
    Cedric
  25. singletons[ Go to top ]

    Cedric: The problem with the static field approach is that there are only two states: null and non-null. Bob's scenario will only work if the non-null state is always valid. It won't work if the value can become stale over time

    The problem with the singleton concept in this context is that the data -- including the reference to the singleton itself -- lives in a more chaotic world that has classloader and potential clustering issues. So if you separate out the data so that it becomes the uniform shared resource across the application (even if clustered) then you can implement access to it via stateless session beans, such that the SSBs become facets of a singleton.

    Peace,

    Cameron Purdy
    Tangosol, Inc.
    Coherence: Clustered JCache for Grid Computing!
  26. [deleted the older quotations]

    > I don't think you have made any reasonable suggestion to replace the use of a static field. Configuration objects can be very heavy-weight, including parsed DOM trees and other large objects. Moving it from the web tier to the EJB tier on every call is grossly inefficient. Placing it in a session bean means you have to load several instances of this large object for no reason, and also that you force single-threaded access to it. Your code is probably using dosens on static field anyway. I have never heard a single good argument against lazy-loaded read-only static fields in EJB.


    Fair enough.
     
    You point out flaws in alternate approaches to this problem, but I'll point out that storing this information in a static field has very subtle limitations that even people who understand Bob's article (and more generally, why the EJB specification makes these limitations) might still be surprised at.


    I don't think the limitations are so subtle. Making the distinction between beans running on different nodes and beans running in the same VM makes this more confusing than it really is. The EJB spec does not make this distinction, and it has little theoretical value since the EJB spec never guarantees that two invocations on the same bean will go to the same VM. The bean can allways be passivated and activated on a different VM. So even if you are not aware of classloading issues, it should be clear that you can never assume two method invocations will access the same value for a static field.


    As you say, it's safe to store information in static fields as long as you don't expect to find it there on your next invocation. Basically, this means that whatever information you are storing there must be a singleton, i.e., a value that once assigned, is not going to have a different value if computed a second time.


    No, not exactly. For instance, if you want to allocate unique global IDs, you can take the following approach: each ID consists of two integers. The first integer is loaded from some global storage, like the database. The secondary ID is simply a static counter. The allocator object might look something like this:

    class Allocator {
      static Allocator instance;

      int globalCounter, localCounter;
      
      Allocator() {
        // load new unique globalCounter from DB
        localCounter = 0;
      }
      
      synchronized long nextID() {
        return globalCounter | ((long)localCounter++)<  }

      synchronized Allocator getInstance() {
        return instance == null ? instance = new Allocator() : instance;
      }
    }

    As long as each time the Allocator class is loaded it gets a new globalCounter, I don't see a problem with it's local state. Can you point out a problem with this class?


    The problem with the static field approach is that there are only two states: null and non-null. Bob's scenario will only work if the non-null state is always valid. It won't work if the value can become stale over time (and more generally, lazy-loading won't work in that scenario anyway).


    I guess we have different ideas of what lazy-loading means in this context. Lazy-loading a global configuration object means loading it once it is first used, and then reusing it on subsequent calls. This does work. It is possible that the value won't allways be reused, if the bean class is reloaded or the bean is moved to a different VM. When you design an application you should prepare for the worst, but expect the average. Yes, this optimization won't do anything if each call is executed in, say, a different VM. But it won't hurt you either. In the average case, where a lot of calls do share a single static field, this optimization will be highly effective.

    Also, I think my example above shows that this doesn't only work in "two-state" situations. I can give you other examples: for instance a singleton that fills up useful caches as it runs, so it's state changes (I don't mean caches that become stale, I mean computational caches). This too works perfectly in EJB (even though reloading of classes will make the caches flush). Or a Random object that changes it state on every invocation, but can also be reloaded using a random seed whenever the class is reloaded (or on different VMs).
    To summarize, I think you are being too restrictive in your description of the limitations on static fields in EJB. Static fields have many useful and perfectly EJB-compliant uses. You have to know what you're doing, but I don't think it's quite as complicated as some people make it out to be.

    Gal
  27. Thread local is always shared amongst applications.
    It's never owned by just one app, so that's not a
    reason to limit threading.
  28. new threads issues[ Go to top ]

    Thread local is always shared amongst applications.
    It's never owned by just one app, so that's not a
    reason to limit threading.


    Some app servers store context information in thread local. If you spin up a new thread, it has no context, and thus cannot use J2EE APIs implemented by that server.

    Other app servers extend the Thread class to make their own thread implementation that carries (among other things) context. Their J2EE implementation will cast the current thread to that implementation sub-class and thus if you spin up your own threads, they will get class cast exceptions when using the J2EE APIs implemented by the container.

    Included in the above two limitations are the app servers that account for most of the marketshare.

    Peace,

    Cameron Purdy
    Tangosol, Inc.
    Coherence: Clustered JCache for Grid Computing!
  29. new threads issues[ Go to top ]

    Some app servers store context information in thread local. If you spin up a new >thread, it has no context, and thus cannot use J2EE APIs implemented by that >server.


    Yes, that's true of any app. That seems like a capability,
    not a reason not to do something.
  30. My understanding of the reason to not use static data is not that it won't really behave as a singleton in a multi-VM environment.

    If you have read/write static data accessed by multiple threads (i.e. from different transactions) you need to synchronize access to it. Then the container no longer controls all locking and you can have deadlocks outside the container. The container cannot control things like deadlock detection, read-only semantics, etc. in that case.