Follow by Email

Monday, 23 January 2017

Using external XML file as list resource bundle in ADF Application


Hello All

In this post I am talking about using external XML file as list resource bundle in ADF Application

Using this approach we need not to hard code component's label and messages , all labels and messages will be read from XML file and no need to open application to change any resource , In short we can update resources without compiling and redeploying application



A resource bundle contains a number of named resources, where the data type of the named resources is String. Resource bundles can be either Java classes, property files, or XLIFF (XML Localization Interchange File Format ) files.

Let's implement this, Created model using Departments table of HR Schema


Right click on viewController project and go to properties , Select Resource Bundle, Change default project bundle name to listresourcebundle.view.bundle.Resource and check Automatically Synchronize Bundle checkbox



Now click on Ok button of Project Properties dialog and click yes on the popup dialog to change bundle name


After changing default resource bundle name , Open faces-config.xml file (Under WEB-INF Folder)

Go to Application tab and add a line in Resource Bundle Section, In Base Name put the whole bundle name and in Var Name use any string that will be further used to fetch resource values 


Create a page in viewController project and drop Departments viewObject as af:table on page and to create Resource Bundle Java class select any column of af:table and Select Text Resource in Header Text property


You can see a Resource.java class in created in viewController project


Now create List Resource XML file in this format


<?xml version="1.0" encoding="windows-1252" ?>
<bundle>
<label>
 <key>RES.1</key>
 <value>Department Id</value>
</label>
<label>
 <key>RES.2</key>
 <value>Department Name</value>
</label>
<label>
 <key>RES.3</key>
 <value>Manager Id</value>
</label>
<label>
 <key>RES.4</key>
 <value>Location Id</value>
</label>
</bundle>

Saved this file as Resource_En.xml in D drive of my system, Now see the code of Resource.java file to process and read resource values from this XML file
The java.util.ListResourceBundle class manages resources in a name and value array. Each java.util.ListResourceBundle class is contained within a Java class file


package listresourcebundle.view.bundle;

import java.io.File;

import java.util.ListResourceBundle;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class Resource extends ListResourceBundle {
    
    //Path to XML Resource File
    private String Res_path = "D://Resource_En.xml";
    
    //Initialize an Object Array to hold label and key values
    public Resource() {
        for (int i = 0; i < 5000; i++) {
            contents[i][0] = "";
            contents[i][1] = "";
        }
    }

    private static final Object[][] contents = new Object[5000][2];

    /**Method to process XML file and get key and value of resource and put that in array
     * @return
     */
    public Object[][] getContents() {
        try {

            File file = new File(Res_path);
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(file);
            doc.getDocumentElement().normalize();
            NodeList nList = doc.getElementsByTagName("label");

            for (int temp = 0; temp < nList.getLength(); temp++) {
                Node nNode = nList.item(temp);
                if (nNode.getNodeType() == Node.ELEMENT_NODE) {

                    Element eElement = (Element) nNode;
                    contents[temp][0] = getTagValue("key", eElement);
                    contents[temp][1] = getTagValue("value", eElement);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return contents;
    }

    private static String getTagValue(String sTag, Element eElement) {
        NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
        Node nValue = nlList.item(0);
        return nValue.getNodeValue();
    }
}

Now configuration part is done and to apply resources in page , Select column and go to header text property and from expression builder select var name from Faces' Resource Bundles and put respective key in single quote like this


Repeat this step for all columns


Now run and check application, All labels are fetched from XML file


Sample ADF Application (Jdeveloper 12.1.3)- Download
Cheers :) Happy Learning

8 comments :

  1. Hello. In which cases is it nessesary to populate labels from external xml?

    ReplyDelete
    Replies
    1. Not for any specific case but you can manage resources without touching application

      Delete
    2. This comment has been removed by the author.

      Delete
    3. Nice blog Ashish.
      This usecase is really helpful in case of internalization (I18N). Based on logged in country pick the resource bundle. Your application labels will be rendered in that specific language.

      Delete
  2. Hi Ashish,
    Thanks for your post. I applied it and its working fine.
    I have a issue, in my application there are some LOV's for which its columns name (with in the LOV popup) are fetching from UI Hints > Label. I would like to use the same external XML file for these LOV col label.

    Thanks in anticipation
    neeraj

    ReplyDelete
    Replies
    1. In same way set resource bundle file path in model properties too, create same java file in model project then set resource key in label prperty in UI hints

      Delete
    2. tried the same but not getting the result , currently facing 3 issue
      1) Resource.java file in not getting created autometicaly (created manualy )
      2) where to set variable name for bundle name as it was done in faces-config (Base Name put the whole bundle name and in Var Name use any string that will be further used to fetch resource values )
      3) In UI Hint > lable in which option to set bundle key (#{BundleKey['RES.1']}) Show resource value or select text resource

      Delete
    3. Hi Neeraj

      1. You need to create that manually
      2. No, In model project propeties as previously done for viewController project
      3. Goto--> UI hints--> Put Key in Label field--> Goto source and put key in ResId field

      Ashish

      Delete