Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Where, when the ServiceManager is started, two beans are instantiated by Spring, and one is used in the constructor argument of the other.

Future Direction of Spring and OSGi

The Service Manager

The ServiceManager provides a developer API of service lookups and manages the overall lifecycle control for the DSpace Application. During this Lifecycle it also manages the configuration of services by allowing properties to be pushed into the services as they start up (mostly from the ConfigurationService).

The ServiceManagerSystem abstraction allows the DSpace ServiceManager to use different systems to manage its services. The current implementation is Spring Framework based. The original design intent of the Service Manager was to support more than one IoC/DI Solution, however, as work has progressed with DSpace, it has become clear that there are trade offs to consider in its usage.

  1. Spring Injection, when used properly, means we do not need to make "lookup calls" to a central "ServiceManager" or "DSpace" object to acquire the service beans we our own code to work with.
  2. Fewer lookups mean less centralized dependencies
  3. Fewer Centralized Dependencies means fewer bottlenecks in source Code Dependency Management.
  4. Fewer Bottlenecks means greater modularity and encapsulation, less need to carry around all the source code when overriding and customizing "dspace".
  5. More use of binary distributions means greater ease in upgrading DSpace.

It is clear that Spring has become quite dominant a solution in DSpace with the adoption of Apache Cocoon 2.2 for the Manakin XMLUI and Spring MVC for the Freemarker Prototype Webapplication currently under Development in the community.

This leads us to our first best practice:

Tip

Best Practice 1: If possible, do use Dependency Injection to acquire your services. This will be of benefit down the road if we make changes to the service manager architecture.

In creating classes that work within the system, the ServiceManager will inject those services you need for you. 

Code Block
public class Example {

    ConfigurationService configurationService;

    RequestService requestService;

    public Example(ConfigurationService cs, RequestService rs)
    {
        this.configurationService = cs;
        this.requestService = rs;
    }

}

Where in our spring configuration we would register this Service via the following configuration:

Code Block

    <bean class="org.dspace.MyService" autowire="byType"/>

Spring AutoWiring looks for other bean of our specific type elsewhere in our configuration and injects them into our service. This is the basic mechanism whereby Addon Modules can reuse existing services or even services provided by other third party modules without having to explicitly depend on any specific implementation of those services.

The DSpace Application Lifecycle

The life cycle of the container and the services therein is controlled by the Web-application context or the DSpace CLI ScriptLauncher main executable in which the servlet has been deployed. The Lifecycle assures that when the Service managers (and specifically Spring in this case) are initialized, the required core and addon services are wired and made available to your application.

Image Removed

The ServiceManager Request Cycle

The ServiceManager Request Cycle is similar to the Webapplication Request Cycle.  In the case of the Service Request, There is an incoming "Request" object with the state of the a call from the client, this Request is then enterpreted by the Container and mapped to a specific Servlet, which executes to completion, On Completion, the Serlvet Generates a

When a request is made by either the Webapplication or the CLI initialization, then the Request Lifecycle is engaged:

Basic Usage

To use the Framework you must begin by instantiating and starting a DSpaceKernel. The kernel will give you references to the ServiceManager and the ConfigurationService. The ServiceManager can be used to get references to other services and to register services which are not part of the core set. For standalone applications, access to the kernel is provided via the Kernel Manager and the DSpace object which will locate the kernel object and allow it to be used.

Code Block

/* Instantiate the Utility Class */
DSpace dspace = new DSpace();


/* Access get the Service Manager by convenience method */
ServiceManager manager = dspace.getServiceManager();


/* Or access by convenience method for core services */
EventService service = manager.getServiceBydspace.getEventService();

The DSpace launcher (

Code Block
bin/dspace

) initializes a kernel before dispatching to the selected command.

The Service Manager Interface

The Path is Clear

