Creating Rice Enabled Applications

Creating a Rice Client Application Project Skeleton

The Kuali Rice source code comes with a script (written in a language called Groovy) which will create a skeleton client application project that bundles Rice. If you do not have Groovy installed on your machine, you will need to download and install it from http://groovy.codehaus.org/

Preparation Steps

To get ready to run the script:

  1. Open a shell window or command prompt window.

  2. Change your current directory to the scripts directory within the Rice source code tree (for example, if you unpacked the source code into a directory named /java/projects/rice, you want to navigate to /java/projects/rice/scripts).

  3. If the Groovy interpreter is not on your command path (entering the command groovy results in an error stating that the command was not found), enter the command: . ./setenv.sh in Unix or setenv.bat in Windows.

  4. Verify that you have Groovy installed by typing the command groovy at the comment line. This should print out the groovy usage message.

Command Syntax

Enter groovy createproject.groovy followed by one or more of the following parameters, separated by spaces:

  • -name defines the name of the project. It must be followed by a space and the desired project name. The project name should consist of letters, numbers, dashes, and underscores only. This parameter is required.

  • -pdir specifies the directory to hold the new project. It must be followed by a space and the directory. A directory named the same as the project name will be created in this directory. If not specified, the directory /java/projects will be used.

  • -rdir specifies the directory containing the Rice project. It must be followed by a space and the directory. If not specified, the directory /java/projects/rice will be used.

  • -mdir specifies the home directory for Maven, which is required to set up the Eclipse project’s class path information. It must be followed by a space and the directory. If not specified, the script will attempt to find Maven using the following sources:

    • An environment variable named M2_HOME

    • An environment variable named m2.home

    • A property named maven.home.directory in the file kuali build.properties in your home directory

  • -sampleapp requests the sample application to be included in the new project. This can serve as an example for building a Rice application. If not specified, the sample application is not included.

  • -standalone requests the client project be set up to be run with a standalone rice server. This sets the default configuration files to containing the necessary settings to connect to standalone rice. The rice url and database properties will still need be updated manually.

Sample Script Execution

groovy createproject.groovy -name MyFirstProject -sampleapp

Further instructions on how to open the project and run it will be printed to the console when the script has finished executing. At this point, you now have a skeleton of a Kuali Rice client application that you can use to begin building your own application. However, before running the application, you will need to create a Rice database (if you’re using the sampleapp, you’ll need to set up the demo database; otherwise, you’ll set up a stripped-down bootstrap database).

The configuration of this application uses a bundled model where the Rice server and client pieces are all being included and loaded by your sample application. This is useful for development purposes since it makes it very easy to get the application running. It is not recommended for an enterprise deployment where you may want to have more than one application integrating with Kuali Rice. In these cases, you would want to install and integrate with a Standalone Rice server. For more information on installing and configuring a standalone server, see the Installation Guide.

Reorder Eclipse Classpath

Once the sample script execution has completed, you will need to import your project into eclipse and reorder the eclipse classpath to account for a change in how the classpath was generated by maven. Navigate to your project properties and select the Order and Export tab from the Java Build Path project property. There will be an entry for JRE System Library at the bottom of the list that should be moved to the very top.

Rice Configuration System

The Rice Configuration System is an XML-based solution which provides capabilities similar to Java property files, but also adds some additional features. The configuration system lets you:

  • Configure keys and values

  • Aggregate multiple files using a single master file

  • Build parameter values from other parameter values

  • Use the parameters in Spring

  • Override configuration values

Configuring Keys and Values

Below is an example of a configuration XML file. Note that the white space (spaces, tabs, and new lines) is stripped from the beginning and end of the values.

<config>
    <param name="client1.location">/home/ubuntu/work/2.0/src/test/clients/TestClient1</param>
    <param name="client2.location">/home/ubuntu/work/2.0/src/test/clients/TestClient2</param>
    <param name="ksb.client1.port">9913</param>
    <param name="ksb.client2.port">9914</param>
    <param name="ksb.testharness.port">9915</param>
    <param name="threadPool.size">1</param>
    <param name="threadPool.fetchFrequency">3000</param>
    <param name="bus.refresh.rate">3000</param>
    <param name="keystore.alias">rice</param>
    <param name="keystore.password">super-secret-pw</param>
    <param name="keystore.file">/home/ubuntu/work/2.0/src/test/resources/keystore</param>
</config>

Here is an example of the Java code required to parse the configuration XML file and convert it into a Properties object:

Config config = new SimpleConfig(configLocations, properties);
config.parseConfig();             

In the sample above, configLocations is a List<String> containing file locations using the standard Spring naming formats (examples: file:/whatever and classpath:/whatever). The variable properties is a Properties object containing the default property values.

Here is an example of retrieving a property value from Java code:

