cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Upayavira ...@odoko.co.uk>
Subject Re: [RT] OSGi based blocks
Date Wed, 15 Mar 2006 12:31:35 GMT
My own reflections on this is whether or not this is still Cocoon.

It seems to me that you are creating a framework for managing web
applications based upon servlets, OSGi and the URLConnections. This
doesn't seem all that specific to Cocoon - it seems more general than
that, and potentially more generally useful too.

Cocoon's contribution would be its SitemapServlet, and other such elements.

So, my question: Is this still cocoon, or is it becoming something more
general than that (e.g. that could become a Felix sub-project) - thus
gaining a far wider adoption?

Regards, Upayavira



Daniel Fagerstrom wrote:
> I have worked on implementing the blocks framework in terms of OSGi for
> some time. Not everything is working yet, but I think it is time to
> start discussing the involved ideas.
> 
> As already discussed I have refactored the blocks fw to reuse as much as
> possible form the servlet APIs. While studying OSGi R4 and especially
> the new declarative services (DS), I have seen that much of what we want
> to accomplish with blocks already is solved in OSGi, although sometimes
> in a different way.
> 
> I have experimented with implementing the blocks fw in terms of DS, and
> am quite happy with the results. The new architecture is less monolithic
> than the previous one and there is not much code at all, most of it is
> OSGi based design patterns.
> 
>                       --- o0o ---
> 
> So, now over to the actual design. As before we have a number of
> different parts (not everything implemented yet):
> 
> * A dispatcher - where the blocks are mounted with their respective 