This tutorial focuses on adoption of Spring as a best practice for many aspects of DSpace development, from Core Library definition and instantiation to Application Developer implementation of customizations and addons.

  • Spring focuses around providing a way to manage your business objects. (DSpace currently lacks this capability).
  • Spring is both comprehensive and modular. Spring has a layered architecture, you can choose to use just about any part of it in isolation.
  • It is easy to introduce Spring incrementally into existing projects. (The Latest DSpace WebMVC, REST and XMLUI development efforts already leverage Spring WebMVC in the application tier).
  • Spring is designed from the ground up to help you write code that's easy to test. Spring is an ideal framework for test driven projects. (DSpace has only just introduced a JUnit Test Suite, which does not leverage Spring in its solution. However, the DSpace Service Manager already delivers a testing suite leverages Spring to support testing configuration).
  • Spring is an increasingly important integration technology, its role recognized by several large vendors. By utilizing Spring, DSpace will be able to incrementally improve its architecture to be more robust, and more "enterprise grade".

The Service Manager

The ServiceManager provides a developer API of service lookups and manages the overall lifecycle control for the DSpace Application. During this Lifecycle it also manages the configuration of services by allowing properties to be pushed into the services as they start up (mostly from the ConfigurationService).

The ServiceManagerSystem abstraction allows the DSpace ServiceManager to use different systems to manage its services. The current implementation is Spring Framework based. The original design intent of the Service Manager was to support more than one IoC/DI Solution, however, as work has progressed with DSpace, it has become clear that there are trade offs to consider in its usage.

  1. Spring Injection, when used properly, means we do not need to make "lookup calls" to a central "ServiceManager" or "DSpace" object to acquire the service beans we our own code to work with.
  2. Fewer lookups mean less centralized dependencies
  3. Fewer Centralized Dependencies means fewer bottlenecks in source Code Dependency Management.
  4. Fewer Bottlenecks means greater modularity and encapsulation, less need to carry around all the source code when overriding and customizing "dspace".
  5. More use of binary distributions means greater ease in upgrading DSpace.

It is clear that Spring has become quite dominant a solution in DSpace with the adoption of Apache Cocoon 2.2 for the Manakin XMLUI and Spring MVC for the Freemarker Prototype Webapplication currently under Development in the community.

This leads us to our first best practice:

Tip

Best Practice 1: If possible, do use Dependency Injection to acquire your services. This will be of benefit down the road if we make changes to the service manager architecture.

In creating classes that work within the system, the ServiceManager will inject those services you need for you. 

Code Block
public class Example {

    ConfigurationService configurationService;

    RequestService requestService;

    public Example(ConfigurationService cs, RequestService rs)
    {
        this.configurationService = cs;
        this.requestService = rs;
    }

}

Where in our spring configuration we would register this Service via the following configuration:

Code Block

    <bean class="org.dspace.MyService" autowire="byType"/>

Spring AutoWiring looks for other bean of our specific type elsewhere in our configuration and injects them into our service. This is the basic mechanism whereby Addon Modules can reuse existing services or even services provided by other third party modules without having to explicitly depend on any specific implementation of those services.

The DSpace Application Lifecycle

The life cycle of the container and the services therein is controlled by the Web-application context or the DSpace CLI ScriptLauncher main executable in which the servlet has been deployed. The Lifecycle assures that when the Service managers (and specifically Spring in this case) are initialized, the required core and addon services are wired and made available to your application.

Image Added

The ServiceManager Request Cycle

The ServiceManager Request Cycle is similar to the Webapplication Request Cycle.  In the case of the Service Request, There is an incoming "Request" object with the state of the a call from the client, this Request is then enterpreted by the Container and mapped to a specific Servlet, which executes to completion, On Completion, the Serlvet Generates a

When a request is made by either the Webapplication or the CLI initialization, then the Request Lifecycle is engaged:

Basic Usage

To use the Framework you must begin by instantiating and starting a DSpaceKernel. The kernel will give you references to the ServiceManager and the ConfigurationService. The ServiceManager can be used to get references to other services and to register services which are not part of the core set. For standalone applications, access to the kernel is provided via the Kernel Manager and the DSpace object which will locate the kernel object and allow it to be used.

Code Block

/* Instantiate the Utility Class */
DSpace dspace = new DSpace();


/* Access get the Service Manager by convenience method */
ServiceManager manager = dspace.getServiceManager();


/* Or access by convenience method for core services */
EventService service = manager.getServiceBydspace.getEventService();

The DSpace launcher (

Code Block
bin/dspace

) initializes a kernel before dispatching to the selected command.

The Service Manager Interface