String val = ConfigContext.getCurrentContextConfig().getProperty(“keystore.alias”);

Aggregating Multiple Files

The Rice Configuration System has a special parameter, config.location, which you use to incorporate the contents of another file. Typically, you use this to include parameters that are maintained by system administrators in secure locations. The parameters in the included file are parsed as if they had been in the original file at that place. Here is an example:

<config>
    <param name="config.location">file:/my_secure_dir/my_secure_file.xml</param>
</config>

Building Parameter Values from Other Parameters

Once you have defined a parameter, you can use it in the definition of another parameter. For example:

<config>
    <param name="apple">red delicious</param>
    <param name="taste">yummy yummy</param>
    <param name="apple.taste">${apple} ${taste}</param>
</config>

When this example is parsed, the value of the parameter apple.taste will be set to red delicious yummy yummy.

Using the Parameters in Spring

Because the parameters are converted into a Properties object, you can retrieve the complete list of parameters using this code:

config.getProperties()

You typically use this in Spring to parse a configuration and put its properties in a PropertyPlaceHolderConfigurer so that the parameters are available in the Spring configuration file:

<bean id="config" class="org.kuali.rice.core.config.spring.ConfigFactoryBean">
    <property name="configLocations">
        <list>
            <value>classpath:my-config.xml</value>
        </list>
    </property>
</bean>

<bean id="configProperties"
 class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject" ref="config" />
    <property name="targetMethod" value="getProperties" />
</bean>

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="properties" ref="configProperties" />
</bean>

Once this is complete, the configuration parameters can be used like standard Spring tokens in the bean configurations:

<bean id="dataSource" class="org.kuali.rice.core.database.XAPoolDataSource">
    <property name="transactionManager" ref="jotm" />
    <property name="driverClassName" value="${datasource.driver.name}" />
    <property name="url" value="${datasource.url}" />
    <property name="maxSize" value="${datasource.pool.maxSize}" />
    <property name="minSize" value="${datasource.pool.minSize}" />
    <property name="maxWait" value="${datasource.pool.maxWait}" />
    <property name="validationQuery" value="${datasource.pool.validationQuery}" />
    <property name="username" value="${datasource.username}" />
    <property name="password" value="${datasource.password}" />
</bean>

Initializing the Configuration Context in Rice

The Config object can be injected into the RiceConfigurer that’s configured in Spring and it will initialize the configuration context with those configuration parameters.

This is done as follows:

<bean id="config" class="org.kuali.rice.core.config.spring.ConfigFactoryBean">
    ...
</bean>

<bean id="rice" class="org.kuali.rice.core.config.RiceConfigurer">
    <property name=”rootConfig” ref=”config”/>
</bean>

Overriding Configuration Values

The primary purpose of overriding configuration values is to provide a set of default values in a base configuration file and then provide a separate file that overrides the values that need to be changed. You can also update a parameter value multiple times in the same file. Parameter values can be changed any number of times; the last value encountered while parsing the file will be the value that is retained.

For example, when parsing the file:

<config>
    <param name="taste">yummy yummy</param>
    <param name="taste">good stuff</param>
</config>

The final value of the parameter taste will be good stuff since that was the last value listed in the file.

As another example, when parsing the file:

<config>
    <param name="taste">yummy yummy</param>
    <param name="apple.taste">apple ${taste}</param>
    <param name="taste">good stuff</param>
</config>

The final value of the parameter apple.taste will be apple yummy yummy. This demonstrates that parameters that appear in the value are replaced by the current value of the parameter at that point in the configuration file.

Additionally, you can define certain parameters in such that they won’t override an existing parameter value if it’s already set.

As an example of this, consider the following configuration file:

<config>
    <param name="taste" override=”false”>even yummier</param>
    <param name=”brand.new.param” override=”false”>brand new value</param>

</config>

If this file was loaded into a configuration context that had already parsed our previous example, then it would notice that the taste parameter has already been set. Since override is set to false, it would not override that value with even yummier. However, since brand.new.param had not been defined previously, it’s value would be set.

Data Source and JTA Configuration

The Kuali Rice software require a Java Transaction API (JTA) environment in which to execute database transactions. This allows for creation and coordination of transactions that span multiple data sources. This feature is something that would typically be found in a J2EE application container. However, Kuali Rice is designed in such a way that it should not require a full J2EE container. Therefore, when not running the client or web application inside of an application server that provides a JTA implementation, you must provide one. The default JTA environment that Kuali Rice uses is JOTM. There are other open-source options available, such as Atomikos TransactionsEssentials, and there are also commercial and open source JTA implementations that come as part of an application server (i.e. JBoss, WebSphere, GlassFish).