> prefixes.
> 
> * Inter block component management - a block can make its components
> available to other blocks, and use components from other blocks.
> 
> * Component manager bridges- the components within a block can be setup
> by our ECM/Spring container or maybe by some other kind of container.
> 
> * Inter block communication and polymorphism - a sitemap, and more
> generally a servlet, can call servlets in other blocks. And there is
> also inheritance so that one sitemap (or servlet) can extend another one.
> 
> * Dynamic deployment and configuration - the blocks can be installed,
> updated, reconfigured and removed dynamically while the rest of the
> framework is executing.
> 
> In the rest of the RT we will step through these parts and look at the
> design. But first a little bit about DS, that is used everywhere in the
> design and replaces block.xml among other things in the current design.
> 
> Declarative Services
> ====================
> 
> The declarative services simplify service (component) handling in OSGi
> by making it possible to declare services and their dependencies in an
> XML file (before service management wasn't configuration file based in
> OSGi).
> 
> The DS supports setter injection. Compared to Spring it is rather small
> and primitive. The cool thing about it is that it support dynamic
> dependencies. A dynamic dependency can have both a setter and an un-setter.
> 
> The framework also takes care of stopping and starting non-dynamic
> components when their dependencies comes and goes.
> 
> The DS can be used together with a configuration service that can
> override the default configurations in the DS XML file. The
> configuration service can take part of the responsibility that the
> wiring file and deployer takes in the current architecture.
> 
> There is not much documentation for the DS yet, so the main references
> are the specification [1] and the documentation of the service binder
> [2] that was a predecessor of DS.
> 
> The dispatcher
> ==============
> 
> The role of the dispatcher is that the blocks (servlets) are mounted in
> it based together with their URI prefixes. The dispatcher then call the
> blocks based on the incoming URIs. This is already handled by the OSGi
> HTTP service which provides a service that a servlet can lookup and
> register it self in.
> 
> A HTTP service implementation normally contains a HTTP server. But an
> alternative for embedding OSGi managed servlets in a servlet container
> is to use a HTTP service that acts as a bridge to the embedding servlet
> container [3].
> 
> It is also inconvenient to require the servlets to lookup the HTTP
> service. It is better to use the whiteboard pattern [4], and just
> register the servlets as services and have a component that reacts on
> the appearance and disappearance of servlet services, and register and
> unregister them in the HTTP service respectively.
> 
> Using DS a declaration (which is referred to by the Service-Component
> property in the manifest file) for a "whiteboard" adapter can look like
> [5]:
> 
>   <scr:component name="cocoon.activator">
>     <scr:implementation class="org.apache.cocoon.blocks.osgi.Activator"/>
>     <scr:reference name="LOG"
>                    interface="org.osgi.service.log.LogService"
>                    bind="setLog"/>
>     <scr:reference name="HTTP"
>                    interface="org.osgi.service.http.HttpService"
>                    bind="setHttpService"/>
>     <scr:reference name="Servlet"
>                    interface="javax.servlet.Servlet"
>                    cardinality="0..n"
>                    policy="dynamic"
>                    bind="setServlet"
>                    unbind="unsetServlet"/>
>   </scr:component>
> 
> which activates the class o.a.c.blocks.osgi.Activator [6] by calling its
>  "void activate(ComponentContext)" method if there is one. We can also
> see that the declaration refers to other services. It will not be
> activated until all its references are fulfilled. In this case it
> require a log service and an HTTP service to be present, and will insert
> these into the Activator instance by using its setLog and setHttpService
> methods.
> 
> The servlet reference is more interesting, it is dynamic an it has
> cardinality 0..n. This means that the activator can be connected to many
> servlets and that they can come and go dynamically. Each time a servlet
> service appears the setServlet method is called with it and each time
> one disappear the unsetServlet method is called.
> 
> The name attribute for the references are used for allowing service
> manager style lookup using the name, within the component. The service
> manager can be get through the ComponentContext.
> 
> A Servlet Service
> -----------------
> 
> A bundle that provides a servlet, can register it as a service with a
> declaration like [5]:
> 
>   <scr:component name="cocoon.servlet3">
>     <scr:implementation class="org.apache.cocoon.blocks.osgi.TestServlet"/>
>     <scr:service>
>       <scr:provide interface="javax.servlet.Servlet"/>
>     </scr:service>
>     <scr:property name="path" value="/test3"/>
>   </scr:component>
> 
> compared to the whiteboard adapter we can see some new things, here we
> provide a service to the framework and it can be refered to by the name
> "cocoon.servlet3" (we should use a better naming scheme, I just adapted
> some examples from the specification while implementing the above).
> 
> The declaration also contains a property: path=/test3, that is looked up
> by the whiteboard adapter and used for mounting the servlet at that URI
> context.
> 
>                       --- o0o ---
> 
> This far we can see that by using what OSGi implementations already
> contain and some minimal glue code [6], we get the possiblity to
> dynamically register (and unregister) servlets within a webapp.
> 
> In the next step we will see how these servlets can share (dynamic)
> components.
> 
> Component Management
> ====================
> 
> Actually we already have inter block component management from OSGi. A
> bundle (block) can provide components by declaring them as services and
> it can depend on other components, possibly from other bundles by
> declaring them as references.
> 
> More specifically, for a servlet to depend on some components, we can
> add a number of set (and unset if we want dynamism) methods to it, and
> add the corresponding references in its declaration.
> 
> So, by just using OSGi, we get much of what the block architecture is
> intended for: dynamic component handling, packaging of servlets
> (sitemaps), sharing of components between blocks.
> 
> Component Manager Bridges
> =========================
> 
> While DS is neat, it is not as flexible and powerful as Spring and we
> still have our legacy of Avalon components to take care of.
> 
> To create a bridge between OSGi services and Spring or Avalon component
> management we need two kind of adapters:
> 
> * An OSGi service to ServiceManager (or BeanFactory) adapter. This
> adapter just implement ServiceManager (or BeanFactory) and lookup the
> components OSGi services. It could be registered as an OSGi service it
> self and refered to by other components that needs a ServiceManager. We
> can even get dynamism by creating the adapter with DS and explicitly
> list the services that it should be able to provide, as references.
> 
> * A Spring component manager to OSGi services adapter. This adapter
> register all the components that is created by the Spring container as
> services. By letting the Spring container have a OSGi service to
> BeanFactory adapter as parent component manager, the Spring component
> manager can use components from other blocks as well, while creating new
> components.
> 
> We have already implemented this kind of bridge for ECM++ [7]. Now we
> need to implement it for the new Spring based container.
> 
> Inter Block Communication
> =========================
> 
> The servlets (sitemaps) in the different blocks need to be able to call
> each other. Also it simplifies reuse of blocks if one block can extend
> another one (or rather that a servlets in one block can extend a servlet
> in another one). This is achieved with the block protocol.
> 
> One way of thinking about the inter block communication is to consider
> the servlet in the block to be embedded in an own container where the
> the servlets of the other blocks are available through the servlet
> context. This is the way I have implemented it, so other servlets can be
> called through the getNamedDispatcher method of the servlet context,
> with the block name as argument.
> 
> The implementation of calls to super blocks and polymorphism requires
> the use of a call stack, see [8] for details.
> 
> Block properties are accessed as servlet config (and context) init
> parameters.
> 
> In the OSGi implementation there is a BlockServlet that sets up the the
> communication with other blocks and creates the context that the servlet
> of the own block is executed within. A declaration of a BlockServlet
> might look like:
> 
>   <scr:component name="cocoon.blockServlet2">
>     <scr:implementation
> class="org.apache.cocoon.blocks.osgi.BlockServlet"/>
>     <scr:service>
>       <scr:provide interface="javax.servlet.Servlet"/>
>     </scr:service>
>     <scr:property name="path" value="/test2"/>
>     <scr:property name="attr" value="bar"/>
>     <scr:reference name="blockServlet"
>                    interface="javax.servlet.Servlet"
>                    target="(component.name=cocoon.servlet2)"/>
>     <scr:reference name="block1"
>                    interface="javax.servlet.Servlet"
>                    target="(component.name=cocoon.blockServlet1)"/>
>   </scr:component>
> 
> Here we can see that we provide a service with the identifier
> "cocoon.blockServlet2" that is implemented by the mentioned BlockServlet
> and implements Servlet, it is mounted on the path "/test2". So the
> "whiteboard" part of the dispatcher described above, will take care of
> installing this block servlet in the HttpService of the framework.
> 
> The servlet reference with the special name "blockServlet" (should find
> a less confusing name) refer to the servlet that is embedded by the
> BlockServlet. The embeded servlet could e.g. be a sitemap servlet, and
> it could get the components it needs through the mechanism described in
> the sections about component management above.
> 
> The "target" attribute in a reference can contain constraints on what
> service that is refered to. The constraint
> "(component.name=cocoon.servlet2)" means that we want the particular
> servlet that is registered under the name "cocoon.servlet2". The
> constraint lanuage is the same as is used in LDAP, and it is possible to
>  create rather complex constraints if needed.
> 
> We can also see that there is a reference to a block servlet with the
> identifier "cocoon.blockServlet1", it will be made available through the
>  servlet context for "cocoon.servlet2" with the getNamedDispatcher
> method  using the name "block1".
> 
> All the properties (path and attr) are made available as init parameters
> in the servlet context for "cocoon.servlet2".
> 
> As we can see, the above DS configuration of a block servlet take care
> of most of what is configured in block.xml in the current block
> architecture.
> 
> The Block Protocol
> ------------------
> 
> OSGi have an URL service that make it possible to dynamically add
> protocols that are available through java.net.URL, much like the
> Excalibur sources. I have reimplemented the block source as an
> URLConnection that is registered as a protocol and can be used like in
> [9] (still buggy code).
> 
> Deployment
> ==========
> 
> I have not thought that much about deployment of OSGi based blocks, and
> assume Reinhard will have ideas about that.
> 
> For packaging the OSGi framework together with needed service bundles
> and an init configuration it is best to see what the Felix and
> Eclipse/Equinox communities have come up with.
> 
> Most OSGi implementations provide both telnet and http based consoles
> for installing, starting and stopping bundles. Deploy time configuration
> (wiring.xml) seem to have less well developed tool support.
> 
> There is a configuration service that can be used for deploy time
> configuration. With the configuration service one can override the
> properties and target attributes for references that is given in the DS
> files in the bundles.
> 
> The wiring.xml could be used for setting up the configuration service.
> 
> Conclusion
> ==========
> 
> It should be noted that I haven't referred to any Cocoon specifics
> above. That is one of the neat things about the architecture. It is
> completely orthogonal to and independent of the rest of Cocoon and it
> could be used together with any servlet based web framework.
> 
> It is obviously not exactly as the block architecture that was designed
> a couple of years ago. But it is rather close and by reusing so much of
> OSGi we get a rather small implementation that can be interesting for
> other communities. Much of the surrounding infrastuture will be needed
> by other OSGi users, so much can be developed together with other
> communities.
> 
> WDYT?
> 
> /Daniel
> 
> 
> References
> ==========
> 
> [1] OSGI R4 specification
> http://www.osgi.org/osgi_technology/download_specs.asp?section=2
> [2] Service binder http://gravity.sourceforge.net/servicebinder/
> [3] Servlet container embedding
> http://www.eclipse.org/equinox/incubator/server/embedding_in_a_servlet_container.php
> 
> [4] Whiteboard pattern
> http://www.osgi.org/documents/osgi_technology/whiteboard.pdf
> [5]
> http://svn.apache.org/repos/asf/cocoon/trunk/cocoon-blocks-fw/cocoon-blocks-fw-osgi-impl/META-INF/components.xml
> 
> [6]
> http://svn.apache.org/repos/asf/cocoon/trunk/cocoon-blocks-fw/cocoon-blocks-fw-osgi-impl/src/main/java/org/apache/cocoon/blocks/osgi/Activator.java
> 
> [7] The bridge was part of cocoon-core in package o.a.c.core.osgi,
> Reinhard moved it to the whiteboard, but the code seem to have
> disappeared on its way.
> [8] Obsolete description of the sitemap blocks that contain an
> explanation of how polymorphism is implemented
> http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=111791016006393&w=2
> [9]
> http://svn.apache.org/repos/asf/cocoon/trunk/cocoon-blocks-fw/cocoon-blocks-fw-osgi-impl/src/main/java/org/apache/cocoon/blocks/osgi/TestServlet2.java
> 
> 


Mime
View raw message