Code Block
public interface ServiceManager {

    /**
     * Allows developers to get the desired service singleton by the provided type.
     * This should return all instantiated objects of the type specified
     * (may not all be singletons).
     *
     * @param <T>
Code Block
public interface ServiceManager {

    /**
     * Allows developers to get the desired service singleton by the provided type.
     * This should return all instantiated objects of the type specified
     * (may not all be singletons).
     *
     * @param <T>
     * @param type the type for the requested service (this will typically be the interface class but can be concrete as well)
     * @return the list of service singletons OR empty list if none is found
     */
    public <T> List<T> getServicesByType(Class<T> type);

    /**
     * Allows developers to get the desired service singleton by the provided name and type.
     * Provide {@code null} for the name if it is not known, but it is better to ensure it is set.
     * <p>
     * <em>NOTE</em>: This also allows special access to the underlying
     * service manager objects.  It is possible to get the underlying Spring ApplicationContext object like so:
     * <xmp>
     * getServiceByName(ApplicationContext.class.getName(), ApplicationContext.class);
     * </xmp>
     *
     * @param <T>
     * @param name (optional) the unique name for this service.
     * If null then the bean will be returned if there is only one
     * service of this type.
     * @param type the type for the requested service (this will typically be the interface class but can be concrete as well)
     * @return the list of service singletonsingletons OR empty nulllist if none is found
     */
    public <T> TList<T> getServiceByNamegetServicesByType(String name, Class<T> type);

    /**
     * Allows Lookupdevelopers to seeget ifthe adesired service existssingleton withby the givenprovided name and type.
     *
 Provide {@code null} for *the @param name theif unique name for this service
     * @return true if it exists, false otherwiseit is not known, but it is better to ensure it is set.
     * <p>
     */
    public boolean isServiceExists(String name);

 <em>NOTE</em>: This also allows special access to the underlying
     /**
 service manager objects.  It *is Getpossible theto namesget ofthe allunderlying registeredSpring serviceApplicationContext singletons.object like Byso:
     * convention,<xmp>
 the name typically matches the fully qualified class* getServiceByName(ApplicationContext.class.getName(), ApplicationContext.class);
     * name).</xmp>
     *
     * @return the list of all current registered services@param <T>
     */
 @param name (optional) publicthe List<String> getServicesNames();

    /**unique name for this service.
     * AllowsIf addingnull singletonthen servicesthe andbean providerswill inbe atreturned runtimeif or
there is only one
  *  after the* service managerof hasthis started uptype.
     * This@param istype primarilythe usefultype for registeringthe providers,requested filters, and
     * plugins with the DSpace core.
     *service (this will typically be the interface class but can be concrete as well)
     * @param@return namethe theservice namesingleton ofOR thenull serviceif (mustnone beis unique)found
     */
 @param service the objectpublic to<T> register as a singleton serviceT getServiceByName(String name, Class<T> type);

    /**
     * Lookup @throwsto IllegalArgumentExceptionsee if thea service exists with cannotthe begiven registeredname.
     */
    public void* registerService(String@param name, Object service);

    /**the unique name for this service
     * Allows@return addingtrue singletonif servicesit andexists, providers in at runtime orfalse otherwise
     */
 after the service managerpublic has started up.boolean isServiceExists(String name);

    /**
     * Get the Thisnames isof theall sameregistered asservice {@link #registerService(String, Object)}singletons.  By
     * except that it allows the core service manager to startup yourconvention, the name typically matches the fully qualified class
     * name).
     *
 service  for you instead* of@return youthe providinglist aof serviceall tocurrent theregistered core.services
     */
 In general, it ispublic better if you use your own service managerList<String> getServicesNames();

    /**
     * (likeAllows Springadding orsingleton Guice)services toand manageproviders yourin servicesat runtime and simplyor
     * inheritafter the core service beansmanager fromhas thestarted DSpaceup.
 core service
   * This *is primarily manageruseful usingfor theregistering specialproviders, capabilitiesfilters, ofand
     * {@link #getServiceByName(String, Class)}plugins with the DSpace core.
     *
     * @see ServiceManager#getServiceByName(String, Class)
     * @param name the name of the service (must be unique)
     * @param typeservice the classobject typeto ofregister theas servicea (must be in the current classloader)singleton service
     * @throws IllegalArgumentException if the service cannot be registered because the name is taken or type is invalid or other
     */
    public <T>void T registerServiceClassregisterService(String name, Class<T>Object typeservice);

