Versions Compared

Key

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

...

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

Framework Choice

After analyzing the available options, we have selected the Spring framework, version 3.

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 considered 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, JSR-250 @PostConstruct/@PreDestroy annotations, spring-specific annotation, or xml-configured)

Yes (interface or JSR-250 @PostConstruct/@PreDestroy annotations)

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

Spring was selected because:

  • It provides an out-of-box and commonly-used way to wire and configure modules ("beans"), outside of code.
  • It supports JSR-250 annotations for module lifecycle hooks
  • Its OSGi-friendliness is well-documented

Implementation Strategy/Principles

...

Implementation Plan

Overview + Discussion

View presentation from March 16th, 2010 Special Topic Meeting

Phase I - Prepare

...

  • Decouple module interface impl from Module abstract class where needed
  • Push param validation responsibility down to each impl (not in Module)
  • Use constructor injection if possible. For those with circular dependencies that can't be refactored easily, provide setters.
  • Where existing modules look at configuration of other modules, get the configuration value from a getter in the interface, not the configuration.
  • Where existing modules look at global fcfg values, make those available via bean-style class, GlobalConfig.
  • Where existing modules look at datastore fcfg values, inject the connectionpool or config values directly.
  • Constructors for impls should do as much arg validation/setup as they can.  If they can't do it all, it should be done in a @PostConstruct void init() method.  In either case, if validation or setup fails, an unchecked exception should be thrown, as per JSR-250.
  • Where de-initialization is needed, a @PreDestroy void destroy() method should be used. Errors encountered during de-initialization should be logged by this method, and an unchecked exception should be thrown, as per JSR-250.
    Tasklist
    Modifications Needed
    Modifications Needed
    || Completed || Priority || Locked || CreatedDate || CompletedDate || Assignee || Name ||
    |F|M|F|1268080202735|  F | M | F | 1268080202735 | | cwilper | Add and populate GlobalConfig |
    |F|M|F|1268080236272|  F | M | F | 1268080236272 | | cwilper | Update org.fcrepo.server.access.DefaultAccess |
    |F|M|F|1268080257979|  F | M | F | 1268080257979 | | cwilper | Update org.fcrepo.server.access.DynamicAccessModule |
    |F|M|F|1268080268001|  F | M | F | 1268080268001 | | cwilper | Update org.fcrepo.server.journal.Journaler |
    |F|M|F|1268080276055|  F | M | F | 1268080276055 | | cwilper | Update org.fcrepo.server.management.BasicPIDGenerator |
    |F|M|F|1268080285519|  F | M | F | 1268080285519 | | cwilper | Update org.fcrepo.server.management.ManagementModule |
    |F|M|F|1268080327906|  F | M | F | 1268080327906 | | cwilper | Update org.fcrepo.server.messaging.MessagingModule |
    |F|M|F|1268080339553|  F | M | F | 1268080339553 | | cwilper | Update org.fcrepo.server.oai.FedoraOAIProviderModule |
    |F|M|F|1268080350944|  F | M | F | 1268080350944 | | cwilper | Update org.fcrepo.server.resourceIndex.ResourceIndexModule |
    |F|M|F|1268080374403|  F | M | F | 1268080374403 | | cwilper | Update org.fcrepo.server.search.FieldSearchSQLModule |
    |F|M|F|1268080381223|  F | M | F | 1268080381223 | | cwilper | Update org.fcrepo.server.security.DefaultAuthorization |
    |F|M|F|1268080399963|  F | M | F | 1268080399963 | | cwilper | Update org.fcrepo.server.security.DefaultBackendSecurity |
    |F|M|F|1268080425721|  F | M | F | 1268080425721 | | cwilper | Update org.fcrepo.server.storage.ConnectionPoolManagerImpl |
    |F|M|F|1268080433280|  F | M | F | 1268080433280 | | cwilper | Update org.fcrepo.server.storage.DefaultDOManager |
    |F|M|F|1268080461067|  F | M | F | 1268080461067 | | cwilper | Update org.fcrepo.server.storage.DefaultExternalContentManager |
    |F|M|F|1268082094738|  F | M | F | 1268082094738 | | cwilper | Update org.fcrepo.server.storage.lowlevel.akubra.AkubraLowlevelStorageModule |
    |F| M|F|1268082154104| | M | F | 1268082154104 | | cwilper |nigel thomas|Update org.fcrepo.server.storage.lowlevel.DefaultLowlevelStorageModule |
    | F | M | F | 1268082165864 | | cwilper | F|M|F|1268082165864|          |cwilper|Update org.fcrepo.server.storage.translation.DOTranslationModule |
    |F|M|F|1268082180490|  F | M | F | 1268082180490 | | cwilper | Update org.fcrepo.server.validation.DOValidatorModule |
    

Phase II - Swap

  • (tick) Decide on DI framework: Spring 3
  • Convert fcfg to DI configuration and update installer to populate it instead
  • Trigger initialization of module singletons via DI framework in context initialization
  • Use injected module dependencies wherever possible, avoiding use of Module and Server at runtime

...