Hello All
I have posted about using external XML file as List resource bundle earlier , the aim of resource file is to read application static text from some source so that we can change that without compiling and redeploying application
Next requirement is to change application language , sometimes we need support multiple langauge in ADF application and it requires 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 same sample application and after adding resource for English language , added a list on page to select 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 resource file and on value change listener of choice list I'll change path of resource file on basis of selected language
In this demo I am using 3 XML resource files for 3 different languages (English, French and Dutch)
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(); } } }
Small change in Resource.java file , Now it reads Resource file path from session scope variable that is initialized in 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 managed bean , Open page and in structure window select f:view tag (container tag for all components used on page)
Refer locale property to bean variable
All Done :) Run and Check Application
Sample ADF Application (Jdeveloper 12.1.3)- Download
Cheers :) Happy Learning
its helpful, Thanks
ReplyDeleteI am wondering If there any way to reload the resource bundle class after any changes.
You're welcome Ahmed :)
Delete