This chapter describes how to use the ADF Faces change persistence framework to create JSF pages that users can customize at runtime.
This chapter includes the following sections:
Section 37.1, "Introduction to Allowing User Customizations"
Section 37.2, "Enabling Runtime User Customizations for a Fusion Web Application"
Section 37.4, "Controlling User Customizations in Individual JSF Pages"
Section 37.6, "Creating Implicit Change Persistence in Custom Components"
Certain ADF Faces components have attributes that can be saved for a specific user. For example, the value of the disclosed
attribute on a panelBox
component can be saved for a specific user during the current session. The myOrders
page in the StoreFront module application contains four panelBox
components that display order information. By default, they are expanded, as shown in Figure 37-1.
Note:
Thequery
component, which is not discussed in this chapter, can be used to implement saved searches, another type of user customization. For information about the query
component, see Chapter 29, "Creating ADF Databound Search Forms." The configuration required for using MDS to store saved searches is discussed in Section 29.2.3, "How to Persist Saved Searches into MDS."However, suppose a user decides to collapse one of the boxes, as shown in Figure 37-2.
Because this application is configured to allow user customizations, then during the user's session, anytime that user returns to the page, the Payment Information box remains collapsed. You need only to enable user customizations for the project in order for these changes to be persisted to the user's session.
Note:
The user session begins when the user logs in to the application, and ends when the user leaves the application. It is possible that while using an application, the user could navigate across application boundaries (for example, to a peer application) and thereby leave the application, at which point the user session would end.See the "Introduction to User Customization" section in the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework for a list of the attribute value changes that are implicitly persisted by an ADF Faces application, after you configure the application to allow user customizations.
You can also configure an application so that the value of these attributes can be persisted across sessions using the MDS repository. For example, if the StoreFront module allowed persistence to the MDS repository, then anytime that user entered the application, the Payment Information box would be collapsed.
Note:
Before you can enable persistence to the repository, you must first follow all MDS configuration procedures as documented in the Oracle Fusion Middleware Administrator's Guide.Along with the automatic persistence available through ADF Faces, you can create your own custom user customization capabilities for the following types of changes:
Changing an attribute value
Adding or removing a facet
Adding or removing a child component
Reordering child components
Moving a child component to a different parent
If you want to create these types of custom user customizations, you need to add code (for example, in an event handler) that will call the APIs to handle the persistence.
Enabling an application to use the change persistence framework requires that you first enable your application to allow user customizations. Part of this process is determining where those changes should be persisted, either to the session or the MDS repository.
If you choose to persist changes to the session, by default all values will be saved for the user's session. However if you choose to persist changes to a repository, you must explicitly configure which of these attribute values will be persisted to the repository. Instead of persisting all these attribute values, you can restrict changes so that only certain attribute value changes for a component are persisted, or so that only specific instances of the components persist changes.
Note:
You cannot persist changes to a component that is contained inside (anywhere in the subtree) ofaf:forEach
or af:iterator
tags. While such structure results in multiple copies of a component in the view tree, each component has only a single representation in the JSP document. Therefore, customizations of the component cannot be persisted in MDS.For any applications that persist changes to an MDS repository, when you deploy your application, you must create a metadata archive (MAR) profile in the application's EAR assembly. For more information, see Section 38.3.2, "How to Create Deployment Profiles."
Enabling an application to allow user customizations (whether for the default changes that some ADF Faces components provide, or for custom capabilities that you create) requires that you configure your application to use the change persistence framework and that you also determine where those changes should be persisted (either the session or the MDS repository).
Note:
If you are planning on persisting changes to the MDS repository, before configuring an ADF Faces application to use change persistence, you must first follow all MDS configuration procedures as documented in the Oracle Fusion Middleware Administrator's Guide.You enable your application to use the change persistence framework by editing the web.xml
and adf-config.xml
files.
To enable user customizations:
Double-click the web project in your application to open the Project Properties dialog. In the tree on the left, select the ADF View node.
On the ADF View page, select the Enable User Customizations checkbox. If you want the changes to be persisted to only the session, select the For Duration of Session radio button. If you want the changes to persist to the MDS repository, select Across Sessions Using MDS.
If you chose to persist to the repository, you now need to declare each component tag and associated attribute values that you want persisted to the repository (if you chose to persist only to the session, all values will be persisted). For procedures, see Section 37.3, "Configuring User Customizations." After that configuration is complete, you can override those settings on a per component instance basis. For procedures, see Section 37.4, "Controlling User Customizations in Individual JSF Pages."
Note:
If you have created custom user customization capabilities as documented in Section 37.5, "Implementing Custom User Customizations," then you also need to declare those attribute values or operations.When you elect to save changes only to the session, JDeveloper adds the CHANGE_PERSISTENCE
context parameter to the web.xml file
, and sets the value to session
. This context parameter registers the ChangeManager
class that will be used to handle persistence. If you instead elect to save the changes to the MDS repository, the value is set to oracle.adf.view.rich.change.FilteredPersistenceChangeManager
, as shown in Example 37-1.
Example 37-1 Context Parameter in web.xml Used For Change Persistence
<context-param> <param-name>org.apache.myfaces.trinidad.CHANGE_PERSISTENCE</param-name> <param-value> oracle.adf.view.rich.change.FilteredPersistenceChangeManager </param-value> </context-param>
Tip:
If needed, you can manually set this value tooracle.adf.view.rich.change.MDSDocumentChangeManager
, if you do not want any customizations to be restricted based on configurations in the adf-config.xml file or on the individual JSF pages, and you always want the changes to be persisted to the MDS repository and not the session.When you elect to persist to the repository, JDeveloper also does the following:
Adds the following JARs to the class path if they don't exist:
javatools-nodep.jar
facesconfigmodel.jar
taglib.jar
Ensures the ADFBindingFilter
is registered. If not, it adds the following entry to the web.xml
file.
<filter> <filter-name>adfBindings</filter-name> <filter-class>oracle.adf.model.servlet.ADFBindingFilter</filter-class> </filter>
Adds another context parameter to web.xml
to register the MDSJSPProviderHelper
class to handle merging MDS customization documents with the base JSP document, as shown in Example 37-2
Adds the ADF Faces Change Manager Runtime 11 library to the project.
In the adf-config.xml
descriptor file, sets the persistent-change-manager
element to the MDSDocumentChangeManager
, which is the class that will be used to persist the changes. Example 37-3 shows the configuration for persisting to the MDS repository.
Creates JSF JSP pages as XML documents. For more information, see Section 37.4, "Controlling User Customizations in Individual JSF Pages."
If you choose to persist changes to an MDS repository, you must decide which of the attribute values that are by default persisted to the session should also be persisted to the repository. Alternatively, you can configure which changes you do not want persisted.
Tip:
Often, a system administrator is the one to set the configurations in theadf-config.xml
. The persist
and dontPersist
attributes on a component allow page authors to override that setting as needed.For example, suppose you decide that you don't want the value for the width
attribute on columns to be persisted to the repository, but you do want all other default attribute changes for columns to be persisted. You must explicitly set the other default column values that you want to be persisted, and you also must explicitly configure the application to NOT persist the width
attribute.
Note:
If you have created custom user customization capabilities as documented in Section 37.5, "Implementing Custom User Customizations," then you must explicitly declare those attribute values or operations as well.You set (and unset) these values using the overview editor for the adf-config.xml
file. Figure 37-3 shows the overview editor where only certain attribute values for the column
component will be persisted.
Once set, you can override persistence for a specific component on a page. For example, suppose you want to disallow change on the width
attribute on only one table's columns. You want the rest of the tables in the application to persist changes to that attribute. You would configure the columns to globally persist changes to the width
attribute, but then for that one table, you would override the global configuration directly on the JSF page. For more information, see Section 37.4, "Controlling User Customizations in Individual JSF Pages."
Note:
If you've enabled just session persistence, then all attribute values shown in the "Introduction to User Customization" section of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework will be persisted to the session. There is no way to override this either globally or on an instance.By default, when you configure your application to use any type of change persistence (that is, to either the session or a repository), the values of all attributes shown in the "Introduction to User Customization" section of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework will always be persisted to the user's session. If you configured your changes to be persisted to a repository, then you must declare the attributes whose values should be persisted to that repository. If there are any values that you don't want persisted, then you need to configure those values as well.
To declare attribute value persistence to a repository:
In the Application Navigator, expand the Application Resources pane, expand the Descriptor > ADF META-INF node, and double-click adf-config.xml to open that file.
In the overview editor, click the View tab.
In the Tags table, select the component whose changes you want to persist (or not persist) to the repository. If the component does not appear in the table, click the Add icon, and select and add it.
Note:
The filter rules specified in theadf-config.xml
file are applicable only when you have chosen to persist to the MDS repository (see Section 37.2.1, "How to Enable User Customizations"). These rules do not apply for persistence within session scope.
If persistence fails for any reason, (for example if one of the filter rules fails or the MDS repository errors), then the values will be stored only within the session scope.
The Tag Attributes table displays all the attributes for the selected component whose values can be persisted. Select Persist Changes for all attributes whose values you want persisted. Deselect any if you do not want the values persisted.
Note:
If you are implementing custom user customizations (see Section 37.5, "Implementing Custom User Customizations"), then you will need to edit theadf-config.xml
manually to add the configuration. See Example 37-4 for an example on how to configure user customizations.When you select the component tags and attribute values to be persisted in the adf-config.xml
file, JDeveloper enters tag library information for the components and attributes that are to be persisted. Example 37-4 shows the entry for persisting the value of the disclosed
attribute on the panelBox
component.
Once you have enabled your application to use user customizations, you can control user customizations for specific components on the page.
By default, the framework persists changes for all component instances, based on the configuration in the adf-config.xml
file. You can override this default behavior by explicitly setting what should be persisted and what should not be persisted on each component instance using the persist
and dontPersist
attributes.
Note:
The filter rules specified using thepersist
and dontPersist
attributes are applicable only when you have chosen to persist to the MDS repository (see Section 37.2.1, "How to Enable User Customizations"). These rules do not apply for persistence within session scope.
If persistence fails for any reason, (for example if one of the filter rules fails or the MDS repository errors), then the values will be stored only within the session scope.
The following components support the persist
and dontPersist
attributes:
panelBox
showDetail
showDetailHeader
showDetailItem
column
tree
treeTable
panelSplitter
calendar
You can override any globally set persistence configuration for a component using its persist
and dontPersist
attributes.
Tip:
Often, a system administrator is the one to set the configurations in theadf-config.xml
. The persist
and dontPersist
attributes allow page authors to override that setting as needed.To implement user customizations on a JSF Page:
Add components to the page, as needed, including components that will be persisting changes.
If you want to persist all persistable attributes for a component:
In the Property Inspector, expand the Advanced section.
Click the drop-down list for the Persist field and choose All Available.
If you do not want to persist any attributes, repeat Step 2 for the Don'tPersist field.
If more than one attribute can be persisted for the component, and you do not want to persist all of them:
Click the drop-down menu to the right of the Persist field and choose Edit to open the Edit Property dialog.
Shuttle any attributes to be persisted from Available to Selected.
If you do not want to persist an attribute value, repeat Step 4 for the Don't Persist field.
Note:
The filter rules specified using thepersist
and dontPersist
attributes take precedence over any adf-config.xml
configuration set for global component-level restrictions.
Values specified for the dontPersist
attribute take precedence over values specified for the persist
attribute. For example, if for a panelBox
component you set disclosed
as the value for both the persist
and dontPersist
attributes, the value of the disclosed
attribute will not be persisted.
If you set the value of the persist
or dontPersist
attribute to All Available
, then any values entered as choices using the Edit dialog and the shuttle will be ignored and all available attribute values will be persisted or not persisted.
When an application is configured to persist changes to the session, any changes made during the session are recorded in a session variable in a data structure that is indexed according to the view ID and the component's ID attribute value. Every time the page is requested, in the subsequent create View or Restore View phase, all changes are applied in the same order as they were added. This means that the changes registered through the session will be applied only during subsequent requests in the same session.
When an application is configured to persist changes to the MDS repository, any changes made during the session are recorded by mutating the Document Object Model that MDS maintains for the JSP document behind the view. A JSF phase listener registered by ADF controller triggers a commit on the MDS session during the appropriate lifecycle phase, resulting in the change document being persisted in the MDS store. Every time the page is requested, Oracle's JSP engine seeks the JSP document from an MDS JSP provider, which provides a flattened document after merging the stored changes to the base document. MDS records the change against the unique value of the component's ID attribute.
Tip:
If changes are applied in response to a partial submit of the page (for example, acommandButton
with the partialSubmit
attribute set to true
), the component for which changes are applied must be set as the value for the partialTarget
attribute.Additionally, be aware that when you run the application from JDeveloper in the Integrated WebLogic Server, MDS creates a local file-based repository to persist metadata customizations. Whereas when the application is deployed to a test or production environment, customizations are persisted to the configured MDS repository. For more information about MDS repository configuration, see the Oracle Fusion Middleware Administrator's Guide. For more information about deploying an application, see Section 38.4, "Deploying the Application."
The way that changes are persisted for components in templates, regions, and declarative components is handled differently, depending on whether the changes are persisted to the session or to the MDS repository. With session persistence, changes are recorded and restored on components against the viewId
for the given session. As a result, when the change is applied on a component that belongs to one of these objects (region, page template, or declarative component), that change is applicable only in the scope of the page that uses the object. It does not span all pages that consume the object.For example, suppose you have pageOne.jspx
and pageTwo.jspx
, and they both contain the region defined in region.jsff
, which in turn contains a showDetail
component. When pageOne.jspx
is rendered and the disclosed
attribute on the showDetail
component changes, the implicit attribute change is recorded and will be applied only for pageOne.jspx
. If the user navigates to pageTwo.jspx
, no attribute change is applied.
When you persist changes to the MDS repository, MDS records and restores customizations for a document identified by a combination of the JSP page path and customization name/value configuration setting as set on the customization class (for more information, see Section 36.2.1.1, "Customization Classes"). As a result, for a given page that is rendered, when MDS applies a change on a component within one of these objects (region, template, or declarative object), it is applicable for all pages that consume the object and that have the same customization name and value as the source page.
In the previous example, assume that the showDetail
component uses the ID of myShowDetail
. When pageOne.jspx
is rendered and the disclosed
attribute on the showDetail
component changes, the attribute change is recorded for region.jsff
(and not the page that consumes it). This change is applied when any page that contains the region is rendered, as long as the ID remains the same.
Additionally, user customizations are allowed through the persistence change manager on components that are direct children of a page template or a declarative component only if the definition of the page template or declarative component is not private. If it is private, the customization is written into the session store.
Note:
The definition of the page template or declarative component is a tag-only, nonbindable attribute. For declarative components, it isaf:componentDef
. For page templates, it is af:pageTemplateDef
.In addition to the user customization capabilities built in to certain ADF Faces components, you can create your own custom user customization capabilities. The change persistence framework supports the following types of user customizations:
Changing an attribute value
Adding or removing a facet
Adding or removing a child component
Reordering child components
Moving a child component to a different parent
To create custom user customizations, you must create a customization class for each type of user customization and then configure your application to use that class. You also need to set up the layers of customization for your application. For more information about both of these procedures, see Section 36.2, "Developing a Customizable Application."
Once those prerequisites are satisfied, you add logic that calls methods on the ADF Faces classes that handle persisting change either to the session or the MDS repository. To handle the change, you create code that uses the APIs from one of the ADF Faces specialized component change classes. For most cases, you add this code to the event handler method on a managed bean associated with the page the persisting component is on. If you want all instances of a component to persist the same change, you need to add this code for each page on which that component appears.
If you are creating a custom component, you can implement user customizations for the component by adding code directly to the custom component class. In that case, you will need to add the code only to the component class, and not once for each instance of the component. For more information, see Section 37.6, "Creating Implicit Change Persistence in Custom Components."
To better understand what you need to do to create custom user customizations, it may help to have a deeper understanding of the change persistence and MDS frameworks. When you elect to persist changes to the MDS repository, the change persistence framework works in conjunction with the MDS framework. Where and how the customizations are saved are determined by how you set up your MDS repository, your customization layers, and your customization classes. Details about the MDS framework and the repository and how to use it are covered in Chapter 36, "Customizing Applications with MDS."
The change persistence framework uses the underlying change manager classes from Apache MyFaces Trinidad (in the org.apache.myfaces.trinidad.change
package) along with a few ADF Faces-specific classes (in the oracle.adf.view.rich.change
package). The instance of the registered ChangeManager
class is accessible through the RequestContext
object. It is responsible for gathering changes as they are created and added during a request, and then persisting them. The SessionChangeManager
class is an implementation of ChangeManager
which handles persistence within a session only, while the MDSDocumentChangeManager
class is an implementation that persists to the MDS repository only. The FilteredPersistenceChangeManager
class is an implementation of ChangeManager
that stores the changes that pass the filter rules into the repository using the registered persistence change manager. Any change that does not get persisted to the repository will be persisted to the session when FilteredPersistenceChangeManager
is used.
Additional classes are used to describe the changes to a component. You use these APIs to handle persisting any changes to components other than the implicit value changes the ADF Faces framework provides (as shown in the "Introduction to User Customization" section of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework). ComponentChange
is the base class for all classes used to implement specific changes that act on the JSF component hierarchy, such as adding or removing a facet or a child component. These changes are automatically applied during subsequent creation of the view, in the same order in which they were added. Classes that extend the ComponentChange
class and that also implement the DocumentChange
interface can directly persist changes to the MDS repository. Classes that do not implement the DocumentChange
interface can persist changes only to the session.
Table 37-1 describes the specialized classes that handle specific customizations. If "yes" appears in the Repository column, then the class implements the DocumentChange
interface and it can persist changes to the MDS repository.
Table 37-1 Classes Used to Handle Change Persistence
Class Name | Repository | Description |
---|---|---|
|
Yes |
Adds a child component using document mark up. While applying this change, the child component is created and added to the document. |
|
No |
Changes the value of an attribute. |
|
Yes |
Changes the value of an attribute. |
|
Yes |
Moves a child from one container to another. |
|
Yes |
Removes a child component. |
|
No |
Adds a child component to the facet using a document markup. While applying this change, the markup will be added to the document. |
|
Yes |
Adds a child component to a facet. While applying this change, the DOM element corresponding to the child component is added to the document. If the facet doesn't exist, it will be created. If the facet does exist, all of its content will be removed and the new content added. |
|
Yes |
Removes a facet. |
|
Yes |
Reorders children of a component. |
Aside from a ChangeManager class, you may also need to implement and register the DocumentChangeFactory
interface with the ChangeManager
class. If the DocumentChangeFactory
implementation can provide an equivalent DocumentChange
for a ComponentChange
, the ChangeManager
will use it to persist the DocumentChange
to the repository.
You need to add code to handle any explicit changes you want to create, and to configure the components on the JSF page to handle customization. As with the default user customizations, you also must register the custom changes in the adf-config.xml
file.
Note:
When the changes are expressible in more than one form, the change must be recorded in the form with highest precedence. For example:Attribute change for a component: The attribute can be specified on the component tag or it can be expressed using the <f:attribute>
tag. In a JSF JSP document, <f:attribute>
takes lesser precedence over the attribute specified on the component tag. Therefore, the attribute change on the component tag will be recorded for customization.
Column header text in a column component: The header text for the column can be specified using either the headerText
attribute or using header facet. In this case, the facet component will have precedence.
To create custom user customizations:
Create a managed bean for the page that contains the component.
Add code to the event handler method for the component that will be used to make the change. This code should obtain the component that contains the change. It should then use the component and the appropriate APIs to create, record, and persist the change.
Example 37-5 shows the code on the action event handler for a command button for a change that will be persisted to the MDS repository. When a user clicks the button, that source graphic file changes. The event handler method accesses the component and changes the source attribute for the graphic. It then calls the private addAttributeChange
method, which first uses the component API to record the change, and then uses the AttributeComponentChange
class to set the new source attribute value.
Example 37-5 Persisting Change to the Repository from an Event Handler on a Managed Bean
public void modifyObjectImage(ActionEvent event) { UIComponent uic = event.getComponent().findComponent("oi1"); String source = "/images/mediumAd.gif"; uic.getAttributes().put("source", source); _addAttributeChange(uic, "source", source); } . . . private static void _addAttributeChange(UIComponent uic, String attribName, Object attribValue) { FacesContext fc = FacesContext.getCurrentInstance(); ChangeManager cm = RequestContext.getCurrentInstance().getChangeManager(); ComponentChange cc = new AttributeComponentChange(attribName, attribValue); apm.addComponentChange(fc, uic, cc); }
Note:
When you persist changes, in addition to explicitly recording a change on the component (which is done in Example 37-5 usinguic.getAttributes().put("source", source)
method), you must also directly apply the change using the component API, as was done using the private _addAttributeChange(uic, "source", source)
method. Applying the change in this way allows the user to see the change in response to the same request. If the change is recorded on the component, then the change will not be seen until a subsequent request.
Additionally, if you know that the component will always persist to the repository regardless of any restricted change persistence settings, you can instead call the AdfFacesContext.getCurrentInstance().
method.
getPersistentChangeManager()
The ChangeManager
class provides support for automatically converting an AttributeComponentChange
into an AttributeDocumentChange
, thereby allowing persistence to a repository. However, if you need to convert another type of change and you use a specialized change manager class that does not implement the DocumentChange
class, you need to create a custom DocumentFactory
implementation that converts the component change to a document change.
Note:
Automatic conversion ofAttributeComponentChange
into an AttributeDocumentChange
assumes that the component attribute is represented as an attribute of the same name on the associated element in the JSPX document.
Only those attribute values that are expressible in the JSPX document can be persisted using AttributeDocumentChange
. In other words, CharSequence
, Number
, Boolean
and ValueExpression
are the only supported data types.
Only values that implement java.io.Serializable
can be persisted using AttributeComponentChange
.
If you create a custom DocumentFactory
implementation, you need to register it with the appropriate change manager class using the following method in your bean:
public static void registerDocumentFactory(String targetClassName, String converterClassName)
Where targetClassName
is the name of the ComponentChange
class and converterClassName
is the name of your DocumentChangeFactory
extension that is capable of converting the target ComponentChange
into a DocumentChange
. The semantics of name
for these classes is same as that of getName()
in the java.lang.Class
class.
If the class you use to create the component change adds a child that has a subtree of components, and you want to persist the changes to the repository, you must create a DocumentFragment
to represent the change.
Example 37-6 shows how to use the AddComponentDocumentChange
specialized class to create a DocumentChange
object and use a DocumentFragment
to represent the change.
Example 37-6 Converting a ComponentChange Object to a DocumentChange Object
public void appendChildToDocument(ActionEvent event) { UIComponent eventSource = event.getComponent(); UIComponent uic = eventSource.findComponent("pg1"); // only allow the image to be added once if (_findChildById(uic,"oi3") != null) return; FacesContext fc = FacesContext.getCurrentInstance(); DocumentFragment imageFragment = _createDocumentFragment(_IMAGE_MARK_UP); DocumentChange change = new AddChildDocumentChange(imageFragment); ChangeManager apm = AdfFacesContext.getCurrentInstance().getChangeManager(); apm.addDocumentChange(fc, uic, change); } private static final String _IMAGE_MARK_UP = "<af:objectImage id='oi3' height='100' width='120' " + "source='http://www.somewhere.com/someimage.jpg' " + "xmlns:af='http://xmlns.oracle.com/adf/faces'/>"; private static DocumentFragment _createDocumentFragment( String markUp) { // prepend XML declaration markUp = "<?xml version = '1.0' encoding = 'ISO-8859-1'?>" + markUp; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); factory.setValidating(false); DocumentBuilder builder; try { builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException pce) { _LOG.log(Level.WARNING, "Unable to get XML Parser:", pce); return null; } try { // use a version explicitly with ISO-8859-1 instead byte[] markupBytes = markUp.getBytes(); Document newDoc = builder.parse(new ByteArrayInputStream(markupBytes)); DocumentFragment fragment = newDoc.createDocumentFragment(); // add the document's root element to the fragment fragment.appendChild(newDoc.getDocumentElement()); return fragment; } catch (SAXException se) { _LOG.log(Level.WARNING, "Unable to parse markup:" + markUp, se); return null; } catch (IOException ioe) { _LOG.log(Level.WARNING, "IO Problem with markup:" + markUp, ioe); return null; } }
Register the user customizations in the adf-config.xml
file, as documented in Section 37.3, "Configuring User Customizations." If the custom changes are of any type other than AttributeDocumentChange
, you will need to manually edit the adf-config.xml
file and indicate that all changes are allowed for the component, as shown in Example 37-7.
When you create a custom component, you may decide that you want certain attribute values on that component to be persisted whenever change persistence is enabled in an application. Setting implicit change on a custom component is similar to setting explicit change persistence on existing components. You add code that executes the actual persistence, but instead of you placing that code on a managed bean, that code can be handled directly by the component class. If your component's attribute values are synchronized with the server using events, then you can use the broadcast method to persist the changes. If the attribute value that you want to persist does not use events, then you need to add code in the renderer and component class.
When an attribute value uses events, you need to add code to the component class.
To set implicit change persistence for attribute values that use events:
Open the custom component class java file.
Add code to the broadcast method that will use the specialized class to create a new ComponentChange
object and then call the ChangeManager
to add the change.
Example 37-8 shows the code added to the UIXShowDetail
class that persists a change to the disclosed
attribute. In this case, the AttributeComponentChange
class is used.
Example 37-8 Persisting Change from a Component Class
public class UIXShowDetail extends UIXComponentBase { ... public void broadcast(FacesEvent event) throws AbortProcessingException { super.broadcast(event); ... if (event instanceof DisclosureEvent) { boolean isDisclosed = ((DisclosureEvent) event).isExpanded(); setDisclosed(isDisclosed); //Record a Change for 'disclosed' attribute AttributeComponentChange aa = new AttributeComponentChange('disclosed', isDisclosed ? Boolean.TRUE : Boolean.FALSE); AdfFacesContext adfContext = AdfFacesContext.getCurrentInstance(); adfContext.getChangeManager().addComponentChange(getFacesContext(), this, aa); ... } } ...
When an attribute does not use events, you need to place code in the component's renderer class.
To set implicit change persistence for other attribute values:
Open the custom component's render class java file.
Use the findTypeConstants
method, which takes a ClientMetadata
instance and use the addPersistedProperty
method to mark certain properties as persisted. Example 37-9 shows a code snippet from the renderer class used for the ADF Faces PanelSplitter
component, which implicitly persists the splitterPosition
attribute value.
Example 37-9 Method in Component Renderer Class to Implicitly Persist Changes
// Code snippet from PanelSplitterRenderer.java protected void findTypeConstants( FacesBean.Type type, ClientMetadata metadata) { super.findTypeConstants(type, metadata); metadata.addRequiredProperty( _orientationKey = type.findKey("orientation")); metadata.addRequiredProperty( _positionedFromEndKey = type.findKey("positionedFromEnd")); metadata.addRequiredProperty( _disabledKey = type.findKey("disabled")); metadata.addRequiredProperty( _splitterPositionKey = type.findKey("splitterPosition")); metadata.addPersistedProperty(_splitterPositionKey); }
In the JavaScript component peer class, define the attribute value to be persisted, using the setProperty
function. This function needs to be invoked with the attribute name (as defined in the renderer in the previous step), the value, and "true
", meaning the value of the attribute will be set. Example 37-10 shows a code snippet from the panelSplitter
class that sets the splitter position.