    /**
     * Allows aadding servicesingleton toservices beand unregisteredproviders (whichin willat onlyruntime work ifor
     * nothing depends on it) after the service manager has started up.
     * This is primarilythe usedsame foras providers, filters, plugins, etc.{@link #registerService(String, Object)}
     * except whichthat wereit registeredallows butthe arecore noservice longermanager availableto becausestartup theyour
     * contextservice theyfor areyou runninginstead inof isyou shuttingproviding downa orservice restarting.
to     * <br/>the core.
     * In WARNING:general, Thisit shouldis notbetter beif usedyou touse attemptyour toown unregisterservice coremanager
     * services as that will fail.
     *(like Spring or Guice) to manage your services  and simply
     * inherit @paramthe namecore theservice namebeans offrom the serviceDSpace (must be unique)core service
     * @throwsmanager IllegalArgumentExceptionusing if the beanspecial cannotcapabilities be unregisteredof
     */
    public void unregisterService {@link #getServiceByName(String, nameClass);}.

     /**
     * Allows new configuration settings to be pushed into the core
     * DSpace configuration.@see ServiceManager#getServiceByName(String, Class)
     * @param name the name of the service (must be unique)
     * @param Thesetype willthe causeclass atype settingsof refreshthe actionservice to(must be in calledthe forcurrent allclassloader)
     * services@throws whichIllegalArgumentException areif listeningthe andservice willcannot causebe anyregistered beanbecause properties
the name is taken or *type tois beinvalid pushed into existing beans.or other
     */
    public *<T> @paramT settings a map of keys (names) and valuesregisterServiceClass(String name, Class<T> type);

    /**
     */
 Allows a service to publicbe voidunregistered pushConfig(Map<String, String> settings);

}

Core Services

Request Service

A request is an atomic transaction in the system. It is likely to be an HTTP request in many cases but it does not have to be. This service provides DSpace with a way to manage atomic transactions so that when a request comes in which requires multiple things to happen they can either all succeed or all fail without each service attempting to manage this independently.

In a nutshell this simply allows identification of the current request and the ability to discover if it succeeded or failed when it ends. Nothing in the system will enforce usage of the service, but we encourage developers who are interacting with the system to make use of this service so they know if the request they are participating in with has succeeded or failed and can take appropriate actions.

Code Block
public interface Request {

    public String getRequestId();

    public Session getSession();

    public Object getAttribute(String name);

    public void setAttribute(String name, Object o);

    public ServletRequest getServletRequest();

    public HttpServletRequest getHttpServletRequest();

    public ServletResponse getServletResponse();
(which will only work if
     * nothing depends on it).
     * This is primarily used for providers, filters, plugins, etc.
     * which were registered but are no longer available because the
     * context they are running in is shutting down or restarting.
     * <br/>
     * WARNING: This should not be used to attempt to unregister core
     * services as that will fail.
     *
     * @param name the name of the service (must be unique)
     * @throws IllegalArgumentException if the bean cannot be unregistered
     */
    public HttpServletResponsevoid getHttpServletResponseunregisterService(String name);

}

The DSpace Session

The Session represents a user's session (login session) in the system. Can hold some additional attributes as needed, but the underlying implementation may limit the number and size of attributes to ensure session replication is not impacted negatively. A DSpace session is like an HttpSession (and generally is actually one) so this service is here to allow developers to find information about the current session and to access information in it. The session identifies the current user (if authenticated) so it also serves as a way to track user sessions. Since we use HttpSession directly it is easy to mirror sessions across multiple servers in order to allow for no-interruption failover for users when servers go offline.

Code Block

public interface Session extends HttpSession {

