Upload
others
View
3
Download
0
Embed Size (px)
Citation preview
Mario J Lorenzo
2/22/18
Aspect-Oriented Whiteboard Pattern
Introduction
In an effort to make software systems more modular, frameworks such as OSGi
provide application developers with a runtime and a specification for defining modules,
called bundles. These bundles can provide and consume services from the OSGi service
registry that functions like a centralized catalog accessible by all bundles and services.
This service-based paradigm introduces new design challenges that have been addressed
through design patterns [6]. One such pattern is the Whiteboard pattern [1]. This pattern
addresses a critical limitation of the Observer/Listener pattern when applied in a runtime
environment where services are dynamic and can register and unregister at any time [2].
The classic Observer pattern introduces unwanted tight coupling between the event
source (observable) and the listener (observer), but when applied within a service-
oriented runtime like OSGi, it also produces a high likelihood of memory leaks caused by
services shutting down or restarting without unregistering themselves from the
observable object. Because service dynamism is an essential aspect of the OSGi
paradigm a better pattern was necessary. Kriens and Hargrave proposed a new design
pattern that provides a safer mechanism to achieve the same effect of monitoring state
changes across services [1].
The Whiteboard pattern takes advantage of the centralized OSGi Service Registry
as an intermediary that can be used to decouple the listener from the observable. In
addition to reducing tangling, this also achieves the desired effect of allowing the listener
services to run through its lifecycle starting and stopping without holding. As a result,
this allows for better memory management, since garbage collection can reclaim memory
from stale listeners that are no longer used.
Unfortunately, Whiteboard pattern introduces a lot of dependency on the OSGi
framework itself but requiring all the elements of the Whiteboard pattern to interact with
the service registry at various points in the lifecycle. This produces additional unwanted
coupling and complexity. This paper proposes an aspectized implementation of the
Whiteboard pattern that preserves the principle design elements while simplifying and
decoupling the pattern elements from the OSGi framework.
An Example: Logging Service
This approach is demonstrated with an example using AspectJ and an OSGi
runtime running 3 bundles (plugins). The example chosen for this demonstration is a
Logging service, log handlers, and logging service consumer. The Loging service
example was chosen because the OSGi framework provides a Logging service that used
the traditional GoF observer pattern. Today, this implementation is considered a bad
example that is corrected with a whiteboard-based implementation provided along with
the aspectized whiteboard implementation allowing for ideal comparison between the
three approaches.
Classic Observer Listener
The first Log Service example is based on the implementation provided by OSGi.
The following class diagram depicts the Log Service using the classic Observer pattern
from GoF [3].
The key weakness of this implementation within a dynamic service environment
lies in the tight coupling between the LogService and the LogHandlers. Each LogHandler
has awareness of the LogService and the LogService in turn must directly manage and
interact with the Log Handlers in order to perform its notification duties [1].
Because services can be stopped and restarted at any time, this means an external
event could cause a Log Handler to become stale. If these events are not properly
handled, it produces a memory leak. Unfortunately, managing these lifecycle events can
be difficult. Consider that not only would the Log Handler listener need to be
unregistered from the LogService, but it also would need to re-register once it is started
again. These lifecycle events are common in an OSGi environment, where updating
bundles (services) to newer versions without having to restart the runtime is an essential
design point of the runtime. This capability not only allows for updating existing modules
but also allows discovery of new modules at a later point.
Whiteboard pattern
Next we examine the current best practice in handling an observer relationship
within OSGi. The redesigned LogService using the Whiteboard Pattern relies on the
Service Registry to separate the LogService from the LogHandler.
This approach results in a looser coupling between the LogService and the
LogHandler, but unfortunately introduces additional coupling between the LogService
and LogHandler and the OSGi framework. This approach also requires additional code to
register, track, and manage each service. The additional coupling to the OSGi framework
can also be considered a bad practice since OSGi service management becomes a
separate cross-cutting concern from the primary concern of each respective Log service
element.
Fortunately, AoP is an elegant solution helping to separate and encapsulate the
cross-cutting concern of managing the service framework away from the primary concern
of the Logging classes. Before presenting the improved Whiteboard pattern, it is
important to understand why the service framework management is a cross-cutting
concern. This concern was introduced by the Whiteboard pattern. The Whiteboard pattern
resolved concerns with applying the Observer pattern, but introduced this additional
cross-cutting concern of service registry management. Here we demonstrate that further
evolving the Whiteboard pattern by leveraging aspects to remove that cross-cutting code
away from the Logging classes resulting in LogService classes that are oblivious not only
to the listeners but also oblivious to the OSGi service registry management.
Proposed Aspectized Whiteboard pattern
The proposed aspectized implementation of the Whiteboard pattern introduces a
“binding” aspect that performs the heavy lifting. In this Logging example, the
“LogHandlerBinding” aspect performs several key functions.
1. Defines observation points in the form of AspectJ pointcuts that intercept
the initialization of a LogHandler.
2. For each LogHandler that is initialized in the runtime, the
LogHandlerBinding aspect applies advice that registers the Log Handler
as a service. This is key contribution of the Whiteboard pattern, but shifts
the responsibility of registering the service to the aspect that represents the
Log-Handler binding concern.
3. Defines observation points in the form of pointcuts that intercept
invocations to the log method of the LogHandler object.
4. Proceeds to apply advice by looking up the registered LogHandlers and
notifying them with the log message in this example.
The implementation of this approach is surprisingly simple and clean. The critical
contribution of this proposal lies in understanding the concern that is being addressed by
the aspect. In this Log Service example, the concern that is being addressed is the binding
between the LogService and a collection of Log Handlers that are notified of a log
message and then proceed to log it in different ways. Further analysis of the binding
concern reveals two critical observation points that need to be intercepted. The first is the
initialization of new log handlers. This allows the binding aspect to discover one of the
two critical elements of the observer/listener pattern, the observer. The second
observation point describes where the notification should occur. In the classical version
of the Observer pattern, this would cause scattering of listener notification code
throughout the system. Instead, this approach cleanly localizes those notification points
within the binding aspect.
The binding aspect applies two forms of advice. The first advice is applied to the
initialization of a new Log Handler and registering it as a service. This fulfills the
Whiteboard pattern approach.
The second advice is applied to the notification points across the system. This
advice notifies the registered Log Handlers passing the arguments as context. For this
Log Service example, the context is just the log message.
This advice uses a helper method that looks up the registered LogHandler services
and notifies each one with the log message. This code is sometimes referred to as the
“glue” code that binds the event producer, the log consumer, and the event consumer, the
LogHandler. This binding was dynamically established by the aspect intercepting an
invocation to the log() method and then looking up the registered listeners and
performing the notification.
This approach of localizing the service registry and binding into the aspect produces very
simple code that is decoupled from the osgi framework and other pattern elements (i.e.
LogHandler, LogService, Log consumer).
The Log Handler simply implements (realizes) the LogServiceHandler interface
(called BetterLogServiceHandler in this aspectized implementation) by providing an
implementation of the handleMessage() operation.
The bundle simply instantiates the log handler within its constructor or activation start()
method.
This initialization of the handler is targeted by the binding aspect’s
“logHandlerInitializationPoints” pointcut presented above.
The Log Service consumer can simply acquire an instance of the Log service (called
BetterLogServiceImpl in this example) and invoke the log method.
The major difference between this new aspectized version of Whiteboard pattern
and the standard Whiteboard pattern is the lack of glue code, scattered notification code
throughout the system, and the decoupling from the OSGi service registry. Instead this
concern is addressed by the “LogHandlerBinding” aspect, shielding the system classes
from this complexity.
After examining the design of this aspect, there is an opportunity to generalize
this aspect pattern by leveraging an abstract binding aspect that allows for sub-aspects to
provide the notification points and the initialization of the listeners. This approach would
produce a reusable abstract aspect that can be concretized by simply providing the
concrete pointcuts.
Effects of Aspectizing Whiteboard Pattern
In order to assess the impacts of aspectizing the Whiteboard pattern, a quantitative
approach was used evaluating the standard and aspectized version of the pattern across a
sampling of 3 key modularity dimensions. Using the Modularity Metrics Suite
established by Sant’Anna et al, a single metric from each dimension was selected to serve
as a representation for the given dimension. The results demonstrate a clear improvement
in modularity in the proposed aspectized version of the Whiteboard pattern when
evaluated against the simple OSGi Log service. Modularity Dimensions Standard
Whiteboard
Aspectized
Whiteboard
Coupling (CBC) 3 2
Cohesion (LCOO) 9 2
SoC (CDO) 1 2
Software Modularity Metrics Suite [11]
These findings support the intuitive observations when comparing the class diagrams for
each approach. The aspectized version eliminated dependencies on several classes that
were pervasive across all classes participating in the pattern by localizing the service
registry mechanisms into the aspect and away from the domain classes. This approach
also reduced the need to mark the log service itself with a marker type and as discussed in
the future work section, can potentially further reduce non-domain classes by removing
the marker type used for identifying observers by leveraging Java annotations. This also
supports the observations made by Lesiecki that programming language features play a
role in the implementation and need of these patterns [9].
Discussion
During the experimentation with aspectizing the Whiteboard pattern, an initial
challenge of understanding the underlying cross-cutting concern that was to be addressed
was not evident. After experimenting with the Whiteboard pattern through a concrete
example (Log service) and reviewing literature on how the Observer pattern was
aspectized, it became clear that the key contribution was to enhance the Whiteboard
pattern by localizing the service registry mechanisms away from the participating classes
into its own aspect. This also helped decide where the aspect should reside. Since OSGi
is a modular system, each bundle should reduce visibility to neighboring classes in other
bundles. In order to insure that a circular dependency was avoided, placing the concrete
binding aspect in the bundle that is observed was the ultimate solution.
A future consideration to improving on this work lies in further generalizing an
abstract binding aspect that can be encapsulated in its own bundle. This allows for reuse
of the abstract aspect mechanisms while allowing for extensibility and reuse by other
listener concerns across the system through concretizing the binding aspect with specific
notification points and type markers used to identify the observers.
Throughout this experimentation, the OSGi framework itself presented additional
complexities over a standard Java runtime. Working through getting a defined OSGi
runtime with the minimal set of bundles using Equinox Aspect Weaver bundle was non-
trivial to get working. The appendix to this report attempts to include steps that can be
taken to reproduce and run the provided example code.
Review of literature
After a survey of the available literature, no specific work was found addressing
the proposed aspectization of the Whiteboard pattern, but several works provided great
insight into the general aspectization of GoF patterns such as key paper from Hannemann
/ Kiczales evaluating the transformation of GoF patterns with AspectJ where they
conclude that most all GoF patterns benefited from apectization [4]. Using the
Modularity Metrics Suite established by Sant’Anna et al and work from Edge /
Mitropoulos and Cacho et al provided methodology reference for quantitatively
measuring the impacts of aspectization on modularity and reusability through specific
metrics used to evaluate separation of concerns, coupling, cohesion, and conciseness
[11]. Edge and Mitropoulos applied these evaluations to analyze affect of aspectization to
security patterns [7 10]. Cacho et al evaluated aspectization effects on pattern
composition [8]. Rho et al proposed architectural enhancements to the OSGi framework
producing service aspects as first class members of the framework allowing for
scalability [6]. Lesiecki provided an example driven review of aspectizing 3 GoF patterns
using AspectJ and providing a comparative analysis of aspectization impacts on reuse,
understandability, maintenance, and composition [9]. All these works were insightful in
helping to pull together their respective contributions into the proposed aspectized
Whiteboard pattern. The primary contribution of this work is demonstrated in improving
upon the original Whiteboard pattern offered by Hargrave / Kriens by removing
scattering caused by their approach to leveraging the OSGi service registry as the
intermediary for registering listeners resulting in better modularity and reusability as
defined by Edge / Metropoulos and Cacho.
Future Work
The proposed solution can be further generalized beyond a Logging service by
separating the binding aspect into an abstract binding aspect and a concrete aspect. The
abstract aspect will encapsulate the mechanics of OSGi service registration, tracking, and
“glue” code performing the dynamic binding leaving two abstract pointcuts to be defined
by the sub-aspect for defining where notification should occur and the type marker for the
observer. Additional work to leverage Java Annotations can be leveraged with later
versions of AspectJ removing the requirement for using a marker type for observers and
further reducing coupling between modules.
Conclusion
Applying Aspect-oriented approach to the Whiteboard pattern within an OSGi
framework produces an elegant solution that reduces scattering and tangling of service
registry management code and produces loose coupling between domain classes
participating in the pattern. Through a concrete example of a Logging service, it is
possible to examine the advantages of using AspectJ over Java to handle the binding
relationship between a Log service, Log handlers, and Log consumer classes. Through a
comparison, it can be concluded that the aspectized version of the Whiteboard pattern
produces better separation of concern over the standard Whiteboard Java-only pattern and
the classic Observer/Listener GoF pattern. Using metrics for measuring separation-of-
concern, coupling, and cohesion and modularity metrics [8 10 11], it can be quantitatively
demonstrated that the aspectized version of the Whiteboard pattern is better than the
traditional non-aspectized version of the pattern producing better modularity and
localization.
Appendix
Running the Log Service Example.
1. Unzip the AspectizedWhiteboardPatternExample.zip
2. Using Eclipse IDE, import the projects by using File->Import and General ->
Import from Existing Projects
3. Select the three projects (BetterLogService, BetterLogServiceConsumer, and
BetterLogServiceHandler) to import
4. Next import the launch configuration. File->Run/Debug -> Launch
Confgurations. Select the “OSGiExample with AspectJ.launch” (from the
unzipped directory above).
5. Run by selecting Run -> Run Configuration and select the imported
configuration: “OSGiExample with AspectJ.launch”
6. The launch configuration should look like this:
Once the OSGi runtime starts, the equinox aspect weaver debug will show the pointcuts
that were weaved and several messages soon after are produced by the Log Consumer
testing the logging service. (Note: this assumes the AJDT plugin is installed in the
Eclipse IDE used).
The following shows sample output.
Note the output produced by “StdOutLogger”. Stopping and starting the consumer bundle
will force it to log a message.
References
[1] Alliance, O. (2004). Listeners Considered Harmful: The “Whiteboard” Pattern. Technical Whitepaper.
[2] Hargrave, B. J., & Kriens, P. (2007). OSGi Best Practices!. OSGi Alliance Community Event, 26-27.
[3] Gamma, E., Helm, R., Johnson, R., & Vlissides, J. (1993, July). Design patterns: Abstraction and reuse of object-oriented design. In European Conference on Object-Oriented Programming (pp. 406-431). Springer, Berlin, Heidelberg.
[4] Hannemann, J., & Kiczales, G. (2002, November). Design pattern implementation in Java and AspectJ. In ACM Sigplan Notices (Vol. 37, No. 11, pp. 161-173). ACM.
[5] Kiczales, G., Lamping, J., Mendhekar, A., Maeda, C., Lopes, C., Loingtier, J. M., & Irwin, J. (1997, June). Aspect-oriented programming. In European conference on object-oriented programming (pp. 220-242). Springer, Berlin, Heidelberg.
[6] Rho, T., Schmatz, M., & Cremers, A. B. (2006). Towards context-sensitive service aspects. Work. on Object Technology for Ambient Intelligence and Pervasive Computing.
[7] Edge, C., & Mitropoulos, F. (2012, March). Improving security design patterns with aspect-oriented strategies. In Proceedings of the 50th Annual Southeast Regional Conference (pp. 24-29). ACM.
[8] Cacho, N., Sant'Anna, C., Figueiredo, E., Garcia, A., Batista, T., & Lucena, C. (2006, March). Composing design patterns: a scalability study of aspect-oriented programming. In Proceedings of the 5th international conference on Aspect-oriented software development (pp. 109-121). ACM.
[9] Lesiecki, N. Enhance design patterns with AspectJ. IBM http://www. developers. net/external/730.
[10] Edge, C. & Mitropoulos, F. 2012. Quantitative Analysis of Modularity Tradeoffs with AspectJ Web-
Tier Security Patterns. Workshop on Empirical Evaluation of Software Composition Techniques (ESCOT).
[11] Sant’Anna, C., Garcia, A., Chavez, C., Lucena, C., & Von Staa, A. (2003, October). On the reuse and maintenance of aspect-oriented software: An assessment framework. In Proceedings of Brazilian symposium on software engineering (pp. 19-34).