You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by Apache Wiki <wi...@apache.org> on 2005/05/11 10:31:38 UTC

[Struts Wiki] Update of "DatabaseMessageResourcesHowto" by AndréWegmüller

Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Struts Wiki" for change notification.

The following page has been changed by AndréWegmüller:
http://wiki.apache.org/struts/DatabaseMessageResourcesHowto

New page:
This document shows you how to load Struts message resources from a database instead from the default .properties file. Here's what you will learn:

 * Setup the database
 * Setup a custom message resources factory
 * Retrieve message resources data from a database
 * Reload message resources without redeploying your web-application

I use EJB and Oracle stored procedures in my example, but you may choose another way to retrieve your message data from a database.

=== Setup the database ===
First of all, we need a database-table, that stores our message resource records. Here's the table that i've used in my example. It has four text columns for different languages (german, french, italian, english). The column smr_key is the primary key.

{{{
STRUTS_MESSAGE_RESOURCES
-----------------------------------
smr_key        varchar2(100)     PK
smr_text_de    varchar2(1000)
smr_text_fr    varchar2(1000)
smr_text_it    varchar2(1000)
smr_text_en    varchar2(1000)
}}}

=== Setup a custom message resources factory ===
Struts has a very flexible mechanism that allows you, to implement your own mechanism to load message resources from any source. In this example the source is a database. First we need to write two classes:

 * DBMessageResourcesFactory
 * DBMessageResources

==== DBMessageResourcesFactory ====
There's nothing special about this one. It just gives you an instance of our custom message resources.
{{{
package ch.trexx.struts;

import org.apache.struts.util.MessageResources;
import org.apache.struts.util.MessageResourcesFactory;

public class DBMessageResourcesFactory extends MessageResourcesFactory {

	/* (non-Javadoc)
	 * @see org.apache.struts.util.MessageResourcesFactory#createResources(java.lang.String)
	 */
	public MessageResources createResources(String config) {
		return new DBMessageResources(this, config);
	}
}
}}}

==== DBMessageResources ====
In this class we implement our connect to the database, that loads the message resources. In my example i use an EJB. You may choose another way to retrieve your data from the database (for instance JDBC).

{{{
package ch.trexx.struts;

import java.util.HashMap;
import java.util.Locale;

import org.apache.log4j.Logger;
import org.apache.struts.util.MessageResources;
import org.apache.struts.util.MessageResourcesFactory;

import ch.trexx.ejb.SBDatabase;
import ch.trexx.ejb.SBDatabaseUtil;
import ch.trexx.ejb.Constants;

/**
 * Lädt die MessageResources über ein Bean aus der Datenbank anstatt
 * aus den normalen Textfiles.
 * @author wegmuelleran
 */
public class DBMessageResources extends MessageResources {

    private final static Logger logger = Logger.getLogger(DBMessageResources.class);

    /**
     * Ist ein Key in einer bestimmten Sprache nicht vorhanden wird
     * der Key der Default Locale zurückgegeben.
     */
    private static final Locale DEFAULT_LOCALE = new Locale(
            Constants.DEFAULT_LANGUANGE, Constants.DEFAULT_COUNTRY);

    private HashMap appText = null;
    
    /**
     * Lädt die Applikationstexte.
     */
    private void loadAppText() {
        try {
            SBDatabaseLocal sbDatabase = SBDatabaseUtil.getLocalHome().create();
            appText = sbDatabase.getAppText();
            logger.info("MessageResources successfully reloaded");
        } catch (Exception e) {
            logger.warn("MessageResources reload failed");
        }
    }
    
    /**
     * Struts initialisiert die Message Resources wenn die init() Methode des
     * ActionServlets aufgerufen wird. Das ActionServlet sorgt dafür, dass die
     * Init-Methode in regelmässigen Abständen aufgerufen wird.
	 * @param factory
	 * @param config
	 */
	public DBMessageResources(MessageResourcesFactory factory, String config) {
		super(factory, config);
        loadAppText();
	}
    
	/* (non-Javadoc)
	 * @see org.apache.struts.util.MessageResources#getMessage(java.util.Locale, java.lang.String)
	 */
	public String getMessage(Locale locale, String key) {
        String message;
        if (appText == null) {
        	message = "[resources not loaded]";
        } else if (appText.containsKey(key)) {
            HashMap text = (HashMap) appText.get(key);
            message = (String) text.get(locale);
            if (message == null) {
            	message = (String) text.get(DEFAULT_LOCALE);
            }
        } else {
            message =  "[key " + key + " is undefined]";
        }
        return message;
    }
}
}}}

Struts calls the factory method createResources only once when you (re-)deploy your application, so you don't have to build a caching mechanism. It took me more time to figure out how to reload the resources without redeploying the whole application. But i will explain that later.

The constructor of DBMessageResources calls the method loadAppText. loadAppText calls an EJB method that returns a nested HashMap containing the database records. The HashMap has the following structure:

{{{
HashMap(
'my.text' => HashMap('de' => 'my german text',
                     'fr' => 'my french text',
                     'it' => 'my italian text',
                     'en' => 'my english text'),
'my.message' => HashMap('de' => 'a german message',
                        'fr' => 'a french message',
                        'it' => 'a italian message',
                        'en' => 'a english message'),
...
)
}}}

==== web.xml ====
You'll have to reference our new message factory in the web.xml. In the action-servlet configuration we add an additional init-param element. The web.xml should look like this afterwards:
{{{
<servlet>
    <servlet-name>action</servlet-name>
    <display-name>DuplexWeb</display-name>
    <servlet-class>ch.trexx.struts.ActionServlet</servlet-class>
    <init-param>
        <param-name>config</param-name>
        <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <init-param>
        <param-name>factory</param-name>
        <param-value>ch.trexx.struts.DBMessageResourcesFactory</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
}}}

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org