    /**
     * @return the session identifier.  This is not the {@link #getId()}
     * from HttpSession unless no session id was specified when the
     * session was bound.    /**
     * Allows new configuration settings to be pushed into the core
     * DSpace configuration.
     * These will cause a settings refresh action to be called for all
     * services which are listening and will cause any bean properties
     * to be pushed into existing beans.
     *
     * @param settings a map of keys (names) and values
     */
    public Stringvoid getSessionId(pushConfig(Map<String, String> settings);

    /**
     * Return the internal user ID for this session.
     *
     * @return internal user ID for the user using this session.
     * This is null if the session is anonymous.
     */}

Core Services

Request Service

A request is an atomic transaction in the system. It is likely to be an HTTP request in many cases but it does not have to be. This service provides DSpace with a way to manage atomic transactions so that when a request comes in which requires multiple things to happen they can either all succeed or all fail without each service attempting to manage this independently.

In a nutshell this simply allows identification of the current request and the ability to discover if it succeeded or failed when it ends. Nothing in the system will enforce usage of the service, but we encourage developers who are interacting with the system to make use of this service so they know if the request they are participating in with has succeeded or failed and can take appropriate actions.

Code Block
public interface Request {

    public String getUserIdgetRequestId();

    /**
public Session getSession();

   * Getpublic the external/enterprise user ID for this session.
     *Object getAttribute(String name);

    public void setAttribute(String name, Object o);

    public * @return the external/enterprise user id of the user associated with this session
     */ServletRequest getServletRequest();

    public HttpServletRequest getHttpServletRequest();

    public StringServletResponse getUserEIDgetServletResponse();

    /**
public HttpServletResponse getHttpServletResponse();

}

The DSpace Session

The Session represents a user's session (login session) in the system. Can hold some additional attributes as needed, but the underlying implementation may limit the number and size of attributes to ensure session replication is not impacted negatively. A DSpace session is like an HttpSession (and generally is actually one) so this service is here to allow developers to find information about the current session and to access information in it. The session identifies the current user (if authenticated) so it also serves as a way to track user sessions. Since we use HttpSession directly it is easy to mirror sessions across multiple servers in order to allow for no-interruption failover for users when servers go offline.

Code Block

public interface Session extends HttpSession {

        * @return true if this session is active OR false if the session has timed out or been invalidated
     */
    public boolean isActive();

