Adding customization (or context sensitivity) to boilerplate text from database backed resource bundles in ADF applications

0

Any web application contains boilerplate text: text that is not part of the enterprise data from web services or databases that is manipulated by the end users using the application but that is part of the application definition itself. Text that is shown as prompt, title, message, hint text and in other ways. Developers can sprinkle the boilerplate text all throughout the application, in pages, JavaScript and other code sections. But they should not do that. Changing boiler plate text is a frequent requirement from the business. Having all boilerplate text in a central location makes such changes a lot easier. Additionally, many organizations require applications to be multi-lingual: different groups of users speak different languages and want to have the application support them in their own language. That means boiler plate text is not just defined once in that central location, but once for every language the application needs to support.

In previous articles I discussed how resource bundles can be used for centralizing the boilerplate text items and how a resource bundle can be implemented in a database table. In this article I will describe how to support not just different boilerplate text items for different languages but also different sets of boiler plate text for user groups that vary by location, role, department, age or personal preference. The example in this article is a variation of boilerplate text based on the selected age context (none, Junior or Senior):

image

Note that any context (or combination of contexts) can be used.

In a later piece we will discuss how to refresh a resource bundle in running application and finally we will see how we can create an in-line resource bundle editing mechanism that allows users to manipulate the boiler plate text in context in a running application.

Note: this article is a sequel to this article (http://http://technology.amis.nl/2012/08/10/implement-resource-bundles-for-adf-applications-in-a-database-table ) that introduces the database backed resource bundles, and this article (http://technology.amis.nl/2012/08/11/supporting-multiple-languages-in-adf-applications-backed-by-resource-bundles-and-programmatically-controlling-the-jsf-locale) that explains how the locale can be programmatically set.

Steps to introduce one context to vary boilerplate text (i.e. resource bundle entries) in

1. Add a column to specify the context to the table RESOURCE_BUNDLE_ENTRIES

image

2. Extend the PL/SQL API to cater for the context

This means: adding the input parameter p_context in function get_resource_bundle_entries in  both specification and body and extending the SQL query to take the context into consideration.

image

and in the body:

image

3. Modify Java method getResourceBundle() in Class AppModuleImpl

Add a parameter context in the method signature, add an addition bind parameter in the callable statement and pass the context parameter as the additional bind parameter’s value:

image

4. Refresh the Client Interface of the Application Module AppModule (add the changed getResourceBundle() method to the client interface

image

5. Change the generic page definition GenericPageDef.xml

Add the context parameter to the operationBinding for getResourceBundle():

image

6. Modify the DatabaseResourceBundle Class

The  DatabaseResourceBundle  class contains method getResourceBundle() that retrieves the contents of the resource bundle from the database – through the GenericPageDef’s operation binding. This method needs to be extended for the new context parameter:

image

The call to getResourceBundle() needs to be modified as well:

image

And the method getContext1() is added:

image

For each context value, there will be separate class – just like there is one for each supported language. The method getContext1() needs to be implemented in each of these classes – returning null, Junior or Senior.

7. Create context specific DatabaseResourceBundle classes

image

Add a DatabaseResourceBundle class for every context value (and for each language) that is to be supported. Ensure that in this class the proper context value is returned by getContext1(), for example:

image

and

image

 

8. Create class MessageProvider

This class will return the resource bundle entries. It is directly referred to from within the boilerplate text properties in the pages – using expressions like #{msg[‘key’]}. Because this class implements the Map interface, it can be accessed with this type of EL expression. The msg bean – based on MessageProvider – gets the MessageManager passed in (to be discussed next). This MessageManager uses the current locale and context as well as all registered resource bundles (potentially more than one) to return the requested value.

image

9. Create class MessageManager

This class does the hard work when it comes to returning the appropriate resource bundle entry, given the locale and the context.

The class exposes method getMessage() that is invoked from the MessageProvider. This method will try to find the resource bundle entry with the best fit, given the key – and the current locale and context.

The current context is set in the property contextDimensionValue (by a selectOneChoice, as we will see in a little while). Method getMessage() first tries to find the resource entry in a context sensitive bundle. If that fails, it will try to look the resource in context neutral (ignorant) way:

image

Method getMessageFromResourceBundle() retrieves the current locale from the JSF ViewRoot (where our custom ViewHandler has put it). It iterates over the bundles (in this case there is only one) defined through the bundleNames member, set through a managed property in the faces-config.xml file. It attempts to find the entry for the given key in each of the bundles (that may be post fixed with the context specific postfix). As soon as the entry is found, the method returns.

image

10. Create managed bean definitions in the faces-config.xml file

Two new managed beans are required. Bean msg will be referred to in each page, whenever a resource bundle entry is required. Bean msgMgr is injected into bean msg and will provide it with the actual logic of retrieving the bundle entry.

image

11. Modify PageOne.jspx: replace bnd references (to JSF resource bundle) with msg references (to the msg bean)

image

12. Add a context selector to PageOne.jspx – a selectOneChoice that manipulates the context value in the msgMgr bean:

image

 

13. Create Resource Bundle Entry records in the database table for the resource keys and supported languages and context values:

image

14. Run the page and try out various combinations of language and context (Age Context)

image

Change the Age Context

image

(and press F5 to refresh the browser or reload from the browser address bar)

image

From Junior to Senior:

image

and on to Dutch:

image

Dutch in the Junior context:

image

and in the age neutral context:

image

 

Resources

Download the ADF application discussed in this article:ADFFacesWithResourceBundle_Step4_WithContextVariation .

Share.

About Author

Lucas Jellema, active in IT (and with Oracle) since 1994. Oracle ACE Director for Fusion Middleware. Consultant, trainer and instructor on diverse areas including Oracle Database (SQL & PLSQL), Service Oriented Architecture, BPM, ADF, Java in various shapes and forms and many other things. Author of the Oracle Press book: Oracle SOA Suite 11g Handbook. Frequent presenter on conferences such as JavaOne, Oracle OpenWorld, ODTUG Kaleidoscope, Devoxx and OBUG. Presenter for Oracle University Celebrity specials.

Leave a Reply