Versions Compared

Key

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

...

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

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

Best Practices:

Tip

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)

Tip

Objectifying Configuration... If you Configuration is too complex, then it probably should be an Object Model

In Comparison with Legacy Configuration

Legacy Configuration

Wiki Markup
_\[dspace\]/config/moduledspace.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. 

Default Configuration

Wiki Markup
_\[addon.jar\]/config/\[
prefix
service\].cfg&nbsp;_

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

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

...

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.

...

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.

Test Driven Development

...

 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.

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

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.\[[3]\|http://en.wikipedia.org/wiki/

...

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.\[[3]\|http://en.wikipedia.org/wiki/Test-driven_development#cite_note-Newkirk-2\]

ACCESSING REGISTERED SERVICES

DEFINING SERVICES
SPRING CONFIGURATION
PROTOTYPES VS SINGLETONS
Example: Creating a Comments Service
Ac dolor ac adipiscing amet bibendum nullam, massa lacus molestie ut libero nec, diam et, pharetra sodales eget, feugiat ullamcorper id tempor eget id vitae. Mauris pretium eget aliquet, lectus tincidunt.
The IMPLEMENTATION
TEST DRIVEN DEVELOPMENT

Using the Service Manager Testing Framework

DSpaceAbstractRequestTest

This is an abstract class which makes it easier to test execution of your service within a DSpace "Request Cycle" and includes an automatic request wrapper around every test method which will start and end a request, the default behavior is to end the request with a failure which causes a rollback and reverts the storage to the previous values

Code Block

public abstract class DSpaceAbstractRequestTest extends DSpaceAbstractKernelTest {

    /**
     * @return the current request ID for the current running request
     */
    public String getRequestId() {
        return requestId;
    }

    @BeforeClass
    public static void initRequestService() {
        _initializeRequestService();
    }

    @Before
    public void startRequest() {
        _startRequest();
    }

    @After
    public void endRequest() {
        _endRequest();
    }

    @AfterClass
    public static void cleanupRequestService() {
        _destroyRequestService();
    }

}

DSpaceAbstractKernelTest

This is an abstract class which makes it easier to test things that use the DSpace Kernel, this will start and stop the kernel at the beginning of the group of tests that are in the junit test class which extends this

Code Block

public abstract class DSpaceAbstractKernelTest extends DSpaceAbstractTest {

    @BeforeClass
    public static void initKernel() {
        _initializeKernel();
        assertNotNull(kernelImpl);
        assertTrue(kernelImpl.isRunning());
        assertNotNull(kernel);
    }

    @AfterClass
    public static void destroyKernel() {
        _destroyKernel();
    }

    /**
     * Test method for {@link org.dspace.kernel.DSpaceKernelManager#getKernel()}.
     */
    @Test
    public void testKernelIsInitializedAndWorking() {
        assertNotNull(kernel);
        assertTrue(kernel.isRunning());
        DSpaceKernel k2 = new DSpaceKernelManager().getKernel();
        assertNotNull(k2);
        assertEquals(kernel, k2);
    }

}

Developing with DSpace

Architectural Introduction

Maven Archetype

Project Generation

Maven Module Wiring

Dependencies

Tiers

Persisitence

Business

Application

Tools

Maven

Jar Projects

 Dependencies

Inheritance

modularity

War Projects

overlays

modularity

Spring

ServiceManager

Core Services

ConfigurationService

Configuration via Spring vs. ConfigurationService

DatabaseService

Opening Doors to Persistence Frameworks

DAO Repositories

Defining, Replacing and Augmenting Storage

Whats a Service?

Defining and Replacing Business Services

Creating Your Own Services

Webapplications

XMLUI / Cocoon

JSPUI (WebMVC)

Example

Facebook Authentication for DSpace

Spring Security

OAuth 2.0 for Spring Security

Facebook Authentication

Implementation

Spring Security Authenticator

Authentication Service

...

Application Frameworks (Spring, Guice, etc.)

Similar to Standalone Applications, but you can use your framework to instantiate an org.dspace.utils.DSpace object.

...


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

Web Applications

In web applications, the kernel can be started and accessed through the use of Servlet Filter/ContextListeners which are provided as part of the DSpace 2 utilities. Developers don't need to understand what is going on behind the scenes and can simply write their applications and package them as webapps and take advantage of the services which are offered by DSpace 2.

Providers and Plugins

For developers (how we are trying to make your lives easier): The DS2 ServiceManager supports a plugin/provider system which is runtime hot-swappable. The implementor can register any service/provider bean or class with the DS2 kernel ServiceManager. The ServiceManager will manage the lifecycle of beans (if desired) and will instantiate and manage the lifecycle of any classes it is given. 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 service if desired. The goal of this system is to allow DS2 to be extended without requiring any changes to the core codebase or a rebuild of the code code.

Activators

Developers can provide an activator to allow the system to startup their service or provider. It is a simple interface with 2 methods which are called by the ServiceManager to startup the provider(s) and later to shut them down. These simply allow a developer to run some arbitrary code in order to create and register services if desired. It is the method provided to add plugins directly to the system via configuration as the activators are just listed in the configuration file and the system starts them up in the order it finds them.

Provider Stacks

Utilities are provided to assist with stacking and ordering providers. Ordering is handled via a priority number such that 1 is the highest priority and something like 10 would be lower. 0 indicates that priority is not important for this service and can be used to ensure the provider is placed at or near the end without having to set some arbitrarily high number.

Core Services

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>

Test-driven_development#cite_note-Newkirk-2\]

ACCESSING REGISTERED SERVICES

DEFINING SERVICES
SPRING CONFIGURATION
PROTOTYPES VS SINGLETONS
Example: Creating a Comments Service
Ac dolor ac adipiscing amet bibendum nullam, massa lacus molestie ut libero nec, diam et, pharetra sodales eget, feugiat ullamcorper id tempor eget id vitae. Mauris pretium eget aliquet, lectus tincidunt.
The IMPLEMENTATION
TEST DRIVEN DEVELOPMENT

Using the Service Manager Testing Framework

DSpaceAbstractRequestTest

This is an abstract class which makes it easier to test execution of your service within a DSpace "Request Cycle" and includes an automatic request wrapper around every test method which will start and end a request, the default behavior is to end the request with a failure which causes a rollback and reverts the storage to the previous values

Code Block

public abstract class DSpaceAbstractRequestTest extends DSpaceAbstractKernelTest {

    /**
     * @return the current request ID for the current running request
     */
    public String getRequestId() {
        return requestId;
    }

    @BeforeClass
    public static void initRequestService() {
        _initializeRequestService();
    }

    @Before
    public void startRequest() {
        _startRequest();
    }

    @After
    public void endRequest() {
        _endRequest();
    }

    @AfterClass
    public static void cleanupRequestService() {
        _destroyRequestService();
    }

}

DSpaceAbstractKernelTest

This is an abstract class which makes it easier to test things that use the DSpace Kernel, this will start and stop the kernel at the beginning of the group of tests that are in the junit test class which extends this

Code Block

public abstract class DSpaceAbstractKernelTest extends DSpaceAbstractTest {

    @BeforeClass
    public static void initKernel() {
        _initializeKernel();
        assertNotNull(kernelImpl);
        assertTrue(kernelImpl.isRunning());
        assertNotNull(kernel);
    }

    @AfterClass
    public static void destroyKernel() {
        _destroyKernel();
    }

    /**
     * Test method for {@link org.dspace.kernel.DSpaceKernelManager#getKernel()}.
     */
    @Test
    public void testKernelIsInitializedAndWorking() {
        assertNotNull(kernel);
        assertTrue(kernel.isRunning());
        DSpaceKernel k2 = new DSpaceKernelManager().getKernel();
        assertNotNull(k2);
        assertEquals(kernel, k2);
    }

}

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

...

Further Reading and Resources:

...