    /**
     * @return id of the server with which this sessionsession identifier.  This is associated.
not the    */{@link #getId()}
    public String getServerId();

    /**
     * @return the IP Address from which this session originated* from HttpSession unless no session id was specified when the
     * session was bound.
     */
    public String getOriginatingHostIPgetSessionId();

    /**
     * @returnReturn the internal hostnameuser fromID whichfor this session originated.
     */
    public String getOriginatingHostName();

    /**
     * Get an attribute from the session if one exists* @return internal user ID for the user using this session.
     * @paramThis keyis null the key forif the attribute
session     * @return the value if one exists OR null if noneis anonymous.
     */
    public String getAttributegetUserId(String key);

    /**
     * Set an attribute on a Get the external/enterprise user ID for this session.
     *
     * @param@return keythe forexternal/enterprise theuser attribute
id of the user  * @param value (ifassociated with this is null then the attribute is removed)session
     */
    public voidString setAttribute(String key, String valuegetUserEID();

    /**
     * Get@return alltrue attributes ofif this session.
 is active OR false *if @returnthe asession copyhas oftimed theout attributesor in this session.been invalidated
     */
 Modifying it has nopublic effect on the session attributesboolean isActive();

    /**
     * @return id of the server with which this session is associated.
     */
    public Map<String, String> getAttributesString getServerId();

    /**
     * @return Purgesthe allIP dataAddress from which this session andoriginated
 effectively resets it to an*/
    public * anonymous session.String getOriginatingHostIP();

   Does not invalidate the session, though. /**
     */
 @return the hostname public void clear();

Behind APIs

 can be reimplemented without affecting developers who are using the services. 

Most of the services have plugin/provider points so that customizations can be added into the system without touching the core services code.

Example, specialized authentication system and wants to manage the authentication calls which come into the system. The implementor can simply implement an AuthenticationProvider and then register it with the DS2 kernel's ServiceManager. This can be done at any time and does not have to be done during Kernel startup. This allows providers to be swapped out at runtime without disrupting the DS2 service if desired. It can also speed up development by allowing quick hot redeploys of code during development.

Configuration Service

The ConfigurationService controls the external and internal configuration of DSpace 2. It reads Properties files when the kernel starts up and merges them with any dynamic configuration data which is available from the services. This service allows settings to be updated as the system is running, and also defines listeners which allow services to know when their configuration settings have changed and take action if desired. It is the central point to access and manage all the configuration settings in DSpace.

Manages the configuration of the DSpace 2 system. Can be used to manage configuration for providers and plugins also.

Benefits over the DSpace ConfigurationManager

  • Type Casting: Common Configuration Interface supports type casting of configuration values of the type required by the caller.
  • Array Parsing: As part of this type casting, the Configuration Service will split your comma separated values for you

Recommendations: Why parse values if you do not have to, avoid Parsing Values where-ever possible.

  • Use commas for lists of values, use lookups (If you end up thinking you want to create maps in your properties, your doing it in the wrong place look instead at Spring Configuration and objectifying your configuration)
  • Objectifying Configuration (Its best to wire your application components with Spring).

Acquiring the Configuration Service

Code Block
/* Instantiate the Utility Class */
DSpace dspace = new DSpace();

/* Access get the Service Manager by convenience method */
ConfigurationService service = dspace.getSingletonService(ConfigurationService.class);

Legacy Configuration

Wiki Markup
_\[dspace\]/config/dspace.cfg_

ConfigurationService contributed to DSpace 1.7.1 (Service Manager Version 2.0.3) 
support for reading the same "dspace.cfg" legacy file is supported. Example of Usage:
ConfigurationService cs = new DSpace().getConfigurationService();
String prop = cs.getProperty("property");

Code Block
String prop = ConfigurationManager.getProperty("property");

Default Configuration

Wiki Markup
_\[addon.jar\]/config/\[service\].cfg_
\\

Any service can provide sane defaults in a java properties configuration file. These properties will be able to be looked up directly using a prefix as syntax.

Example of Usage:

Code Block

ConfigurationService cs = new DSpace().getConfigurationService();
String prop = cs.getProperty("prefix.property");

N/A

Modularization of Configuration

Wiki Markup
_\[dspace\]/config/module/\[prefix\].cfg_

Any service can provide overrides in the DSpace home configuration directory sane defaults in a java properties configuration file. These properties will be able to be looked up directly using a prefix as syntax.

Example of Usage:

Code Block
ConfigurationService cs = new DSpace().getConfigurationService();
String prop = cs.getProperty("prefix.property");

In DSpace 1.7.0 enhanced capabilities were added to the ConfigurationManager to support the separation of of properties into individual files. The name of these files is utilized as a "prefix" to isolate properties that are defined across separate files from colliding.

Example of Usage:

from which this session originated
     */
    public String getOriginatingHostName();

    /**
     * Get an attribute from the session if one exists.
     * @param key  the key for the attribute
     * @return the value if one exists OR null if none
     */
    public String getAttribute(String key);

    /**
     * Set an attribute on a session.
     *
     * @param key for the attribute
     * @param value (if this is null then the attribute is removed)
     */
    public void setAttribute(String key, String value);

    /**
     * Get all attributes of this session.
     * @return a copy of the attributes in this session.
     * Modifying it has no effect on the session attributes.
     */
    public Map<String, String> getAttributes();

    /**
     * Purges all data from this session and effectively resets it to an
     * anonymous session.  Does not invalidate the session, though.
     */
    public void clear();

Behind APIs

 can be reimplemented without affecting developers who are using the services. 

Most of the services have plugin/provider points so that customizations can be added into the system without touching the core services code.

Example, specialized authentication system and wants to manage the authentication calls which come into the system. The implementor can simply implement an AuthenticationProvider and then register it with the DS2 kernel's ServiceManager. This can be done at any time and does not have to be done during Kernel startup. This allows providers to be swapped out at runtime without disrupting the DS2 service if desired. It can also speed up development by allowing quick hot redeploys of code during development.

Configuration Service

The ConfigurationService controls the external and internal configuration of DSpace 2. It reads Properties files when the kernel starts up and merges them with any dynamic configuration data which is available from the services. This service allows settings to be updated as the system is running, and also defines listeners which allow services to know when their configuration settings have changed and take action if desired. It is the central point to access and manage all the configuration settings in DSpace.

Manages the configuration of the DSpace 2 system. Can be used to manage configuration for providers and plugins also.

Benefits over the DSpace ConfigurationManager

  • Type Casting: Common Configuration Interface supports type casting of configuration values of the type required by the caller.
  • Array Parsing: As part of this type casting, the Configuration Service will split your comma separated values for you

Recommendations: Why parse values if you do not have to, avoid Parsing Values where-ever possible.

  • Use commas for lists of values, use lookups (If you end up thinking you want to create maps in your properties, your doing it in the wrong place look instead at Spring Configuration and objectifying your configuration)
  • Objectifying Configuration (Its best to wire your application components with Spring).

Acquiring the Configuration Service

Code Block
/* Instantiate the Utility Class */
DSpace dspace = new DSpace();

/* Access get the Service Manager by convenience method */
ConfigurationService service = dspace.getSingletonService(ConfigurationService.class);

Legacy Configuration

Wiki Markup
_\[dspace\]/config/dspace.cfg_

ConfigurationService contributed to DSpace 1.7.1 (Service Manager Version 2.0.3) 
support for reading the same "dspace.cfg" legacy file is supported. Example of Usage:
ConfigurationService cs = new DSpace().getConfigurationService();
String prop = cs.getProperty("property");

Code Block
String prop = ConfigurationManager.getProperty("prefix", "property");

Mirrors DSpace Configuration
dspace/config/dspace.cfg
dspace/config/modules/addon.cfg
Defaults supported in Addon Jars.
addon.jar/spring/

Test Driven Development

Default Configuration

Wiki Markup
_\[addon.jar\]/config/\[service\].cfg_
\\

Any service can provide sane defaults in a java properties configuration file. These properties will be able to be looked up directly using a prefix as syntax.

Example of Usage:

Code Block

ConfigurationService cs = new DSpace().getConfigurationService();
String prop = cs.getProperty("prefix.property");

N/A

Modularization of Configuration

Wiki Markup
_\[dspace\]/config/module/\[prefix\].cfg_

Any service can provide overrides in the DSpace home configuration directory sane defaults in a java properties configuration file. These properties will be able to be looked up directly using a prefix as syntax.

Example of Usage:

Code Block
ConfigurationService cs = new DSpace().getConfigurationService();
String prop = cs.getProperty("prefix.property");

In DSpace 1.7.0 enhanced capabilities were added to the ConfigurationManager to support the separation of of properties into individual files. The name of these files is utilized as a "prefix" to isolate properties that are defined across separate files from colliding.

Example of Usage:

Code Block
String prop = ConfigurationManager.getProperty("prefix", "property");

Mirrors DSpace Configuration
dspace/config/dspace.cfg
dspace/config/modules/addon.cfg
Defaults supported in Addon Jars.
addon.jar/spring/

Test Driven Development

Wiki Markup
{*}Test-driven development*&nbsp;(*TDD*) is a&nbsp;[software development process
Wiki Markup
{*}Test-driven development*&nbsp;(*TDD*) is a&nbsp;[software development process|http://en.wikipedia.org/wiki/Software_development_process]&nbsp;that relies on the repetition of a very short development cycle: first the developer writes a failing automated&nbsp;[test case|http://en.wikipedia.org/wiki/Test_case]&nbsp;that defines a desired improvement or new function, then produces code to pass that test and finally&nbsp;[refactors|http://en.wikipedia.org/wiki/Code_refactoring]&nbsp;the new code to acceptable standards.&nbsp;[Kent Beck|http://en.wikipedia.org/wiki/KentSoftware_development_Beck], who is credited with having developed or 'rediscovered' the technique, stated in 2003 that TDD encourages simple designs and inspires confidence.\[process]&nbsp;that relies on the repetition of a very short development cycle: first the developer writes a failing automated&nbsp;[test case|http://en.wikipedia.org/wiki/Test-driven_development\]case]&nbsp;that defines a desired improvement or new function, then produces code to pass that test and finally&nbsp;[refactors|http://en.wikipedia.org/wiki/

...

We want to clarify that that the Testing Framework in the DSpace Services Module Predated the actual JUnit testing support that was added to dspace-api.  Testing is a very beneficial practice where the developer writes small java based test of the code they are going to produce.  The 

...

Code_refactoring]&nbsp;the new code to acceptable standards.&nbsp;[Kent Beck|http://en.wikipedia.org/wiki/

...

Kent_

...

Beck], who is credited with having developed or 'rediscovered' the technique, stated in 2003 that TDD encourages simple designs and inspires confidence.\[http://en.wikipedia.org/wiki/Test-driven_development\]

begun in 1999,\[[2]\|http://en.wikipedia.org/wiki/Test-driven_development#cite_note-Beck-0

We want to clarify that that the Testing Framework in the DSpace Services Module Predated the actual JUnit testing support that was added to dspace-api.  Testing is a very beneficial practice where the developer writes small java based test of the code they are going to produce.  The 

Wiki Markup
Test-driven development is related to the test-first programming concepts of&nbsp;[extreme programming|http://en.wikipedia.org/wiki/Extreme_programming], begun in 1999,\[[2]\|http://en.wikipedia.org/wiki/Test-driven_development#cite_note-Cworld92-1\]&nbsp;but more recently has created more general interest in its own right.\Cworld92-1\]&nbsp;but more recently has created more general interest in its own right.\[[3]\|http://en.wikipedia.org/wiki/Test-driven_development#cite_note-Newkirk-2\]

...

The core services are all behind APIs so that they can be reimplemented without affecting developers who are using the services. Most of the services have plugin/provider points so that customizations can be added into the system without touching the core services code. For example, let's say a deployer has a specialized authentication system and wants to manage the authentication calls which come into the system. The implementor can simply implement an AuthenticationProvider and then register it with the DS2 kernel's ServiceManager. This can be done at any time and does not have to be done during Kernel startup. This allows providers to be swapped out at runtime without disrupting the DS2 service if desired. It can also speed up development by allowing quick hot redeploys of code during development.

Caching Service

Provides for a centralized way to handle caching in the system and thus a single point for configuration and control over all caches in the system. Provider and plugin developers are strongly encouraged to use this rather than implementing their own caching. The caching service has the concept of scopes so even storing data in maps or lists is discouraged unless there are good reasons to do so.

EventService

Handles events and provides access to listeners for consumption of events.

Configuring Event Listeners

Event Listeners can be created by overriding the the EventListener interface:

In Spring:

...


<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <bean id="dspace" class="org.dspace.utils.DSpace"/>

    <bean id="dspace.eventService"
          factory-bean="dspace"
          factory-method="getEventService"/>

    <bean class="org.my.EventListener">
         <property name="eventService" >
    		<ref bean="dspace.eventService"/>
    	</property>
    </bean>
</beans>

speed up development by allowing quick hot redeploys of code during development.

Caching Service

Provides for a centralized way to handle caching in the system and thus a single point for configuration and control over all caches in the system. Provider and plugin developers are strongly encouraged to use this rather than implementing their own caching. The caching service has the concept of scopes so even storing data in maps or lists is discouraged unless there are good reasons to do so.

EventService

Handles events and provides access to listeners for consumption of events.

Configuring Event Listeners

Event Listeners can be created by overriding the the EventListener interface:

In Spring:

Code Block
xml
xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <bean id="dspace" class="org.dspace.utils.DSpace"/>

    <bean id="dspace.eventService"
          factory-bean="dspace"
          factory-method="getEventService"/>

    <bean class="org.my.EventListener">
         <property name="eventService" >
    		<ref bean="dspace.eventService"/>
    	</property>
    </bean>
</beans>

(org.my.EventListener will need to register itself with the EventService, for which it is passed a reference to that service via the eventService property.)

or in Java:

Code Block

DSpace dspace = new DSpace();

EventService eventService = dspace.getEventService();

EventListener listener = new org.my.EventListener();
eventService.registerEventListener(listener);

(This registers the listener externally – the listener code assumes it is registered.)

Further Reading and Resources:

(org.my.EventListener will need to register itself with the EventService, for which it is passed a reference to that service via the eventService property.)

or in Java:

Code Block

DSpace dspace = new DSpace();

EventService eventService = dspace.getEventService();

EventListener listener = new org.my.EventListener();
eventService.registerEventListener(listener);

...