Recipe2.7.Accessing Message Resources from a Database


Recipe 2.7. Accessing Message Resources from a Database

Problem

You want to store all labels, messages, and other static text in a database rather than a properties file, while still being able to access the values using the bean:message tag.

Solution

  1. Download the OJBMessageResources distribution from http://prdownloads.sourceforge.net/struts/ojb-message-resources.zip?download.

  2. Extract the ZIP file into a directory on your computer.

  3. Copy the ojb-msg-res.jar file from the ojb-message-resources/dist folder into your application's WEB-INF/lib folder.

  4. Copy the properties, XML, and DTD files from the ojb-message-resources/config folder to your application's src folder. When you build your application, these files must be copied to the WEB-INF/classes folder.

  5. Create the tables to hold the Objec Relational Bridge (OJB) metadata tables. OJB uses these tables to keep internal mapping information. Example 2-12 shows the data definition SQL that creates these tables for the MySQL database. These statements for other databases are included with the OJB distribution.

Example 2-12. OJB metadata DDL (MySQL)
CREATE TABLE ojb_dlist (   ID int NOT NULL default '0',   SIZE_ int default NULL,   PRIMARY KEY  (ID) ) TYPE=MyISAM; CREATE TABLE ojb_dlist_entries (   ID int NOT NULL default '0',   DLIST_ID int NOT NULL default '0',   POSITION_ int default NULL,   OID_ longblob,   PRIMARY KEY  (ID) ) TYPE=MyISAM; CREATE TABLE ojb_dmap (   ID int NOT NULL default '0',   SIZE_ int default NULL,   PRIMARY KEY  (ID) ) TYPE=MyISAM; CREATE TABLE ojb_dmap_entries (   ID int NOT NULL default '0',   DMAP_ID int NOT NULL default '0',   KEY_OID longblob,   VALUE_OID longblob,   PRIMARY KEY  (ID) ) TYPE=MyISAM; CREATE TABLE ojb_dset (   ID int NOT NULL default '0',   SIZE_ int default NULL,   PRIMARY KEY  (ID) ) TYPE=MyISAM; CREATE TABLE ojb_dset_entries (   ID int NOT NULL default '0',   DLIST_ID int NOT NULL default '0',   POSITION_ int default NULL,   OID_ longblob,   PRIMARY KEY  (ID) ) TYPE=MyISAM; CREATE TABLE ojb_hl_seq (   TABLENAME varchar(175) NOT NULL default '',   FIELDNAME varchar(70) NOT NULL default '',   MAX_KEY int default NULL,   GRAB_SIZE int default NULL,   PRIMARY KEY  (TABLENAME,FIELDNAME) ) TYPE=MyISAM; CREATE TABLE ojb_lockentry (   OID_ varchar(250) NOT NULL default '',   TX_ID varchar(50) NOT NULL default '',   TIMESTAMP_ decimal(10,0) default NULL,   ISOLATIONLEVEL int default NULL,   LOCKTYPE int default NULL,   PRIMARY KEY  (OID_,TX_ID) ) TYPE=MyISAM; CREATE TABLE ojb_nrm (   NAME varchar(250) NOT NULL default '',   OID_ longblob,   PRIMARY KEY  (NAME) ) TYPE=MyISAM; CREATE TABLE ojb_seq (   TABLENAME varchar(175) NOT NULL default '',   FIELDNAME varchar(70) NOT NULL default '',   LAST_NUM int default NULL,   PRIMARY KEY  (TABLENAME,FIELDNAME) ) TYPE=MyISAM;

  1. Create the table to hold the message resources data using the SQL DDL shown in Example 2-13.

Example 2-13. MessageResources DDL
create table application_resources (    subApp            varchar(100)     not null,   bundleKey         varchar(100)     not null,   locale            varchar(10)      not null,   msgKey            varchar(255)     not null,   val               varchar(255),   Primary Key(     subApp,     bundleKey,     locale,     msgKey   ) );

  1. Populate the table with your message resources. Example 2-14 shows an easy means of loading the table using SQL.

Example 2-14. SQL to load message resources table
insert into application_resources (      subApp, bundleKey, locale, msgKey, val )    values ('', '', '', 'label.index.title',            'Struts Cookbook'); insert into application_resources (      subApp, bundleKey, locale, msgKey, val )    values ('', '', 'fr', 'label.index.title',            'Struts Livre de Cuisine');

  1. Change the Struts configuration file to use the OJBMessageResources factory:

    <message-resources     factory="org.apache.struts.util.OJBMessageResourcesFactory"    parameter="." />

  2. Change the repository.xml in your WEB-INF/classes folder (copied over in step 4) to use the database connection properties specific to your database. Example 2-15 demonstrates a configuration for a MySQL database.

Example 2-15. OJB connection descriptor for MySQL
<jdbc-connection-descriptor      platform="MySQL"      jdbc-level="2.0"      driver="com.mysql.jdbc.Driver"      protocol="jdbc"      subprotocol="mysql"      dbalias="//localhost:3306/test"      username="user"      password="pass" />

