Versions Compared

Key

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

...

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();

Wiki Markup
The DSpace launcher
(

...

 (\[dspace\]/bin/dspace

...

) initializes a kernel before dispatching to the selected command.

The Service Manager Interface

Code Block
public interface ServiceManager {

    public <T> List<T>  /**getServicesByType(Class<T> type);

    public *<T> AllowsT developers to get the desired service singleton by the provided type.getServiceByName(String name, Class<T> type);

    public boolean isServiceExists(String name);

    public * This should return all instantiated objects of the type specified
     * (may not all be singletons).
     *List<String> getServicesNames();

    public void registerService(String name, Object service);

     * @parampublic <T>
 T registerServiceClass(String name, Class<T> type);

    public void unregisterService(String name);


    public void pushConfig(Map<String, String> settings);

}

Core Services

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.

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

The ConfigurationService API

Code Block
public interface ConfigurationService {

    /**  * @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.
     * ProvideGet {@codea null}configuration forproperty the(setting) namefrom ifthe itsystem isas nota
 known, but it is better* to ensure it is setspecified type.
     * <p>
     * <em>NOTE</em>: This also allows special access to the underlying@param <T>
     * @param name the property name
     * service@param managertype objects.  It is possiblethe type to getreturn the underlyingproperty Springas
 ApplicationContext object like so:
 * @return the property *value <xmp>
OR null if none  * getServiceByName(ApplicationContext.class.getName(), ApplicationContext.class);is found
     * </xmp>
@throws UnsupportedOperationException if the type *
cannot be converted to the *requested @param <T>type
     * @param name (optional) the unique name for this service./
    public <T> T getPropertyAsType(String name, Class<T> type);

    /**
     * IfGet nulla thenconfiguration theproperty bean(setting) willfrom bethe returnedsystem, ifor therereturn
 is only one
  * a default *value serviceif ofnone thisis typefound.
     *
 @param type the type for* the@param requested<T>
 service (this will typically be the interface class but can be concrete as well) * @param name the property name
     * @param defaultValue the value to return if this name is not found
     * @return the serviceproperty singletonvalue OR null if none is found
     * @throws IllegalArgumentException if the defaultValue type does not match the type of the property by name
     */
    public <T> T getServiceByNamegetPropertyAsType(String name, Class<T>T typedefaultValue);

    /**
     * LookupGet toa seeconfiguration ifproperty a(setting) servicefrom existsthe withsystem, the given name.or return
     *
 (and possibly store) a *default @paramvalue nameif thenone unique name for this serviceis found.
     *
 @return true if it exists,* false@param otherwise<T>
     */
 @param name  public boolean isServiceExists(Stringthe property name);

     /**
 @param defaultValue the value *to Getreturn theif namesthis ofname allis registered service singletons.  By
     * convention, the name typically matches the fully qualified class
     * name).
     *not found
     * @param setDefaultIfNotFound if this is true and the config value
     * is not found then the default value will be set in the
     * configuration store @returnassuming theit listis ofnot allnull. current registeredOtherwise servicesthe
     */
 default value is publicjust List<String> getServicesNames();

    /**returned but not set.
     * Allows@return addingthe singletonproperty servicesvalue andOR providersnull inif atnone runtimeis orfound
     * after the service manager has started up. @throws IllegalArgumentException if the defaultValue type does not match the type of the property by name
     */
 This  is primarilypublic useful<T> forT registeringgetPropertyAsType(String providersname, T filters, anddefaultValue, boolean setDefaultIfNotFound);

    /**
     * Get pluginsall withcurrently theknown DSpaceconfiguration core.settings
     *
     * @param@return nameall the name of the service (must be unique)configuration properties as a map of name -> value
     */
  @param service thepublic objectMap<String, to register as a singleton serviceString> getAllProperties();

    /**
     * Convenience @throwsmethod IllegalArgumentException- ifget thea serviceconfiguration cannotproperty be(setting) registeredfrom
     */
 the system.
  public void registerService(String name, Object service);

 *
     /**
 @param name the property name
     * Allows@return addingthe singletonproperty servicesvalue andOR providersnull inif atnone runtimeis orfound
     * after the service manager has started up./
    public String getProperty(String name);

    /**
     * Convenience Thismethod is- theget sameall asconfiguration {@linkproperties #registerService(String, Objectsettings)}
     * except that it allowsfrom the coresystem.
 service manager to startup your*
     * service@return forall youthe insteadconfiguration ofproperties youin providinga aproperties serviceobject to(name the core.-> value)
     */
 In general, it ispublic better if you use your own service managerProperties getProperties();

    /**
     * Set (likea Springconfiguration orproperty Guice(setting) toin manage your services  and simplythe system.
     * inheritType theis corenot serviceimportant beanshere fromsince theconversion DSpacehappens core serviceautomatically
     * managerwhen usingproperties the special capabilities ofare requested.
     * {@link #getServiceByName(String, Class)}.
     *
 @param name the  * @see ServiceManager#getServiceByName(String, Class)property name
     * @param namevalue the name of the service (must be unique property value (set this to null to clear out the property)
     * @return @paramtrue typeif the classproperty typeis ofnew theor servicechanged (mustfrom bethe in the current classloader)existing value, false if it is the same
     * @throws IllegalArgumentException if the name is null
     * @throws IllegalArgumentExceptionUnsupportedOperationException if the servicetype cannot be registeredconverted becauseto thesomething namethat is taken or type is invalid or otherunderstandable by the system as a configuration property value
     */
    public <T>boolean T registerServiceClasssetProperty(String name, Class<T>Object typevalue);

    /**
     * Allows a service to be unregistered (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 void unregisterService(String name);

    /**
     * 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 void 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();

    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 the session identifier.  This is not the {@link #getId()}
     * from HttpSession unless no session id was specified when the
     * session was bound.
     */
    public String getSessionId();

    /**
     * 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.
     */
    public String getUserId();

    /**
     * Get the external/enterprise user ID for this session.
     *
     * @return the external/enterprise user id of the user associated with this session
     */
    public String getUserEID();

    /**
     * @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 session is associated.
     */
    public String getServerId();

    /**
     * @return the IP Address from which this session originated
     */
    public String getOriginatingHostIP();

    /**
     * @return the hostname 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();

Benefits over the Legacy 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 comma separated values for you when you request the property as type "Array"
    Code Block
    /* type casting */
    int value = configurationService.getPropertyAsType("some-integer",int.class);
    
    
    
    /* Array Parsing */
    String[] values = configurationService.getPropertyAsType("some-array", String[].class);
    
    /* Default Values */
    int value = configurationService.getPropertyAsType("some-integer",1);
    
    
    
    /* Default Array Values */
    String[] values = configurationService.getPropertyAsType("some-array",new String[]{"my", "own", "array"});
            

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

 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.

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

The ConfigurationService API

Code Block
public interface ConfigurationService {

    /**
     * Get a configuration property (setting) from the system as a
     * specified type.
     *
     * @param <T>
     * @param name the property name
     * @param type the type to return the property as
     * @return the property value OR null if none is found
     * @throws UnsupportedOperationException if the type cannot be converted to the requested type
     */
    public <T> T getPropertyAsType(String name, Class<T> type);

    /**
     * Get a configuration property (setting) from the system, or return
     * a default value if none is found.
     *
     * @param <T>
     * @param name the property name
     * @param defaultValue the value to return if this name is not found
     * @return the property value OR null if none is found
     * @throws IllegalArgumentException if the defaultValue type does not match the type of the property by name
     */
    public <T> T getPropertyAsType(String name, T defaultValue);

    /**
     * Get a configuration property (setting) from the system, or return
     * (and possibly store) a default value if none is found.
     *
     * @param <T>
     * @param name the property name
     * @param defaultValue the value to return if this name is not found
     * @param setDefaultIfNotFound if this is true and the config value
     * is not found then the default value will be set in the
     * configuration store assuming it is not null.  Otherwise the
     * default value is just returned but not set.
     * @return the property value OR null if none is found
     * @throws IllegalArgumentException if the defaultValue type does not match the type of the property by name
     */
    public <T> T getPropertyAsType(String name, T defaultValue, boolean setDefaultIfNotFound);

    /**
     * Get all currently known configuration settings
     *
     * @return all the configuration properties as a map of name -> value
     */
    public Map<String, String> getAllProperties();

    /**
     * Convenience method - get a configuration property (setting) from
     * the system.
     *
     * @param name the property name
     * @return the property value OR null if none is found
     */
    public String getProperty(String name);

    /**
     * Convenience method - get all configuration properties (settings)
     * from the system.
     *
     * @return all the configuration properties in a properties object (name -> value)
     */
    public Properties getProperties();

    /**
     * Set a configuration property (setting) in the system.
     * Type is not important here since conversion happens automatically
     * when properties are requested.
     *
     * @param name the property name
     * @param value the property value (set this to null to clear out the property)
     * @return true if the property is new or changed from the existing value, false if it is the same
     * @throws IllegalArgumentException if the name is null
     * @throws UnsupportedOperationException if the type cannot be converted to something that is understandable by the system as a configuration property value
     */
    public boolean setProperty(String name, Object value);

}

The most important

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:

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

The most important

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:

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/

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();

    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 {

    public String getSessionId();

    public String getUserId();

    public String getUserEID();

    public boolean isActive();

    public String getServerId();

    public String getOriginatingHostIP();

    public String getOriginatingHostName();

    public String getAttribute(String key);

    public void setAttribute(String key, String value);

    public Map<String, String> getAttributes();

    public void clear();

Benefits over the Legacy 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 comma separated values for you when you request the property as type "Array"
    Code Block
    /* type casting */
    int value = configurationService.getPropertyAsType("some-integer",int.class);
    
    /* Array Parsing */
    String[] values = configurationService.getPropertyAsType("some-array", String[].class);
    
    /* Default Values */
    int value = configurationService.getPropertyAsType("some-integer",1);
    
    /* Default Array Values */
    String[] values = configurationService.getPropertyAsType("some-array",new String[]{"my", "own", "array"});
            

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

 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.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|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/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\]

...