If installing Rice using the standalone server option and a full Java application server is not being utilized, then the libraries required for JTA will need to be moved to the servlet server which is being used. These libraries have already been retrieved by Maven during project set up; it is a simple matter of moving them from the Maven repository to the libraries directory of the servlet server. Assuming, for instance, that Tomcat is being used, the following files need to be copied from the Maven repository to $TOMCAT_HOME/common/lib:

  • {Maven repository home}/repository/javax/transaction/jta/1.0.1B/jta-1.0.1B.jar

  • {Maven repository home}/repository/jotm/jotm/2.0.10/jotm-2.0.10.jar

  • {Maven repository home}/repository/jotm/jotm_jrmp_stubs/2.0.10/jotm_jrmp_stubs-1.0.10.jar

  • {Maven repository home}/repository/xapool/xapool/1.5.0-patch3/xapool-1.5.0-patch3.jar

  • {Maven repository home}/repository/howl/howl-logger/0.1.11/howl-logger-0.1.11.jar

  • {Maven repository home}/repository/javax/resource/connector-api/1.5/connector-api-1.5.jar

  • {Maven repository home}/repository/javax/resource/connector/1.0/connector-1.0.jar

  • {Maven repository home}/repository/org/objectweb/carol/carol/2.0.5/carol-2.0.5.jar

Additionally, the {Rice project home}config/jotm/carol.properties configuration file needs to be moved to $TOMCAT_HOME/common/classes, this time from the built Rice project.

Configuring JOTM

Configure the JOTM transaction manager and user transaction objects as Spring beans in your application’s Spring configuration file. Here is an example:

<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean">
    <property name="defaultTimeout" value=”3600”/>
</bean>
    
<alias name="jotm" alias="jtaTransactionManager"/>
<alias name="jotm" alias="jtaUserTransaction"/>

You can use these beans in the configuration of Spring’s JTA transaction manager and the Rice configurer. This configuration might look like the following:

<bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="userTransaction">
        <ref local="userTransaction" />
    </property>
    <property name="transactionManager">
        <ref local="jtaTransactionManager" />
    </property>
</bean>    

<bean id="rice" class="org.kuali.rice.core.config.RiceConfigurer">
    <property name="transactionManager" ref="jtaTransactionManager" />    
    <property name="userTransaction" ref="jtaUserTransaction" />
    ...
</bean>

Configuring Transactional Data Sources

JTA requires that the datasources that are used implement the XADataSource interface. Some database vendors, such as Oracle, have pure XA implementations of their datasources. However, internally to Rice, we use wrappers on plain datasources using a library called XAPool. When configuring transactional data sources that will be used within JOTM transactions, you should use the org.kuali.rice.core.database.XAPoolDataSource class provided with Rice. Here is an example of a Spring configuration using this data source implementation:

<bean id="myDataSource" class="org.kuali.rice.core.database.XAPoolDataSource">
    <property name="transactionManager" ref="jtaTransactionManager" />
    <property name="driverClassName" value="${datasource.driver.name}" />
    <property name="url" value="${datasource.url}" />
    <property name="maxSize" value="${datasource.pool.maxSize}" />
    <property name="minSize" value="${datasource.pool.minSize}" />
    <property name="maxWait" value="${datasource.pool.maxWait}" />
    <property name="validationQuery" value="${datasource.pool.validationQuery}" />
    <property name="username" value="${datasource.username}" />
    <property name="password" value="${datasource.password}" />
</bean>

Configuring Non-Transactional Data Sources

When using the built-in instance of the Quartz scheduler that Rice creates, you will need to inject a non-transactional data source into the RiceConfigurer in addition to the JTA transactional instance. This is to prevent deadlocks in the database and is required by the Quartz software (the Quartz web site has an FAQ entry with more details on the problem). Here is an example of a non-transactional data source configuration:

<bean id="nonTransactionalDataSource"
 class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${datasource.driver.name}"/>
    <property name="url" value="${datasource.url}"/>
    <property name="maxActive" value="${datasource.pool.maxActive}"/>
    <property name="minIdle" value="7"/>
    <property name="initialSize" value="7"/>
    <property name="validationQuery" value="${datasource.pool.validationQuery}"/>
    <property name="username" value="${datasource.username}" />
    <property name="password" value="${datasource.password}" />
    <property name="accessToUnderlyingConnectionAllowed"
 value="${datasource.dbcp.accessToUnderlyingConnectionAllowed}"/>
</bean>

You need to either inject this non-transactional data source into the Quartz SchedulerFactory Spring bean (if you are explicitly defining it) or into the rice bean in the Spring Beans config file as follows:

<bean id="rice" class="org.kuali.rice.config.RiceConfigurer">
    ...
    <property name="nonTransactionalDataSource" ref="nonTransactionalDataSource" />
    ...
</bean>