Change live application language/resource in Oracle ADF, Change XML Resource file at runtime

Sharing is Caring

Hello All

I have posted about using external XML file as List resource bundle earlier, the aim of the resource file is to read application static text from some source so that we can change that without compiling and redeploying the application

Next requirement is to change application language, sometimes we need to support multiple languages in ADF application and it requires a change in all static text so for this I am going to use separate XML resource file for different language and in this post, I’ll show that how to update resource file in a live running application

Here I am using the same sample application and after adding resource for the English language, added a list on the page to select a language

created a value change listener in managed bean for this list

<af:selectOneChoice label="Select Language" id="soc1" autoSubmit="true"
                                    valueChangeListener="#{ResourceManagerBean.changeLanguageVCE}"
                                    contentStyle="width:100px;">
                    <af:selectItem label="English" value="English" id="si1"/>
                    <af:selectItem label="French" value="French" id="si2"/>
                    <af:selectItem label="Dutch" value="Dutch" id="si3"/>
                </af:selectOneChoice>

Here ResourceManagerBean is a session scope bean, Initialized a session scope variable that holds the path of the resource file and on value change listener of choice list I’ll change the path of resource file on basis of the selected language

In this demo, I am using 3 XML resource files for 3 different languages (English, French, and Dutch)
The user will select any language from the list and resource values will be read from respective resource file after a page refresh and clearing resource cache

Managed Bean Code-

import java.io.Serializable;

import java.util.ResourceBundle;

import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;

import javax.servlet.http.HttpSession;

public class ResourceManagerBean implements Serializable {

//String variable to hold locale
private String appLocale;

public void setAppLocale(String appLocale) {
this.appLocale = appLocale;
}

public String getAppLocale() {
return appLocale;
}
public ResourceManagerBean() {
//Take a session variable to put resource file path
FacesContext fc = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) fc.getExternalContext().getSession(true);
session.setAttribute("resName", "D://Resource_En.xml");
}

/**Method to forcefully refresh page
 */
protected void refreshPage() {

FacesContext fctx = FacesContext.getCurrentInstance();
String page = fctx.getViewRoot().getViewId();
ViewHandler ViewH = fctx.getApplication().getViewHandler();
UIViewRoot UIV = ViewH.createView(fctx, page);
UIV.setViewId(page);
fctx.setViewRoot(UIV);

}

/**Method to change app language by changing locale and XML resource file of application
 * @param vce
 */
public void changeLanguageVCE(ValueChangeEvent vce) {
if (vce.getNewValue() != null) {
if ("English".equalsIgnoreCase(vce.getNewValue().toString())) {
//Change application locale to English
setAppLocale("en");
FacesContext fc = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) fc.getExternalContext().getSession(true);
session.setAttribute("resName", "D://Resource_En.xml");

} else if ("French".equalsIgnoreCase(vce.getNewValue().toString())) {
//Change application locale to French
setAppLocale("fr");
FacesContext fc = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) fc.getExternalContext().getSession(true);
session.setAttribute("resName", "D://Resource_fr.xml");

} else if ("Dutch".equalsIgnoreCase(vce.getNewValue().toString())) {
//Change application locale to Dutch (Netherland)
setAppLocale("nl");
FacesContext fc = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) fc.getExternalContext().getSession(true);
session.setAttribute("resName", "D://Resource_nl.xml");

}
//Clear Resource Bundle cache to load Resource.java file again
ResourceBundle bundle = ResourceBundle.getBundle("listresourcebundle.view.bundle.Resource");
bundle.clearCache();

//Refresh Page after changing resource file
refreshPage();
}
}
}

A small change in Resource.java file, Now it reads Resource file path from session scope variable that is initialized in the managed bean

Resource.java file-

import java.io.File;

import java.util.ListResourceBundle;

import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;

import javax.faces.application.Application;
import javax.faces.context.FacesContext;

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 = 

    resolvEl("#{sessionScope.resName}");

//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 {
System.out.println("Resource path is- " + Res_path);
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();
}

public String resolvEl(String data) {
FacesContext fc = FacesContext.getCurrentInstance();
Application app = fc.getApplication();
ExpressionFactory elFactory = app.getExpressionFactory();
ELContext elContext = fc.getELContext();
ValueExpression valueExp = elFactory.createValueExpression(elContext, data, Object.class);
Object expVal = valueExp.getValue(elContext);
String Message = "D:\Resource_En.xml";
if (expVal != null) {
Message = expVal.toString();
}

return Message;
}
}

Next step is to refer page locale from the managed bean, Open the page and in structure window select f:view tag (container tag for all components used on the page)

Refer locale property to bean variable

All Done 🙂 Run and Check Application

Sample ADF Application (JDeveloper 12.1.3)- Download
Cheers 🙂 Happy Learning

Related Posts

0 thoughts on “Change live application language/resource in Oracle ADF, Change XML Resource file at runtime”

Leave a Reply

Your email address will not be published. Required fields are marked *