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 > >