[Announcements] Some changes in the heart of

Developer
jfirechief
2010-10-03
2013-04-25
  • jfirechief
    jfirechief
    2010-10-03

    DO NOT ANSWER TO THIS POST. ANSWER TO THE ORIGINAL POST INSTEAD.
    Original post: https://www.jfire.org/modules/newbb/viewtopic.php?forum_id=2&topic_id=501#forumpost1779
    by: Marc Klinger (Marc)
    on: Sat Oct 02 21:42:47 CEST 2010

    Hi,

    for various reasons, I had to change the way that several core components in JFire are accessed and work together. These components are:

    1. Cache
    2. JDOLifecycleManager
    3. JDOObjectID2PCClassMap (suggested to be included in my changes by Marco)
    4. SecurityReflector
    5. JFireEJB3Factory

    Those components used the shared-instance pattern to provide VM-wide global instances of themselves. (2) and (4) required a system property with a class extending them to be set. (4) also allowed JNDI lookup if no system property was set. (5) is a pure static utility class.

    What I have done is to split those components into parts. For most of these components, there is now an interface, an abstract implementation and a Global*Provider class which still uses the shared-instance pattern. My intention was to be able to use these components in a non-global way but still provide backwards-compatibility for all the code out there that is just working. I marked most of the old classes and methods deprecated which resulted in having 275 compiler warnings more only in JFire-Min. Sorry about that - but this code should still be working fine.

    Especially all DAOs now use the Global*Providers by default if no other provider instances have been set. This means, that using the code without taking care about the providers just works and the DAOs can also be used in other environments where multiple caches, security reflectors and whatever may exist in parallel.

    What you should change in the future (when developing new classes or stumble upon deprecated-warnings):

    1. Cache: Cache.sharedInstance() is deprecated. In a DAO, just use the method getCache() defined in BaseJDOObjectDAO. To use the VM-wide singleton cache, use GlobalJDOManagerProvider.sharedInstance().getCache(). If you are using that, always think about the fact, that your component will only work in an environment that relies on the global shared-instance pattern. To make your component reusable in other environments consider injecting a provider instance by constructor argument or setter.

    2. JDOLifecycleManager: Same here. JDOLifecycleManager.sharedInstance() is deprecated. In a DAO, just use getJDOManagerProvider().getLifecycleManager(). To use the VM-wide singleton lifecycle manager, use GlobalJDOManagerProvider.sharedInstance().getLifecycleManager(). The same re-usability issue applies here.

    3. JDOObjectID2PCClassMap. Just the same - sharedInstance() deprecated - accessible via JDOManagerProvider instances.

    4. SecurityReflector. The same pattern. The whole SecurityReflector class is now deprecated. There is now the ISecurityReflector interface and the GlobalSecurityReflectorProvider which uses the same lookup strategies that where formerly implemented in SecurityReflector. Existing SecurityReflectors now extend AbstractSecurityReflector.

    5. JFireEJB3Factory is NOT deprecated as its design is puristic and clean and there are no dependencies to other components. However, it is pure static and thus not exchangeable. There is now the JFireEJB3Provider interface with an AbstractJFireEjb3Provider and a GlobalJFireEJB3Provider class that uses the shared-instance pattern. DAOs can use getEjbProvider().getRemoteBean(MyRemoteInterface.class). There is no need anymore to pass initial context properties to this method as the implementation has access to a SecurityReflectorProvider instance (and uses the Global*Provider by default) - we've come full circle.

    I tried not to touch existing implementations except the DAOs as I want to re-use them, now. There are still some DAOs (3-4) accessing SecurityReflector.sharedInstance(). I hope I can introduce another mechanism for their needs soon. All other existing classes still use the deprecated methods/classes. All new classes use the Global*Providers by default. The deprecated methods and the Global*Providers should by default always return the same instances.

    Everything should work fine (in a perfect world)… :-)

     
  • jfirechief
    jfirechief
    2010-10-15

    DO NOT ANSWER TO THIS POST. ANSWER TO THE ORIGINAL POST INSTEAD.
    Original post: https://www.jfire.org/modules/newbb/viewtopic.php?forum_id=2&topic_id=501#forumpost1787
    by: Marc Klinger (Marc)
    on: Fri Oct 15 19:12:56 CEST 2010

    I used the same pattern for NumberFormatter and DateFormatter. While doing so, I changed the default behaviour from NumberFormatter when formatting currencies. It now uses the Java currency symbol which is locale dependent.

     
  • jfirechief
    jfirechief
    2010-10-16

    DO NOT ANSWER TO THIS POST. ANSWER TO THE ORIGINAL POST INSTEAD.
    Original post: https://www.jfire.org/modules/newbb/viewtopic.php?forum_id=2&topic_id=501#forumpost1788
    by: Marco (marco)
    on: Sat Oct 16 13:05:18 CEST 2010

    Hello Marc,

    thanks a lot for your notification. I like the ability to inject the mentioned services a lot, but I see problems with the usage of components now. As you say, components either must take the services in a constructor or need to use injection.

    Injection is not available in every environment. This means, every component that we migrate to the new mechanism either does not work in a non-injection-environment anymore or pollutes the API by forcing to drag the services through various levels (pass them as method arguments).

    The previous implementation worked in simple JavaSE. I would love to get a new mechanism that works fine in JavaSE and with injection (Spring or JavaEE). Is it possible to find a way to support this (without dragging all the services as method arguments through all the layers)?

    Or do we now require the clients to use injection in order to use all components? Isn't that a harsh requirement?

    Concerning the currencies, we just talked by phone and I only want to clarify for others reading this thread: You told me that it is still possible to declare custom currencies (e.g. game money not known to the ISO) in JFire. Only those currencies that are standardized are taken from Java (overriding whatever is configured in JFire).

    Best regards, Marco :-)

     
  • jfirechief
    jfirechief
    2010-10-18

    DO NOT ANSWER TO THIS POST. ANSWER TO THE ORIGINAL POST INSTEAD.
    Original post: https://www.jfire.org/modules/newbb/viewtopic.php?forum_id=2&topic_id=501#forumpost1791
    by: Marc Klinger (Marc)
    on: Mon Oct 18 11:51:48 CEST 2010

    Hi Marco,

    > As you say, components either must take the services in a constructor or need to use injection.

    I did not say/write that. The point is: the developer should take care from where to get the components. All components I have changed now use a fall-back strategy to get the components they need from a global context. This global context currently uses exactly the code that was used before. But that may as well be another context implementation in the future.

    It is not true that the previous implementation worked on plain JavaSE. In fact, it works on the JFire framework which is quite heavy. Using the injection pattern will now *allow* you to use it in JavaSE and simply call the setters you need (in absence of a injection framework that does it for you).

    It further allows you to use a framework of your choice for injection if you don't want to do it manually. Think about
    - Spring
    - Eclipse Extensions
    - OSGi Services
    - Hand-written annotation scanners
    - JEE
    - whatever…
    or a combination of those.

    It is however true that we need a plan about how to get this pattern working overall in JFire. But this should be solved in some kind of context and not in the component implementations.