|
Recipe 2.7. Accessing Message Resources from a DatabaseProblemYou 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
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;
Example 2-13. MessageResources DDLcreate 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 ) );
Example 2-14. SQL to load message resources tableinsert 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');
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" /> DiscussionThe 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.
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.
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 AlsoRecipe 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. |
|