Live update of Resource Bundle from within running ADF application

0

In a number of prior articles I have discussed how resource bundles are used in ADF applications to centralize boilerplate text elements – and how such resource bundles can be implemented in the database. I have shown how various groups of users can be served with different sets of resource bundle entries (context sensitive) and how resource bundles can be refreshed at run time, without redeployment or even restart of the application. Building on top of these earlier steps, I will now add functionality to the demo application to edit the resource bundle entries live and in context of the application. That means: a user (with the proper authorization) can bring up a boilerplate text editor in the context of a specific UI component and edit the resource bundle entries associated with that component – for each of the supported languages and each of the supported context values.

image

Any changes made while editing are recorded in the database table under the resource bundle and can be applied to the running application through the refresh resource bundle functionality introduced earlier on.

image

Steps for implementing resource bundle editing in an ADF application

(here I am assuming that all steps discussed in the earlier articles on resource bundles in ADF applications have been taken already)

1. Extend the PL/SQL package nls_resource_manager with a procedure for updating resource bundle entries

2. Extend the ADF BC Application Module AppModuleImpl with a method updateResourceBundleEntry() that leverages the PL/SQL package to apply new and modified resource bundle entries

3. Extend the client interface of the AppModuleImpl to expose the new method in the Data Control

4. Extend the generic page definition to also contain an operationBinding for the updateResourceBundleEntry() operation

5. Create a managed bean that reads textual properties from a UI Component, exposes them and is capable of writing them to persistent store through the operationBinding

6. Create a popup that uses the managed bean to show the textual properties for the selected UI Component and allows the user to edit them

7. Extend the managed bean with the logic to persist new and changed resource bundle entries

8. Configure UI Components to allow the user to open the popup for them

9. Run the page, activate the popup for one of more UI Components and edit the textual properties for them.

 

1. Extend the PL/SQL package nls_resource_manager with a procedure for updating resource bundle entries

image

The implementation of this procedure – using a MERGE to deal with both new and modified resource bundle entries:

image

Also notice the use of the autonomous transaction. This ensures that the manipulation of the resource bundle is completely isolated from the ADF application transaction.

2. Extend the ADF BC Application Module AppModuleImpl with a method updateResourceBundleEntry() that leverages the PL/SQL package to apply new and modified resource bundle entries

image

3. Extend the client interface of the AppModuleImpl to expose the new method in the Data Control

image

At this point we can run the Application Module to test whether we can indeed update entries in the table that holds Resource Bundle Entries.

After refreshing the Data Control, the new operation is available:

image

4. Extend the generic page definition to also contain an operationBinding for the updateResourceBundleEntry() operation

image

 

5. Create a managed bean that reads textual properties from a UI Component, exposes them and is capable of writing them to persistent store through the operationBinding

Class TextEditor is created. One of its methods is populateProperties. This method takes a UIComponent as input. It inspects this component and retrieves all of its properties that contain a reference to the resource bundles in their value (this is found by looking for a ValueExpression that contains the string #{msg[ ).

image

The list of TextResources is stored in the class member

image

is populated in the method extraxtTextResource

image

TextResource objects are defined by the TextResource class:

image

The naïve implementation of extractKeyFromExpression() looks like this:

image

The TextResources are displayed in the Popup in which the user can edit the textual properties. The bean is populated at the moment the popup is launched. When the popup is launched, the UI Component that launches the popup is passed to the TextEditor bean:

image

This is the UIComponent that has a showPopupBehavior child (see later).

The setPopuplauncher() method invokes the populateProperties() method:

image

 

6. Create a popup that uses the managed bean to show the textual properties for the selected UI Component and allows the user to edit them

image

7. Extend the managed bean with the logic to persist new and changed resource bundle entries

When the dialog is closed with the OK button, the method handleDialogEvent() is invoked:

image

(because of the dialogListener attribute on the af:dialog component)

The method recordResourceEntries() is invoked by the handleDialogEvent() method. It establishes the current context value and the current language. Then it iterates of all text resources. When a text resource has been  modified, method updateResourceBundleEntry() is invoked for the text resource:

image

Method updateResourceBundleEntry() is the one that gets hold of the updateResourceBundleEntry operationBinding that is associated with the method of that name in AppModImpl class that invokes the PL/SQL procedure.

image

8. Configure UI Components to allow the user to open the popup for them

We need to do something to associate UI components such as inputText, commandButton and panelHeader with the popup in which the textual properties can be inspected and edited.

For inputText, and panelHeader we can use a showPopupBehavior - linked to the dblClick action:

image

and

image

When these components are double clicked, the popup editTextResources is brought up. The inputText and panelHeader play the role of the launcher [component].

For a commandButton this is not a feasible approach. In this case, I have embedded the commandButton together with a commandImageLink in a panelGroupLayout:

image

The commandImageLink shows up with a little icon. This component has more or less the same showPopupBehavior child as the inputText and panelHeader components. It will bring up the popup.

Note how method populateProperties() has a special provision for this construct:

image

When the launcher component is a commandImageLink, the code locates the first child of the parent of the commandImageLink and takes that one as the component to retrieve the textual properties from.

9. Run the page, activate the popup for one of more UI Components and edit the textual properties for them.

A typical sequence looks like this:

The page is shown and we see the textual properties – prompt and hint text -of the inputText component, for the current language (en) and context (Junior):

image

We can bring up the text editor by double clicking on the input field:

image

The user can change the Prompt and Hint Text property in the editor:

image

And press the OK button to have these changes persisted. At this moment, the user will not see the modified textual properties. However, pressing the Refresh link will propagate the changed values into the user interface:

image

And they are visible:

image

If so desired, the language or context can be changed, and the process can be repeated:

image

Language Dutch and Context None.

Double click the Page title; the popup appears:

image

Edit the textual property:

image

and press the OK button to persist this change.

image

Press the Force Refresh link and the change is visible in the application:

image

Resources

Download the ADF application with the code discussed in this article:http://technology.amis.nl/wp-content/uploads/2012/08/ADFFacesWithResourceBundle_Step6_EditTextualProperties.zip .

Other articles in this series:

  1. Introduction to Resource Bundles in ADF applications for centralizing (management of) boilerplate text

  2. Implement resource bundles for ADF applications in a database table

  3. Supporting multiple languages in ADF applications backed by resource bundles – and programmatically controlling the JSF locale

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

  5. Refresh resource bundle from within the ADF application – to absorb changes in database backed bundles

  6. Live update of Resource Bundle from within running ADF application

  7. Live resource bundle entry editing in a generic way through declarative component and UI component tree manipulation

  8. Creating reusable ADF Library with generic live resource bundle editing functionality and reusing it in any ADF application

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