Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

...

Background

At a face-to-face meeting in April 2009, the Fedora committers agreed to begin moving toward OSGi as a module framework for Fedora.  Over the remainder of 2009, several of us gained experience with OSGi:

...

So, rather than concentrating on "Moving to OSGi" as a goal in itself, we resolved to improve Fedora's modularity in other, more tractable ways, while using the knowledge we've gained over the last year to increase Fedora's "OSGi-Friendliness" over time. 

Goals

We have identified a few concrete steps we can take to move Fedora's Module Architecture forward:

Getting Involved

Want to

...

help?

...

Great! Please signal your interest by adding your name below, contributing to this wiki page, and participating in related discussions on the fedora-commons-developers mailing list.

...

Interested Contributors: (thumbs up) Dan Davis, (thumbs up) Andrew Woods, (thumbs up) Asger Askov Blekinge

OSGi Friendliness

What can we do to make Fedora more OSGi-friendly (ideally, without building in any runtime dependencies on OSGi)?

  • For jars that are intended to be usable by other projects, build them with the maven-bundle-plugin so they include OSGi metadata.
  • Put APIs and implementation details in different packages.  Two common conventions in the OSGi world are to use an ".internal" or ".impl" suffix on packages that contain implementation details. If you use the maven-bundle-plugin, such named packages will not be exported by default.
  • If possible, avoid using libraries that are known to be problematic in OSGi environments, or require third-party repackaging in order to work in OSGi environments.  Well-known examples include:

Dependency Injection Framework

Problem Statement

Fedora's original Server and Module classes were designed in 2002, and provided a common way for major functional components ("modules") of the repository to be plugged in, configured, initialized, and stopped. Problems with the existing framework include:

  • It's homegrown. Better, more widely-understood frameworks have come along.
  • Unit testing is unnecessarily complicated. The base Module class depends on a Server instance being available in order to function, and the Server base class is not easily mocked.

Requirements

Use standard, well-known frameworks/libraries to:

  • Resolve inter-module dependencies via dependency injection
  • Provide hooks to initialize/de-initialize modules when the webapp container starts and stops
  • Allow re-configuration and plugging in of alternative modules without re-compiling

Non-requirements

This work will NOT attempt to:

  • Provide a way to dynamically re-configure modules without restarting
  • Provide the ability to run modules in their own classloader space

These capabilities may be added in the future, possibly with the help of OSGi.

Framework Choice

Popular frameworks that support the dependency injection pattern include Spring, PicoContainer, and Guice.

How do they compare? Several articles have been written comparing Spring and Guice, as well as all three. As many have pointed out, Spring and Guice are more than DI frameworks. For our purposes, we should consider the attributes of each that are most relevant to the problem at hand:

 

Spring

PicoContainer

Guice

Supports start/stop lifecycle hooks for components

Yes (interface or xml-configured)

Yes (interface or annotation)

No

Supports autowiring

Yes

Yes

Yes

Supports in-code wiring and configuration

Yes (JavaConfig)

Yes

Yes

Supports external wiring (outside of code)

Yes (xml)

No

Not directly (but it's possible)

Supports external config (outside of code)

Yes (xml and/or properties)

No

Yes (Names.bindProperties)

OSGi-Friendly

Yes (Spring-DM)

Unknown

Yes (Guice-Peaberry)

JSR-330 Support

Yes, 3.0+

In Progress

In Progress

Jar Footprint (non-OSGi)

750kb

300kb

650kb

Implementation Strategy/Principles

  • Prefer constructor injection to setter injection
  • Minimize coupling of code with DI framework
  • Minimize changes to existing runtime functionality

Implementation Plan

Phase I - Preparation

  • List all dependents of existing module interfaces.
  • Identify and remove unused modules.
  • Identify and address circular module dependencies. Refactor if possible; otherwise prepare to use setter injection in these cases.

Phase II

  • Profit

Current Inter-Module Dependencies

...

Module Interface

...

Implementation(s)

...

Depends-on

...

Access

...

DefaultAccess

...

Authorization
DOManager
DynamicAccess
ExternalContentManager
OAIProvider

...

Authorization

...

DefaultAuthorization

...

DOManager

...

BackendSecurity

...

DefaultBackendSecurity

...

- none -

...

ConnectionPoolManager

...

ConnectionPoolManagerImpl

...

- none -

...

DOManager

...

DefaultDOManager
GSearchDOManager
RebuildDOManager

...

ConnectionPoolManager
DOTranslator
DOValidator
ExternalContentManager
FieldSearch
ILowlevelStorage
Management
PIDGenerator
ResourceIndex

...

DOTranslator

...

DOTranslatorImpl
DOTranslatorModule

...

- none -

...

DOValidator

...

DOValidatorImpl
DOValidatorModule

...

- none -

...

DynamicAccess

...

DynamicAccessImpl
DynamicAccessModule

...

Access
DOManager

...

ExternalContentManager

...

DefaultExternalContentManager

...

Authorization
BackendSecurity

...

FieldSearch

...

FieldSearchSQLImpl
FieldSearchSQLModule

...

ConnectionPoolManager
DOManager

...

ILowlevelStorage

...

AkubraLowlevelStorage
AkubraLowlevelStorageModule
DefaultLowlevelStorage
DefaultLowlevelStorageModule
Third-Party...

...

ConnectionPoolManager (only used by DefaultLowlevelStorage)

...

Management

...

Authorization
DOManager
ExternalContentManager

...

Messaging

...

MessagingImpl
MessagingModule

...

- none -

...

OAIProvider

...

FedoraOAIProvider
FedoraOAIProviderModule
SampleOAIProvider

...

DOManager
FieldSearch

...

PIDGenerator

...

DBPIDGenerator
BasicPIDGenerator

...

ConnectionPoolManager

...

ResourceIndex

...

ResourceIndexImpl
ResourceIndexModule

...

- none -

...

ThreadMonitor

...

ThreadMonitorImpl
ThreadMonitorModule

...