Announcement Announcement Module
Collapse
No announcement yet.
why is context hierarchy a tree and not a graph? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • why is context hierarchy a tree and not a graph?

    hi,

    i'm wondering why it is only possible to define a single
    ApplicationContext as the parent of another one.

    as far as i understand it, the main benefit with multiple
    contexts is the possibility to modularize bean definitions.
    sub-contexts can refer to (and even modify/override)
    beans in parent contexts. that's really nice.

    what i'm missing is support to inherit and use beans
    from several parent contexts.

    as an anology you could take the reference to classes
    in jars. no one would expect that a maximum of 1
    jar-reference per application module would be sufficient.

    another example is OO inheritance itself, inheriting from
    a single class was not enough, so (in java) interfaces
    were invented to allow a form of multiple inheritance.

    in my opinion the first analogy gives a better picture
    of my concern, because it focuses on a deployment issue.
    maybe my hazzle with the tree-like hierarchy of contexts
    becomes clearer in a pluggable deployment environment.
    in my case it is Eclipse with its plugins and extension points.
    the pure appearance of a plugin in a special folder leads
    to the start of a sub-ApplicationContext.

    there frequently is the need to use several beans from
    different contexts as collaborators in a "plugged" context.
    at the moment i see only two possibilities to refer to such
    beans:

    1. via String-typed properties that are later resolved to
    private bean handles by application code.

    2. by letting lower contexts "inject" bean definition files
    into an upper context. this way dependent code could
    introduce a registry which dependent beans must
    register with. beside the fact that this procedure is clumsy
    in handling, it introduces severe problems with class
    loading in managed environments (although it would
    be possible to assemble the needed ClassLoaders
    dynamically).

    wouldn't it instead be a neat feature if i was allowed to
    simply specify more than one parent context?!

    i'd be pleased to open a JIRA if this feature is accepted
    commonly. i'm aware that this is no simple patch ;-)

    cheers
    /eike

  • #2
    Multiple inheritance

    Erik

    I need to think of this a bit more but I think there are a few issues here.

    To pursue the OO analogy, what you're talking about sounds a bit like C++ style multiple inheritance, which was intentionally left out of Java.

    For example, what would happen if a context C had 2 parents, A and B, and both A and B defined bean "foo"? What if C used the "parent=bar" definition style, and there were two inherited "bar" definitions?

    Note that it is presently possible for a context at any level to be made out of multiple physical files, parsed by BeanDefinitionReaders.

    Rgds
    Rod

    Comment


    • #3
      Your issues

      Rod and Erik,

      i've also thought about your first issue. you're right with your analogy to C++ and in that area there are solutions. however i think that it would be better to follow the way autoWireByType goes: simply indicate an error.

      the second issue was already addressed in my request (numered 2). to achieve at least a similar behaviour, the plugin code that starts a sub-context would have to tell another plugin (that starts a higher-level context) to include an additional file into its context config. this file could contain a registry bean that lower beans use to register with. here i see several problems:

      1. who takes care to 'inject' the registry into the upper context? there might be even more than 2 clients of that registry! in the end the 'duplicate parent' problem, you mentioned, could arise, too.

      2. the "prerequisit problem". since all config-fragments have to be present at context load-time the processing order of the contexts to be created changes and becomes more complex. basically a sort of 'forward reference' is introduced that splits the assembly of the context hierarchy into two steps (first propagating all the fragments, then loading the contexts).

      3. typically the code of the beans contained in the propagated config-fragments require to be loaded by a different classloader than the beans in the upper context, where they are 'injected'. this issue could be solved be hacking the thread's classloader, but this is clumsy, error-prone and even adds runtime penalty during findClass().

      cheers
      /eike

      Comment


      • #4
        One more Point

        i've forgotten to mention another important reason against the config-fragment solution:

        4. it would break encapsulation of the parent context, as it assumes that ithe parent context is made of files at all.

        cheers
        /eike

        Comment


        • #5
          Perhaps hierarchy solves many things now but later? Look at the Java classloader headaches. I'm reminded of a project called ClassWorlds that may have some tangential relevance:

          "...does away with the hierarchy normally associated with ClassLoaders. Instead, there is a pool of ClassRealms which can import arbitrary packages from other ClassRealms. Effectively, classworlds turns the old-style hierarchy into a directed graph. " See http://classworlds.codehaus.org/ See also: http://maven.apache.org/reference/plugins/uberjar/

          It seems that the above allows a form of 'import' of jars and classes based on a configuration file.

          So, can't Spring do something similar and have an import from any context? To avoid some multiple-inheritance problems, use namespaces based on the context imported? Or contexts should belong to some kind of namespace? Just guessing here [still learning Spring ]

          J. Betancourt

          Comment


          • #6
            Maybe I am not qualified to say anything about this, since I have never run into a situation, I have to stress the application-context mechanism of Spring to such extend.

            But using my knowledge gained by other closely related situations, here is what I think:

            First of all - hopefully I am not out of date - I think it would be nice to specify some kind of visibility within the bean id. You know specifying beans only to be visible within the current context (private) or globally(public). This will help to keep things clean.

            In the Eclipse world, required plugins are sepcified rather then imported (semantically it's a huge diffrence). So you will get something similar to the import statement but more like a reference then an actual extension. So every context will need an optional name to be identifiable within any kind of collection of contexts.

            If the actual context doesn't provide a bean (definition), Spring may simply look up the required contexts to identify and retrieve the required bean. How the collection of contexts is created/implemented (composition context, registry (global/local) or even simple add/remove files) should be uninteresting by now, since a generic type/interface should exist to decouple this, anyway.

            One Problem may be the cycles in the dependency graph of the contexts. This can be simply avoided using a normal stratification algorithm. So nothing to battle with also.

            Also the name of each context may serve as a name-space / context-domain. So two diffrent contexts may define diffrent beans with the same id.

            So instead of referring to inheritance, I would like to talk about reference and dependency. A visibility control-management on bean and context level would also be a good enhancement.

            I am also a bit unsure wether a bean definition may manipulate other bean definitions. You know, currently I think about the context more as a collection of beans (singletons) and bean factories. So if another context depends on any of the foreign beans, it will never change the configuration of the foreign beans, right? So I think there is no problem on that since it's not inheritance anymore - nothing gets overridden, the zoo of available beans is just increasing.

            But maybe I am wrong on that. Don't know, but hoping the best! :-)

            Comment


            • #7
              Martin,

              you have mentioned some interesting points.

              context name: i like the idea to define a context name in the config file. in fact i always use a derived context class that provides a name for contexts to be set programmatically in the ctor. i use it to give a namespace to the beans.

              context creation: since i've come from avalon/merlin, i kow how unflexible it can be, if the an actual context is created by some layer belonging to the context. this way the context would be forced to bother handle classloading issues. i strongly recommend to leave it to the apllication to provide the loading logic. on a second thought though, it might be nice (if only for documentation purpose) to specify the name of parent context(S) in the bean config. a callback interface could be used to ask the app to load respective contexts and provide context handles.

              visibility control-management: nice to have thing! even useful for the (current) single-parent way.

              cheers
              /eike

              p.s. forgive me, what you say about eclipse is neither correct nor complete, in my opinion:

              you're right, in eclipse you rather "require a plugin" than "import a package". but this is only technically different. semantically they're the same - both ways reference functionality from a foreign unit and "pull" into the current unit.

              in eclipse there's an additional, quite powerful way to make functionality available in the opposite direction: the extension point mechanism. this way a plugin may "inject" its functionality into a referenced (required) plugin (which declares the extension point). in fact this is the situation where classloading issues arise most commonly. this scenario was a major point that made me post this request ;-))

              Comment


              • #8
                Interesting post,

                I am currently working on a project of quite huge legacy modular ERP system where we are using the Spring. As we are only in early phase of analysis and implementation, we use simple flat AppCtx, but I expect we will use hierarchical contexts in future.
                Because of the nature of the developed system (loosly coupled modules) I think, the simple tree will not suffice.

                Eike, at first I didn't understand what should it be good for, but after Martins post I think this is very good idea and can solve many problems in similar (lossly coupled modular) systems.

                I hope this will go into the Spring release ASAP :-)

                Regards,
                CS

                Comment


                • #9
                  p.s. forgive me, what you say about eclipse is neither correct nor complete, in my opinion:

                  you're right, in eclipse you rather "require a plugin" than "import a package". but this is only technically different. semantically they're the same - both ways reference functionality from a foreign unit and "pull" into the current unit.
                  In my point of view, it is a fundamental diffrence. There is only one concrete instance in the plugin-world for a given plugin. You know, normaly only one instance of the Plugin class exists within a Eclipse workspace. Also by referring it, the plugin simply has to exist or be known. But by importing something it becomes yours.

                  It's like, I require plants and I import plants in a context of your living room. If you require plants, the plant may be everywhere, even outside the room. But by importing plants it has to belong to you and has to be inside your room. - I didn't came up with a better example, so I am sorry. I just hate car examples

                  Import a library and it becomes a part of your project. Require a plugin and it is just there but it doesn't belong to you, you just can relay on it. That's the huge diffrence, I was talking about. But maybe we are not sharing the same point of view. Anyways, you dont have to say sorry, if you disagree with me or have to correct me, I think. :-)

                  in eclipse there's an additional, quite powerful way to make functionality available in the opposite direction: the extension point mechanism. this way a plugin may "inject" its functionality into a referenced (required) plugin (which declares the extension point). in fact this is the situation where classloading issues arise most commonly. this scenario was a major point that made me post this request )
                  That's why I think the way the context collection is created, handled and referred to, should be abstract (types), so special implementation taking diffrent enviroments into account should be possible. For example it may be possibile to add a context to such a collection of contexts by cloning it rather then using the providing context.

                  But never the less, I would prefer a required context solution rather then polymorphism. I guess a collection of beans /bean-definition shouldn't be seen as a compositum of beans. Maybe an aggregation, but you can not extend an aggregation type by simply adding some more bean-definitions. That feels wrong in some ways, semantically speaking.

                  Comment


                  • #10
                    Hi all,

                    I too was thinking of namespaces as I was reading through this thread. I've been up to my ears in jsp and xml lately, and this situation has already been resolved in that realm with namespaces.

                    Perhaps a default namespace would help the transition in that you would not have to go through your code and add
                    Code:
                    [i]MyOldNamespace:[/i]MyBean
                    everywhere and just add
                    Code:
                    MyNewNamespace:SomeoneElsesPrePackagedBean
                    as needed. It's a tradeoff though. Many things added out of convenience can lead to sloppy code in the long run.

                    As Spring becomes more popular, and open source modules start popping up on sourceforge.net, being able to incorporate multiples of them them will be much easier if there is a way to resolve these conflicts. As easily as JSP tagLibs (well, almost).

                    Anyhow, Rod, u da man. I'm enjoying your book and hope to finish it soon (as my wife and kids allow).

                    Comment


                    • #11
                      I was thinking more about this last night on the ride home and thought it would be silly to use namespaces within classes when requesting beans... What's IoC for if not to avoid tying you to things like that.

                      Rod mentioned in his post and in his book, "J2EE Development without EJB" on page 177 that:

                      Originally posted by Rod Johnson and Juergen Hoeller in 'J2EE Development without EJB'
                      You can also specify multiple file locations to be merged into a single application context instance. Each file must conform to the DTD; they can refer to each other's beans with normal bean references. This is useful for splitting up large middle tier application contexts, for example by module or into business context and a data access context.
                      While there is an example given of a context instance being loaded from a single xml file, I would have loved to have seen an example of more than one file being used to load a context.

                      ClassPathXmlApplicationContext's constructor with a single String was used. However, there are several constructors, and some allow you to supply a String[] of resource xmls.
                      :arrow: ClassPathXmlApplicationContext

                      Comment


                      • #12
                        While there is an example given of a context instance being loaded from a single xml file, I would have loved to have seen an example of more than one file being used to load a context.
                        Just take a look at the jpetstore sample, it builds a context from two xml fragments, specified in the web.xml file.

                        One related note, you can very nicely use aliases (having both an id as well as one or more extra names) on beans, to tie together components, yet keep them unaware of each other.

                        Colin

                        Comment


                        • #13
                          I've been on holiday, so I've missed this very important topic. I too am srpingizing a system that uses a plugin module similar to eclipse (except we define extension points and extensions directly in the spring config files!). However, the limitation of a tree for context is a dead-end.

                          Heres what I'm doing to get around the tree limitation:

                          - All beans have a unique prefix (equivilent to the eclipse plugin-id)
                          - A bootstrap layer determines the full set of plugins installed for the app, and loads all plugin context files into a single appContext.
                          - There is no support limiting visibility between plugins. That is, a plugin does not have speciify which other plugins it depends on. (I don't like this, but its the only I way I can make this work. In practice, however, I can live with it).

                          Of course, I would much rather have some explicit support for a plugin framework within spring.

                          Comment


                          • #14
                            memelet,

                            in fact what you are doing sounds very similar to my solution to the plugin challenge. as the unique prefix you mention i use the path down in the (named) context hierarchy. this way i get a "full qualified" bean name which is also used as the logging category and the logging hierarchy does not differ from the runtime hierarchy of objects (beans).

                            if you are interested in my experiences with eclipse as a plugin environment, you could have a look at my Net4j project. it is open source and uses eclipse at client- and server-side to build upon a sophisticated plugin technology. at server-side i use a socalled "headless" eclipse environment (1mb disk space and 1 sec startup time).

                            the code is full functional and half tested. unfortunately the documentation is already outdated with respect to the chosen environment, because my first try was with merlin/avalon plus eclipse. for other reasons i'm forced to update the docs soon (and submit a first proper release). if you'd like to have a first look, try http://net4j.berlios.de

                            cheers
                            /eike

                            Comment

                            Working...
                            X