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.
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.
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
The implementation of this procedure – using a MERGE to deal with both new and modified resource bundle entries:
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
3. Extend the client interface of the AppModuleImpl to expose the new method in the Data Control
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:
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
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[ ).
The list of TextResources is stored in the class member
is populated in the method extraxtTextResource
TextResource objects are defined by the TextResource class:
The naïve implementation of extractKeyFromExpression() looks like this:
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:
This is the UIComponent that has a showPopupBehavior child (see later).
The setPopuplauncher() method invokes the populateProperties() method:
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
When the dialog is closed with the OK button, the method handleDialogEvent() is invoked:
(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:
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.
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:
and
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:
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:
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):
We can bring up the text editor by double clicking on the input field:
The user can change the Prompt and Hint Text property in the editor:
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:
And they are visible:
If so desired, the language or context can be changed, and the process can be repeated:
Language Dutch and Context None.
Double click the Page title; the popup appears:
Edit the textual property:
and press the OK button to persist this change.
Press the Force Refresh link and the change is visible in the application:
Resources
Download the ADF application with the code discussed in this article:https://technology.amis.nl/wp-content/uploads/2012/08/ADFFacesWithResourceBundle_Step6_EditTextualProperties.zip .
Other articles in this series:
-
Introduction to Resource Bundles in ADF applications for centralizing (management of) boilerplate text
-
Implement resource bundles for ADF applications in a database table
-
Supporting multiple languages in ADF applications backed by resource bundles – and programmatically controlling the JSF locale
-
Adding customization (or context sensitivity) to boilerplate text from database backed resource bundles in ADF applications
-
Refresh resource bundle from within the ADF application – to absorb changes in database backed bundles
-
Live update of Resource Bundle from within running ADF application
-
Live resource bundle entry editing in a generic way through declarative component and UI component tree manipulation
-
Creating reusable ADF Library with generic live resource bundle editing functionality and reusing it in any ADF application
many thanks to your efforts, you saved my life 🙂