Discussion

The Struts MessageResources facility manages static text such as error messages, field labels, table headers, and window titles. With this facility, the text is stored as name/value pairs in one or more .properties files known as resource bundles; the name is a logical key and the value is the text to display. If your application needs to be localized for a particular language and country, then you create a new properties file. You associate the file with the particular locale (language and country) by adding a suffix composed of a language and country code for the particular locale. For example, the MessageResources.properties file for French Canadian users would be MessageResources_fr_CA.properties. The properties in the localized file contain values specific to the locale. This approach of localizing resources is specified by Java itself.

More details, including a list of language and country codes, can be found at http://java.sun.com/j2se/1.4.2/docs/guide/intl/locale.doc.html.


This facility works well for most small to medium-sized applications. However, you may want to store the text using a more manageable persistent means such as a database. While Struts does not support this out-of-the-box, it does support it through extension. Behind the scenes, Struts uses an implementation of the MessageResourcesFactory to create the MessageResources object that is stored in the servlet context at runtime. You can provide a custom implementation of the Struts MessageResourcesFactory and then declare that implementation in your Struts configuration file:

<message-resources    factory="com.foo.CustomMessageResourcesFactory"   parameter=" moduleName . bundleKey " />

The parameter attribute specifies the Struts module name and bundle key (bundle name) that the message resources factory creates messages for.

So, you could create your own message resources factory that reads the resources from a database. Thankfully, the grunt work of creating such an extension has been done! James Mitchell, a long-time Struts committer, created the OJBMessageResources implementation. This set of classes leverages the object-relational mapping framework OJB to provide an easy-to-use database-driven MessageResources implementation.

If you are unfamiliar with OJB, don't let that dissuade you from this Solution. You don't need to know anything about OJB to use the OJBMessageResources. OJB is simply used under the covers to map the relational data to the object data. If you use the table schema specified in the Solution, no additional changes are needed to map the data. However, if you want to use a different schema, you can change the mappings in the OJB XML-based configuration files to suit your needs. You will not need to make any changes to the actual Java code that implements the MessageResourcesFactory. OJBMessageResources is well documented and comes with a step-by-step installation and configuration README file. The Solution above is derived from those instructions.

To use OJBMessageResources most effectively, it helps to understand how the database schema maps to the object data. First, the schema only requires creation of a single table to hold the message resources (step 6 in the Solution). Using a single table simplifies the data mapping. Table 2-2 describes the columns that make up this table and how they are used in Struts.

Table 2-2. OJBMessageResources schema

Column name

Corresponding Struts concept

Notes and examples

subApp

Module prefix

Not null. Use an empty String("") to represent the default module.

bundleKey

Key to locate a set of message resources when using multiple sets. This value must match the value of the key attribute of the message-resources element in the Struts configuration file. This value corresponds to the value for the bundle attribute in the Struts tags (e.g., bean:message bundle="labels"

Not null. Use an empty String to represent the default key. Otherwise, the name is a logical value such as "labels," "headers," and "errors."

Locale

The locale code representing the locale of the message. This value is a combination of the two-letter language code and two-letter country code.

Not null. Use an empty String to represent the default (server's) locale. Examples of values are "en_US" for English/United States and "fr" for French.

msgKey

The message name used to look up the message. This value will be the same for all locales. This value is the same as the left-hand side of a property in a .properties file. The value of this column corresponds to the value for the key attribute in the Struts tags that retrieve values from MessageResources.

Not null, and should never be empty. A key value might look something like "title.hello.world".

val

Value corresponding to the msgKey. This is the localized text and corresponds to the right-hand side of a property. This is the value that will be retrieved and displayed by a Struts tag.

Can be null. This is the text that will be displayed on the page. For example, "Hello, World!"


Keep in mind that while OJBMessageResources uses a single database table to hold all message resources, each resource set must still be configured in the struts-config.xml with a message-resources element. In other words, you will need to have a message-resource element for each resource set distinguished by a bundleKey and subApp. See Recipe 2.6 for more details.

See Also

Recipe 2.6 describes how to configure Struts to use multiple message resource bundles. Chapter 14 has additional recipes related to internationalizing Struts applications.

OJB is a project under the Apache umbrella. Complete information on OJB can be found online at http://db.apache.org/ojb.

An effort is underway to factor out the Struts message resources into a reusable set of common classes. The Commons Resources project, http://jakarta.apache.org/commons/sandbox/resources/, will provide an implementation of message resources backed by properties files as well as other persistence mechanisms including OBJ, Hibernate, Torque, and straight JDBC. It's anticipated that a future version of Struts will deprecate the internal message resources implementation and in favor of Commons Resources.



    Jakarta Struts Cookbook
    Jakarta Struts Cookbook
    ISBN: 059600771X
    EAN: 2147483647
    Year: 2005
    Pages: 200

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net