The Oracle Metadata Services (MDS) framework allows you to create customizable applications. This chapter describes how to develop applications that can be customized and subsequently deployed by a customer. It also covers how to implement customizations on such applications.
This chapter includes the following sections:
For information on how to deploy customized applications, see Section 36.5, "Deploying the Application."
Using the customization features provided by MDS, you can create applications that fall into the following customization patterns:
Seeded customization
Seeded customization of an application is the process of taking a generalized application and making modifications to suit the needs of a particular group, such as a specific industry or site. Seeded customizations exist as part of the deployed application, and endure for the life of a given deployment. This chapter describes how to create a customizable application, and then customize the application using JDeveloper.
User customization (change persistence)
User customization allows an end user to change the content of the application at runtime to suit individual preferences (for example, which columns are visible in a table), and have those changes "remembered" the next time the user opens the application. For information about user customization, see Chapter 35, "Allowing User Customizations at Runtime."
Design time at runtime
Using the features of Oracle WebCenter, you can create applications that are customizable at runtime. This allows business analysts or administrators, using a Web browser interface, to customize the application for their end users. For information about runtime customization, refer to the Oracle Fusion Middleware Developer's Guide for Oracle WebCenter.
For more information about the MDS architecture and metadata repositories (database and file-based) and archives (EAR, MAR), refer to the Oracle Fusion Middleware Administrator's Guide.
A customized application contains a base application and one or more layers containing customizations. MDS stores the customizations in a metadata repository and retrieves them at runtime to merge the customizations with the base metadata to reveal the customized application. Since the customizations are saved separately from the base, the customizations are upgrade safe; a new patch to base can be applied without breaking customizations. When a customized application is launched, the customization content is applied over the base application.
For example, say you have a generalized payroll application with a validation rule that limits the salary field to 4000. Then you create a customization of that validation rule that limits the salary field to 3300. At runtime, the customization is applied to the base application and the validation rule for the salary field limits it to 3300.
A customizable application can have multiple customization layers. Examples of customization layers are industry
and site
. Each layer can have multiple customization layer values, but typically only one such layer value from each layer is applied at runtime. For example, the industry
layer for a customizable application can contain values for healthcare
and financial
industries; but in the deployed customized application, only one of the values from this layer is used at a time.
Layer values from multiple customization layers can be applied, in a specified order of precedence, on top of the base metadata. For example, a customized application can contain customizations in the financial
layer value of the industry
layer and the Financial Company #1
layer value of the site
layer. Each customization layer corresponds to a customization document that contains a set of instructions that change the underlying metadata.
The customization context of a customized application is defined by the set of customization layer values applied to it.
Figure 34-1 illustrates how layers are applied in a customized application.
To support this, you use JDeveloper to create customization classes, define layers and values, and specify the order of precedence. These processes are described in Section 34.2, "Developing a Customizable Application."
Customizations can be categorized as either static or dynamic. Static customizations have only one layer value in effect for all executions of the application, while dynamic customizations can have values that vary based on the execution context of the application. If a customization can vary for different users executing the application, then it is dynamic. If a customization has the same value for all users executing the application then it is static.
When you implement customizations in ADF Model objects and ADF Business Components objects, the customizations remain the same for entire runtime of the application. This is because these objects are loaded only once for an application and reused for the duration of the application. For example, you can have a customized validation rule in the Healthcare Company #1 value of the site layer that limits salaries for that site to 3300. This is static customization content.
However, you can also implement customizations at the controller or view level that allow the layer value to be determined at runtime, based on user roles (responsibilities) or other application-specific criteria. For example, you can design an application so that users from different organizations see different sets of fields on a given screen. This is dynamic customization content.
The determination of whether a customization is static or dynamic is made in the customization class. In the customization class, if the getCacheHint()
method returns ALL_USERS
, then the customization layer is static. For more information about CacheHint
values, see Section 34.2.2, "What You May Need to Know About Customization Classes."
All objects could have a static customization layer, depending on how the customization classes are implemented. But for ADF Model and Business Components objects, customizations can only be static.
To create a customizable application, create the base application and perform the following procedures:
To prepare an application for customization:
Create the customization classes that will be used, as described in Section 34.2.1, "How to Create Customization Classes."
Enable seeded customization in the application, as described in Section 34.2.3, "How to Enable Seeded Customizations for View Projects."
Specify the customization classes in the adf-config.xml
file, as described in Section 34.2.6, "How to Configure the adf-config.xml file."
You can optionally restrict runtime customizations on the application, as described in Section 34.4.1, "How to Edit Extended Metadata Properties."
After you have prepared the application for customization, you must prepare JDeveloper so you can use it to implement the customizations, as described in Section 34.3.4, "How to Configure Customization Layers."
A customization class is the interface that MDS uses to define which customization applies to the base definition metadata. Each customization class defines a customization layer (for example, industry
or site
) and can contain multiple layer values. The customization classes that are used in the application must be available to JDeveloper when customizing the application, and included in the deployed application.
A customization class evaluates the current context and returns a String result. This String result is used to locate the customization layer.
The customization class provides the following information:
A name, that represents the name of the layer.
An array of values, that represent the customization layer values. Typically, each layer returns a single value. If multiple values are returned, the customizations available in the MDS repository for those values are applied in the order in which they appear in the array. For more information, see Section 34.2.1.2, "Implementing the getValue() Method in Your Customization Class."
An IDPrefix, for objects created in the layer. When new objects are created in a customization layer they need a unique ID. The IDPrefix is added to the autogenerated identifier for the object to create an ID for the newly added object. Each layer needs a unique IDPrefix so that objects created at different customization layers will have unique IDs.
A cache hint, for the layer defined by the customization class. The cache hint defines whether a layer is static or dynamic. If the getCacheHint()
method returns ALL_USERS
, then the customization layer is static. For more information about dynamic customizations, see Section 34.1.2, "Static and Dynamic Customization Content." For more information about CacheHint
values, see Section 34.2.2, "What You May Need to Know About Customization Classes."
Customizations can be used to tailor an application to suit a specific industry domain (verticalization). Each such domain denotes a customization layer and is depicted using a customization class.
To implement seeded customizations using your customization classes:
The cust-config
section (under mds-config
) in the adf-config.xml
must contain a reference to the customization classes (as shown in Example 34-6).
The customization configuration (cust-config
) section provides the customization classes and their precedence for a customized application. See Section 34.2.6, "How to Configure the adf-config.xml file."
The customization classes must be available on JDeveloper's classpath to support seeded customizations.
After creating your customization classes, you can create an extension library that is included in JDeveloper's classpath. (For more information, see Section 34.2.1.4, "Making Your Customization Classes Available to JDeveloper.") At runtime, your customization classes must be available in the EAR-level application class loader.
The layer values must be listed in the CustomizationLayerValues.xml
file.
This file is located in the jdev_install
\jdev
directory. The names of the layers in this file must be consistent with the customization classes. (For more information, see Section 34.3.4, "How to Configure Customization Layers.") JDeveloper uses this file to retrieve layer values at design time.
When JDeveloper is launched in the Customization Developer role, the Customization Context window displays the available customization layers and layer values. You can select the layer and value to which you want to apply customizations in the Customization Context window. For more information about working in the Customization Developer role, see Section 34.3.1, "Introducing the Customization Developer Role." The layer you choose to customize is called the tip layer. For more information, see Section 34.3.3, "Introducing the Tip Layer."
Example 34-1 shows a sample customization class. Note that all customization classes should have a single, no-argument constructor.
Example 34-1 Sample IndustryCC customization class in the mycompany package
package mycompany; import java.io.IOException; import java.io.InputStream; import java.util.Properties; import oracle.mds.core.MetadataObject; import oracle.mds.core.RestrictedSession; import oracle.mds.cust.CacheHint; import oracle.mds.cust.CustomizationClass; public class IndustryCC extends CustomizationClass { private static final String DEFAULT_LAYER_NAME = "industry"; private String mLayerName = DEFAULT_LAYER_NAME; public IndustryCC() { } public CacheHint getCacheHint() { return CacheHint.ALL_USERS; } public String getName() { return mLayerName; } public String generateIDPrefix(RestrictedSession sess, MetadataObject mo) { return new String ("I"); } public String[] getValue(RestrictedSession sess, MetadataObject mo) { // This needs to return the appropriate value at runtime. return new String[] {"financial"}; } }
This example shows the four methods that define how the customization class will work: getCacheHint()
, getName()
, generateIDPrefix()
, and getValue()
.
The return value for getCacheHint()
indicates to MDS how widely visible a metadata object with this customization is, and therefore its likely duration in memory. It also defines whether or not a layer is static or dynamic. In this example, the getCacheHint()
method returns ALL_USERS
, which means the customization layer is static. For more information about CacheHint
values, see Section 34.2.2, "What You May Need to Know About Customization Classes."
The getName()
method returns the name of the customization layer. A SiteCC customization class, for example, might return "site." In this example, the getName()
method returns "industry."
The generateIDPrefix()
method creates an IDPrefix. The IDPrefix is a unique, abbreviated string that identifies the name and value of the layer. It is used as the prefix of the ID for objects created in the customization layer. The default implementation (if no IDPrefix is specified) returns name of the layer concatenated with customization value. For performance reasons, the IDPrefix should be kept short (4 characters or less). Therefore, the default implementation should be overridden. The related getIDPrefix()
method returns the IDPrefix of the customization layer. In this example, the getIDPrefix()
method would return "I" (for "industry").
The getValue()
method returns the customization value (or values) for the customization class. In this example, the getValue()
method returns a single value, "financial," that defines the customization context when combined with the layer name. There are additional techniques for using the getValue()
method described in Section 34.2.1.2, "Implementing the getValue() Method in Your Customization Class."
Note:
The possible layer values corresponding to a layer name are retrieved by JDeveloper in the Customization Developer role from theCustomizationLayerValues.xml
file. The precedence of layers is defined by the order of the customization classes specified in the adf-config.xml
file. The names of the layers must be consistent in these files and in the customization classes.The getValue()
method is used to retrieve the layer value(s) of the customization class based on the application context and the metadata. For example, calling getValue()
on a SiteCC
customization class might return an array with single entry "headquarters
." Typically, the getValue()
method returns an array with a single value, as shown in Example 34-1.
You can also return multiple values from the getValue()
method, as shown in Example 34-2.
Example 34-2 The getValue() Method Returning Multiple Values
public String[] getValue(RestrictedSession sess, MetadataObject mo) { return new String[]{"North America", "US", "CA"} }
When multiple values are returned, customizations applicable to all values are applied. Customizations are applied in the order in which they appear in the array. In this example, North America
customizations are applied over the base application, then US
customizations are applied, and finally CA
.
Note:
Returning multiple values for a customization layer is an advanced concept that is typically unnecessary.The getValue()
method can return a layer value based on the current execution context for the current user, pulled either from static or thread local state maintained by the client, or from properties set by the client on the MDS session and based on the metadata object name. Example 34-3 shows this type of implementation.
Example 34-3 The getValue() Method Returning a Layer Value Based on the Current Execution Context
public String[] getValue(RestrictedSession sess, MetadataObject mo) { if (mo.getName().equals("/sample/abc.jspx")) { return new String[]{"Headquarters"}; } else { return new String[]{"RemoteSite"}; } }
In this example, the getValue()
method uses the getName()
method on the metadata object to determine if the name of the metadata document is "/sample/abc.jspx
". If so, getValue()
returns Headquarters
to apply headquarters customizations. If not, it returns RemoteSite
to apply customizations for remote sites.
Note:
Coding thegetValue()
method to return a value based on the metadata object is an advanced concept that is typically unnecessary. Customization context for dynamic layers is typically determined through facets of the application context, such as user name or responsibility.An additional technique that can be useful during the development cycle is to use an external properties file to specify layer values. Example 34-4 references a properties file (customization.properties
) that stores the layer values.
Example 34-4 The getValue() Method Using a Properties File to Specify Layer Values
public String[] getValue(RestrictedSession sess, MetadataObject mo) { Properties properties = new Properties(); String configuredValue = null; Class clazz = IndustryCC.class; InputStream is = clazz.getResourceAsStream("/customization.properties"); if (is != null){ try { properties.load(is); String propValue = properties.getProperty(mLayerName); if (propValue != null){ configuredValue = propValue; } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return new String[] {configuredValue}; }
When an application using this technique is run in JDeveloper, you can change the layer value in the properties file and refresh the browser to see new customizations being applied. This customization class and properties file combination allows you to maintain the layer value in a separate file so you don't need to modify and recompile Java code to change it for a particular deployment. If you use a customization.properties
file, it must be packaged with the customization classes so that they are loaded from the same class loader.
Example 34-5 shows a sample customization.properties
file. When the IndustryCC
class is loaded with this properties file, the layer value healthcare
is applied.
Use the following procedure to create a customization class.
To create a customization class:
Launch JDeveloper using the Default role, and open the application that you want to make customizable.
In the Application Navigator, right-click the model project and choose New.
Note:
You can alternatively create a separate project for the customization classes. Then you can deploy them to a JAR and import the JAR into your lowest level project (which is typically the model project). This approach increases modularity, making it easier to include them in multiple applications across your company, and easier to patch them centrally.If you use this approach, make sure that there is only one copy of the customization classes in the application and that they are packaged in a JAR so that they are loaded at the EAR level application class loader. By default, adding project dependencies will add the customization classes to the WAR, which will not work correctly after the application is packaged and deployed. For more information about packaging your application for deployment, see Section 36.3.2, "How to Create Deployment Profiles."
In the New Gallery, expand General, select Java Class and then Java, and click OK.
In the Create Java Class dialog, enter a name for the class and the appropriate package.
In the Extends field, enter oracle.mds.cust.CustomizationClass
.
Make sure Implement Abstract Methods is checked and click OK.
Replace the code in the generated file with code like that shown in Example 34-1.
Save your changes and rebuild the project.
This creates the customization class. The sample code uses the package name mycompany
and the class name IndustryCC
. You will need to change these as appropriate for your application.
Note:
Customization classes can be executed frequently, once for each document being accessed to get the layer name and layer value, so take care to ensure their efficiency.After you create the customization classes, you must make them available to JDeveloper so that you can use them when implementing customizations. When working in the Customization Developer role, your customization classes must be available on JDeveloper's classpath.
Because the customization classes are reusable components, you can create a JDeveloper extension to contain them and make them available to JDeveloper. For information about creating and using JDeveloper extensions, see the Writing JDeveloper Extensions topic in JDeveloper Online Help.
However, when you package and deploy your customized application or run it from JDeveloper, the customization classes must be available at the application level on the application's classpath. Therefore it is important to include them in the application (for example, in the model project), and not just as a JDeveloper extension.
As described in Section 34.2.1.1, "Customization Classes," the customization class defines a CacheHint
which specifies the visibility of metadata objects in a customization layer, and therefore its likely duration in memory. This information is used by MDS to decide whether or not to cache a customization, and where to cache it. Any customization layers constructed using this customization class have this cache hint.
The following constants are supported values of CacheHint
:
ALL_USERS
-- The customization is applied globally (non-conditionally) for a given deployment. This constant is used for static customization layers.
MULTI_USER
-- The customization is applied to multiple users.
REQUEST
-- The customization is applied for the duration of the request only.
USER
-- The customization is applied for a single user to documents which are accessed throughout the user's application session. (In web applications the application session is typically a servlet session.)
Like all customizable components, the XML elements of a customizable metadata object must be uniquely identifiable by MDS, and therefore must have a unique, non-null identifier. The component's identifier is used to refer to the element in the customization instructions in the customization layer. The ID property is the identifier for each type of component in an ADF Faces .jspx
or .jsff
file.
To allow for customizations on your JSF and JSP pages, you must enable seeded customizations in the application's view project, which drives some defaults for your pages. This is not necessary for your model and controller projects.
Note:
MDS requires that pages be XML-based to be customized. Therefore, customizations are not allowed on.jsp
files; use .jspx
files instead.To enable seeded customizations in your view project:
Launch JDeveloper using the Default role, and open the application that you want to make customizable.
In the Application Navigator, right-click the view project and choose Project Properties.
In the Project Properties dialog, click ADF View.
Select the Enable Seeded Customizations checkbox, as shown in Figure 34-2.
Click OK.
Save the changes to your project.
If you have pages in your project that were created in an earlier version of JDeveloper, you must make sure that these pre-existing pages are also enabled for seeded customizations. This is only necessary if you migrated the application from an earlier version of JDeveloper and did not generate ids during migration.
To enable seeded customizations in an existing page:
Launch JDeveloper using the Default role, and open the application that you want to make customizable.
Create an audit profile to implement ID tokens for all XML objects in your page.
From the Tools menu, choose Preferences.
In the Preferences dialog, select Audit > Profiles.
In the Rules tab on the Profiles page, deselect all rules.
Select the rule ADF Faces > Component ID Rules > Check for ID When ADF Faces is Present.
From the Default Fix dropdown list, select Generate a unique ID.
Click Save As, then enter an identifiable name for the profile (such as Generate Unique IDs). and click Save.
Click OK to close the Preferences dialog.
In the Application Navigator, select the page for which you want to enable seeded customizations. Alternatively, you can select a project to run the audit on all the files it contains.
From the Build menu, choose Audit filename.
In the Audit dialog, select the profile you created to generate ids and click Run.
Use the Log window to review issues and apply fixes.
When the audit is complete, save your changes.
If you plan to create new resource keys when implementing customizations, you can specify the affected resource bundles using the Application Properties dialog.
To enable customizations in resource bundles:
From the application context menu, choose Application Properties.
In the Application Properties dialog, click Resource Bundles.
Click Add.
In the Select Resource Bundle dialog, navigate to and select the resource bundles for which you want to enable customization.
Click Open.
In the Application Properties dialog, select the checkbox in the Overridden column of the Bundle table.
Click OK.
The application's adf-config.xml
file must have an appropriate cust-config
element in the mds-config
section. The cust-config
element allows clients to define an ordered and named list of customization classes. You use the overview editor for the adf-config.xml
file to add customization classes (see Figure 34-3).
To identify customization classes in the adf-config.xml file:
With the application you want to customize open in JDeveloper, open the Application Resources panel in the Application Navigator.
Expand Descriptors, then expand ADF META-INF.
Right-click adf-config.xml
, and choose Open.
In the overview editor, click the MDS Configuration navigation tab, and then click the Add icon.
In the Edit Customization Classes dialog, search for or navigate to the customization class you have already created.
Select the appropriate class and click OK.
After you have added all of the customization classes, you can use the arrow icons to put them in the appropriate order.
Figure 34-3 shows the overview editor for the adf-config.xml
file with two customization classes added.
The order of the customization-class elements defines the precedence of customization layers. For example, in the code shown in Example 34-6, the IndustryCC
class is listed before the SiteCC
class. This means that customizations at the industry layer are applied to the base application, and then customizations at the site layer are applied.
Example 34-6 Customization Class Order in the adf-config.xml File
<adf-config xmlns="http://xmlns.oracle.com/adf/config"> <adf-mds-config xmlns="http://xmlns.oracle.com/adf/mds/config"> <mds-config xmlns="http://xmlns.oracle.com/mds/config" version="11.1.1.000"> <cust-config> <match path="/"> <customization-class name="com.mycompany.IndustryCC"/> <customization-class name="com.mycompany.SiteCC"/> </match> </cust-config> </mds-config> </adf-mds-config> </adf-config>
When you create a customizable application, you have a base application that includes the pieces necessary for you or someone else to use as the basis for a customized application.
To perform the customization, you must open the application in JDeveloper using the Customization Developer role, as described in Section 34.3, "Customizing an Application."
Oracle ADF components (such as controller, model, and business components objects) must have a unique identifier so that they can be customized. ADF components generated by JDeveloper are created with identifiers by default, with the exception of JSP and JSF pages in your view controller projects. To cause JDeveloper to generate identifiers for components on pages in your view controller projects, you must explicitly specify this at the project level (as explained in Section 34.2.3, "How to Enable Seeded Customizations for View Projects").
Before you implement customizations in an application, make sure that all objects that you intend to customize have the necessary identifiers. In many cases, you can run an audit rule to catch and fix any omissions (as explained in Section 34.2.4, "How to Enable Seeded Customizations in Existing Pages").
Also, take care to ensure the efficiency of your customization classes, because they can be executed frequently, once for each document being accessed to get the layer name and layer value.
Using the Customization Developer role, you can create customizations in a customizable application.
The Customization Developer role is used to customize the metadata in a project. Customization features are available only in this role. When you are in the Customization Developer role, you can do the following:
Create and update customizations
Select and edit the tip layer of a customized application
Remove existing customizations
When you are in the Customization Developer role, the source editor is read-only and the following JDeveloper features are disabled:
Workspace migration
Creation, deletion, and modification of application and IDE connections. You must configure connections in Default role before opening an application in Customization Developer role.
When working with an application in the Customization Developer role, new objects cannot be created, and noncustomizable objects cannot be modified. However, the following content types are customizable:
Portal modules
ADF modules, including ADF Faces, ADF Model, Oracle ADF Business Components, and ADF Controller
Note:
ADF Business Components objects and ADF Model objects are customizable only if a static customization class is selected in the Customization Context window. Otherwise, model and business component objects are read-only.When working in the Customization Developer role, you cannot edit noncustomizable files, such as Java classes, resource bundles, security policies, deployment descriptors, and configuration files. Noncustomizable files are indicated by a lock icon when you are working in the Customization Developer role.
You are also restricted from modifying project settings and customizing certain ADF Business Components features, including service interfaces and business event definitions. Additionally, you cannot refactor, or make changes to customizable files that would, in turn, necessitate changes in noncustomizable files.
The customization features of JDeveloper are available to you in the Customization Developer role. To work in this role, you can either choose it when you start JDeveloper or, if JDeveloper is already running, you can use the Preferences dialog to switch to the Customization Developer role.
To switch to the Customization Developer role in JDeveloper:
From the Tools menu, choose Preferences.
In the Preferences dialog, click the Roles node.
The Roles page of the Preferences dialog displays the different roles that are available to you.
Select Customization Developer, and click OK.
When working in the Customization Developer role, the layer and layer value combination that is selected in the Customization Context window is called the tip layer. The changes you make while in the Customization Developer role are applied to this layer.
The metadata displayed in the JDeveloper editors is a combination of the base metadata and the customization layers up to and including the tip layer, according to the precedence set in adf-config.xml
, with the values specified in the Customization Context window for each layer.
To customize an application, you must specify the customization layers and their values in the CustomizationLayerValues.xml
file so that they are recognized by JDeveloper.
When you open a customizable application in the Customization Developer role, JDeveloper reads the adf-config.xml
file to determine the customization classes to use and their order of precedence. JDeveloper also reads the CustomizationLayerValues.xml
file to determine the layer values to make available in the Customization Context window. If there are layer values defined in the CustomizationLayerValues.xml
file that are not defined in the customization classes listed in the adf-config.xml
file, they are not displayed in the Customization Context window.
Therefore, you can have a comprehensive list of layer values for all of your customization projects in the CustomizationLayerValues.xml
file, and only those appropriate for the current application are available in the Customization Context window. Conversely, you could have a comprehensive list of customization classes for an application in the adf-config.xml
file, and only the subset of layer values that you will work on in your CustomizationLayerValues.xml
file.
Note:
At design time, JDeveloper retrieves customization layer values from theCustomizationLayerValues.xml
file. But at runtime, the layer values are retrieved from the customization class.The names of the layers and layer values that you enter must be consistent with those specified in your customization classes.
To configure design time customization layers for JDeveloper:
Locate and open the CustomizationLayerValues.xml
file.
You can find this file in the jdev
subdirectory of your JDeveloper installation directory (jdev_install
\jdev\CustomizationLayerValues.xml
).
For each layer, enter a cust-layer
element, as shown in Example 34-7.
For each layer value, enter a cust-layer-value
element, as shown in Example 34-7.
Save and close the CustomizationLayerValues.xml
file.
Make sure that the customization class JARs (created in Section 34.2.1.4, "Making Your Customization Classes Available to JDeveloper") are available in the JDeveloper classpath.
Example 34-7 Layers and Layer Values Defined in CustomizationLayerValues.xml
<cust-layers xmlns="http://xmlns.oracle.com/mds/dt"> <cust-layer name="industry" id-prefix="i"> <cust-layer-value value="financial" display-name="Financial" id-prefix="f"/> <cust-layer-value value="healthcare" display-name="Healthcare" id-prefix="h"/> </cust-layer> <cust-layer name="site" id-prefix="s"> <cust-layer-value value="headquarters" display-name="HQ" id-prefix="hq"/> <cust-layer-value value="remoteoffices" display-name="Remote" id-prefix="rm"/> </cust-layer> </cust-layers>
For each layer and layer value, you can add an id-prefix
token. This helps to ensure the uniqueness of the id
, so that customizations are applied accurately. When you add a new element (such as a command button) to a page during customization, JDeveloper adds the id-prefix
of the layer and layer value (determined by the selected tip layer) to the autogenerated identifier for the element to create an id
for the newly added element in the customization metadata file. For example, in Example 34-7, the site
layer has an id-prefix
of "s
" and the headquarters
layer value has an id-prefix
of "hq
". So, when you select site/headquarters
as the tip layer and add a command button to a page, the command button will have an id
of "shqcb1
" in the metadata customization file.
For each layer value, you can also add a display-name
token to provide a human-readable name for the layer value. When you are working in the Customization Developer role, the value of the display-name
token is shown in the Customization Context window for that layer value.
You use the same development procedures and techniques to customize metadata that you use when developing the base application. To implement customizations, however, you must be working in the Customization Developer role and specify the customization context by selecting a tip layer and layer value before editing the metadata. For an application to be customizable, customizations must be enabled in your project. For more information, see Section 34.2, "Developing a Customizable Application."
To customize metadata in JDeveloper:
Launch JDeveloper using the Customization Developer role.
Open the customizable application.
In the Customization Context window, select the layer and value for which you want to implement customizations.
The Customization Context (displayed at the bottom of the Customization Context window) changes to reflect your selection, as shown in Figure 34-4.
Note:
The selection you make in the Customization Context window indicates the context for the customizations that you will implement in JDeveloper. This selection does not directly impact the runtime for the application. At runtime, the customization context is returned from your customization classes. For more information, see Section 34.2.1, "How to Create Customization Classes."Edit the metadata as you typically would during development. For example, right-click an entity object and choose Open. Then edit the object using the overview editor.
Even though you use the overview editor to implement customizations, you do not make changes to the base metadata file. Your changes are stored separately in a customization metadata file.
Note:
To see the uncustomized base metadata, you can select View without Customizations in the Customization Context window.You can optionally choose Remove Customization from the dropdown menu for a property (in the Property Inspector) to clear the existing customization.
Note:
In the Property Inspector, tip layer customizations are indicated by an orange icon, while non-tip layer changes are indicated by a green icon. Remove customization can only be performed in the context in which the customization was added. So you can remove only those customizations that have an orange indicator in the Property Inspector.Choose Save from the File menu to save your changes.
After you have completed your customizations, you can run and test the customized application.
When you implement customizations in an application, JDeveloper creates a metadata file for the customizations and a subpackage to store them in.
The metadata file contains the customizations for the customized object, which are applied over the base metadata at runtime. The new metadata file is named the same as the base file for the object with an additional .xml
extension. For example, if you implement customizations for the browseOrders.jsff
page, the customization metadata file is named browseOrders.jsff.xml
. Or if you implement customizations on the OrderItems
entity object, the base metadata file is named OrderItems.xml
and the customization metadata file is named OrderItems.xml.xml
.
The customization metadata files are stored in a subpackage hierarchy that is created at the same level as the object you customize. The first-level package is named mdssys
, and it contains a package named cust
. The cust
package contains a package for each customization layer for which you have implemented customizations.
For example, say you have a base application that has a package called oracle.fod.model
containing your entity objects, and you have a customization layer named site
with two layer values: headquarters
and remoteoffices
. Then you implement customizations for the OrderItems
entity object at the headquarters
layer value. When you implement these customizations, JDeveloper creates the subpackage hierarchy oracle.fod.model.mdssys.cust.site.headquarters
and stores the customization metadata files there.
Similarly, for pages in your view controller project, JDeveloper creates a directory structure to store the customization metadata files. For example, if you customize the BrowseOrders.jsff
page in the Web Content folder of your view controller project, JDeveloper creates the directory structure mdssys/cust/site/headquarters
under Web Content and stores the customization metadata file there.
In the Customization Developer role, you can use JDeveloper to customize artifacts in an ADF library. This need can arise when, for example, one development team produces task flows as part of a framework service and makes them available to other teams as an ADF library. Then another development team uses one of the task flows in a consuming application, and needs to fine-tune it to fit the requirements of the application.
You can add an ADF library to your project in the Customization Developer role just as you would add it in the Default role. However, in the Customization Developer role, content from an ADF library appears as editable to allow you to implement customizations, whereas in the Default role it is read-only. For more information about working with ADF libraries, see Chapter 33, "Reusing Application Components."
To customize an ADF library artifact:
Open your customizable application in the Customization Developer role.
In the Application Navigator, click the Navigator Display Options icon and choose Show Libraries.
This displays the libraries in the Application Navigator, so that you can explore them and access their artifacts.
Add the desired library to your project if it is not already shown among the libraries in the Application Navigator.
For information about how to do this, see Section 33.3, "Adding ADF Library Components into Projects."
Customize the artifacts just as you would customize other content in your project.
For example, you can drag and drop taskflows from a library to .jspx
or .jsff
pages in a consuming project, drag and drop taskflows from a library to a page or fragment in another library, drag and drop library content or taskflows from the Resource catalog, drag and drop data controls from data control palette to .jspx
or .jsff
pages in a library, edit business components, and drag and drop a data control from a library to the data control palette and then drop to a page in another palette. All these actions would result in customizations of the library.
During the development of enterprise applications, there might be artifacts (such as task flows) that can be reused in multiple applications. To facilitate reuse of these common artifacts they are usually packaged into an ADF library and distributed. This allows you to add the ADF library to the list of libraries on which the consuming application depends on. Then when the application is packaged, the customizations from all such ADF libraries are included in the MAR, which is later deployed to the MDS repository.
Note:
The ADF library provider should take care to ensure that no name conflicts arise due to customizations in the library. In the event that name conflicts arise between customizations packaged in an ADF library and the customizations from the consuming project, the customizations from the ADF library are ignored.When you implement customizations on objects from an ADF library, the customization metadata is stored by default in a subdirectory of the project called libraryCustomizations
. And although you create ADF library customizations at the project level, they are merged together during packaging to be available at the application level at runtime. Essentially, ADF libraries are JARs that are added at the project level, which map to library customizations being created at the project level. However, although projects map to web applications at runtime, the MAR (which contains the library customizations) is at the EAR level, so the library customizations are seen from all web applications.
Therefore, you can customize an ADF library artifact in only one place in an application for a given customization context (customization layer and layer value). Customizing the same library content in different projects for the same customization context would result in duplication in MAR packaging. To avoid duplicates that would cause packaging to fail, implement customizations for a given library in only one project in your application.
For example, say the ADF library you are using contains a page fragment text.jsff
. In the consuming application, customize this library page in only one project. By doing so, customizations are available for all projects in the application that consume this library at runtime.
You are also restricted from customizing an object from an ADF library when your project already contains an object with the same name. In case of duplication, you must manually fix the projects by deleting one of the duplicate documents or deleting one and manually merging the differences into the other.
Similarly, if the ADF library contains seeded customizations for an artifact within a given customization context (customization layer and layer value), you cannot implement customizations for that artifact within the same customization context. In this situation, the ADF library artifact is read-only. You can, however, implement customizations for the artifact within other customization contexts.
For example, say the ADF library you are using contains seeded customizations for the Headquarters
layer value in the Site
layer. When you select this as your tip layer in the Customization Context window, the customized objects in that ADF library are read-only. However, if you select Site
/Remote Site 1
as your tip layer, then the objects are customizable.
Note:
When the consuming application implements customizations on content from an ADF library, the customizations are written to the local project directories, but they are not automatically injected with theweb-app-root
during packaging. For more information, see Section 36.3.2.3, "Creating a MAR Deployment Profile."The location where ADF library customizations are stored (project-dir
\libraryCustomizations
, by default) is automatically included when you create a MAR deployment profile. You can change the location of ADF library customizations on the Project Source Paths > ADF Library Customizations page of the Project Properties dialog. If you change this location after you have created a MAR profile, you must also change the corresponding entry in the contributors list on the User Metadata file group page of the Edit MAR Deployment Profile Properties dialog before packaging. Alternatively, you can re-create the MAR profile to pick up this change. For more information about creating a MAR deployment profile, see Section 36.3.2, "How to Create Deployment Profiles."
After you customize the application, you will want to deploy it. Before you deploy the customized application, you must follow the configuration procedures for setting up your MDS repository, as described in the Oracle Fusion Middleware Administrator's Guide.
An enterprise application can contain model and view-controller projects, and both types of projects can contain customized metadata. The customized metadata is packaged into a MAR for deployment. By default, the customizations from both types of projects are added to a single MAR. For information about how to create a MAR profile, see Section 36.3.2.3, "Creating a MAR Deployment Profile."
For customizations created in JDeveloper to take effect in the application when it is deployed, these customizations need to be made available to the application at runtime. There are two techniques you can use to accomplish this:
Package the customizations along with the application using a MAR.
Create a MAR profile that includes the customization metadata. The MAR profile should be included in the deployed EAR to ensure that the customizations are available at runtime. Your customization classes must be packaged in the EAR such that they are in the application-level class loader.
Note:
If you have only seeded customizations, you do not need to create a MAR to import them into the MDS repository unless you also want to support runtime customizations. If you have seeded customizations and do not have cross-session persistence enabled, the seeded customizations will be packaged in the EAR, by default, and loaded from the classpath.Import the customizations to the runtime repository used by the application.
You typically use this approach if customizations to library metadata need to be applied to an application that is deployed separately. Using this approach, you package the customizations into a JAR and then use the importMetadata
WLST command to import them to the MDS runtime repository. For more information about this and other WLST commands, see the Oracle Fusion Middleware WebLogic Scripting Tool Command Reference.
If your application has customizations on objects from an ADF library, the customization metadata is implicitly included when you create the MAR profile. If you change the location of ADF library customizations in the Project Properties dialog, you must re-create the MAR profile before packaging.
If you plan to use design time at runtime capabilities to add or edit resource keys in the override bundle at runtime, the override bundle must be packaged as part of the MAR. By default, the override bundle is packaged as part of the autogenerated MAR if the application contains seeded customizations. However, if the application doesn't contain seeded customizations, you must explicitly create the MAR deployment profile to package the override bundle. When the MAR profile is created explicitly, override bundle is added and included by default as part of the user metadata.
When you package and deploy the completed customized application, you should do so from the Default role, rather than from the Customization Developer role. For information about how to create a MAR profile, see Section 36.3.2, "How to Create Deployment Profiles."
At runtime, the application applies the customization metadata files over the base application in the order of precedence defined in the cust-config
section of the adf-config.xml
file.
The layer value is retrieved from the customization class at runtime and evaluated in the context the application is running, and the appropriate customizations for that layer value are applied.
When you are customizing an application, you might be using integrated source control or customizing resource strings. When you use these features, there is additional information you need to know.
When working in the Customization Developer role, your source control integration complements the process of customization. If JDeveloper is configured to automatically check out and add new files to source control and you attempt to customize a base document that is available from a source control system, JDeveloper behaves in the following way:
If the corresponding customization file is not already available, then a new customization file is created in source control and the customizations are written to it.
If the corresponding customization file exists, it is checked out and customizations are written to it.
If the corresponding customization file exists and it is already checked out or not yet in version control, customizations are written to it without any further version control operation.
Since the base document is not modified in the Customization Developer role, the base document is not checked out.
If JDeveloper is not configured to automatically check out or add new files to source control, you must manually make the customization files editable and check in newly created customization files to source control. For more information about using source control in JDeveloper, see section Section 1.4.2, "Using a Source Control System."
During the course of customizing your application, you might want to customize the content to use different resource bundle keys or define and use new resource keys.
You can open a customizable application in the Customization Developer role and use the Property Inspector to customize the usages of resource bundle strings. You can change a document to use another already existing resource key in a resource bundle, or create a new resource. For more information about resource bundles, see Section 4.7, "Working with Resource Bundles."
New resource keys (created in the Customization Developer role) are saved to an application-level override bundle (in XLIFF format), and JDeveloper adds an entry to the adf-config.xml
file like the one shown in Example 34-8 to configure the application-level override bundle.
Example 34-8 adf-resourcebundle-config Section in adf-config.xml
<adf-resourcebundle-config xmlns="http://xmlns.oracle.com/adf/resourcebundle/config"> <applicationBundleName> path-to-resource-bundle/bundle-name </applicationBundleName> <bundleList> <bundleId> package.BundleID </bundleId> </bundleList> </adf-resourcebundle-config>
Note:
If an application is not configured for customization, you can open it in the Customization Developer role and define new resource keys by choosing Edit Resource Bundles from the Application menu. However, you cannot change a document to use the new resource keys if it is not configured for customization.Extended metadata is data that describes the metadata content. The extended metadata file contains additional information about the metadata file. One use of this extended information is to identify which parts of the metadata can be customized at runtime (design time at runtime customizations) and who can customize them. For more information about this use of extended metadata properties, see Section 34.4.2, "How to Enable Customization for Design Time at Runtime."
You can open a metadata file (such as a .jspx
file) in JDeveloper and use the Property Inspector to view and edit its extended metadata properties. When you open a metadata file, its extended metadata properties are displayed in the Property Inspector. These properties can be edited to add metadata information at either of the following levels:
File-level: These properties are displayed in the Property Inspector when the root element is selected in the Structure window.
Element-level: These properties are displayed in the Property Inspector when an element is selected in the Structure window. The selected element should have a non-null identifier.
Extended metadata properties are supported for file types that support customizations and can be packaged in a MAR, such as .jsff
and .jspx
files.
Extended metadata for a metadata document is stored in an associated resource description framework (RDF) file. RDF is a W3C standard used to define an XML framework for defining metadata. The RDF file associated with the metadata document is created when the first property value is specified using the Property Inspector. Extended metadata properties are editable only when JDeveloper is in the Default role. RDF files are read-only in the Customization Developer role.
The RDF file is stored in the mdssys
directory. For example, if the metadata being described is stored in the file system as /myapp/data/page1.jspx
, the corresponding extended metadata document would be stored as /myapp/data/mdssys/mdx/page1.jspx.rdf
. The extended metadata document must then be packaged with the corresponding metadata base file and added to the same deployment profile. For more information about creating a MAR deployment profile, see Section 36.3.2, "How to Create Deployment Profiles."
Note:
Don't edit the extended metadata documents directly. Use the Property Inspector.You can use extended metadata properties to provide additional metadata information that is not covered in the metadata file (such as a .jspx
file). When you open the metadata file in JDeveloper, extended metadata properties are displayed in the Property Inspector, which you can use to edit these properties when you are using JDeveloper in the Default role.
For example, suppose you want to deliver a metadata file in some form to external customers. Along with metadata file, you need to provide additional information about the file, such as the creator, subject, description, format, and rights. You can accomplish this by creating an extended metadata property file for your metadata file.
To edit extended metadata properties:
Launch JDeveloper using the Default role.
In JDeveloper, open the appropriate application and project.
In the Application Navigator, select the object for which you want to edit extended metadata properties.
In the Structure window, select the appropriate element (typically the root element).
In the Property Inspector, expand the appropriate node to edit the properties.
To display the Property Inspector with the values for the selected component, choose Property Inspector from the View menu.
Edit the value for the desired property and press Enter.
Choose Save from the File menu to save your work.
If you have edited extended metadata properties for a metadata file, you must package your extended metadata (or RDF) files with the metadata files when you deploy the application.
You can also use extended metadata properties to provide information about which parts of the metadata can be customized at runtime and who can customize the metadata content.
By default, many components (such as tables and panelSplitters) that you can add to a .jspx
page are preconfigured to allow runtime customization to support implicit user personalization (such as changing the order of columns in a table). Some WebCenter components (such as panelCustomizable
) also allow customization in their type definition. For more information about user customization, see Chapter 35, "Allowing User Customizations at Runtime." For more information about WebCenter components, see the Oracle Fusion Middleware Developer's Guide for Oracle WebCenter.
Components that are preconfigured to allow customization need no further modification to enable design time at runtime customizations. If you use them in a .jspx
page, then they are customizable by default. However, the root elements of metadata objects (such as .jspx
pages and page definition files) and other components (such as buttons) that you can add to a .jspx
page are not preconfigured to be customizable at runtime, and must be explicitly configured to allow runtime customizations.
Therefore, depending on the requirements of your application, you will need to modify Customization properties in the following situations:
For components that are preconfigured to allow customization, you can override the default settings to disallow customization.
For components that are not preconfigured to allow customization and metadata objects (such as .jspx
pages), you can override the default settings to allow customization.
For components that are configured to allow customization, you can optionally restrict who is allowed to perform customizations at runtime.
In the Customization group in the Property Inspector, there are two properties that allow you to specify whether customizations for an object are permitted at runtime and who is permitted to do them. The CustomizationAllowed property can be set on any element to specify whether or not it can be customized. The CustomizationAllowedBy property controls which users can customize the element. These settings are not enforced when implementing seeded customizations using JDeveloper, but are instead enforced when customizing the application at runtime (design time at runtime customizations).
For example, say you have a .jspx
page with a form that contains two panels, and you need to allow runtime customization for content in Panel1, but not Panel2. You would set CustomizationAllowed to true
for Panel1, and set it to false
for Panel2. If you need to allow runtime customization on an entire page, you would set CustomizationAllowed to true
for the .jspx
page root.
To edit customization properties:
Launch JDeveloper using the Default role.
In JDeveloper, open the appropriate application and project.
In the Application Navigator, select the object for which you want to edit customization properties.
In the Structure window, select the appropriate element.
In the Property Inspector, expand the Customization node to edit the customization properties.
To display the Property Inspector with the values for the selected component, choose Property Inspector from the View menu.
Edit the property value and press Enter.
For example, to allow runtime customizations on a .jspx
file, select the file and set the CustomizationAllowed property to true
.
Choose Save from the File menu to save your work.
If you have edited customization properties, you must package your extended metadata (RDF) files with the metadata files when you deploy the application.
You can prepare your customized application to accept overrides to the customization configuration (the cust-config
section of the adf-config.xml
file) at runtime on a per-session basis, thus allowing the user to change the way customizations are applied for a given session (or web request).
Consider a scenario where an application is configured with a site
layer and a user
layer and you want to make design time at runtime customizations to the site
layer. If you use the application's customization configuration (defined in the adf-config.xml
file), any customizations that you implement are applied to the user
layer. So, you need to be able to adjust the customization configuration for a given session to allow your customizations to be applied to the site
layer.
Or you have a requirement that an administrator wants to see the base metadata document with the site
layer customizations alone. For cases like this, you need to specify a modified customization configuration, other than what was originally specified in application's adf-config.xml
file.
For each web request, Oracle ADF creates an MDS session. For any MDS customization configuration modifications that apply to a session (web request), the user could programmatically provide modified MDS session options with a new customization configuration to Oracle ADF that would be applied on top of the original MDS configuration while creating a MDS session.
To implement this functionality, use the following ADF interfaces for sessionOptionsFactory
:
oracle.adf.share.mds.SessionOptionsFactory
is the interface you use to specify modified MDS session options for a web request in an ADF application.
SessionOptionsFactory :: oracle.mds.core.SessionOptions createSessionOptions(oracle.mds.core.SessionOptions defaultOptions)
You implement this method to return the modified MDS sessionOptions
to ADF.
oracle.adf.share.config.ConfigUtils
is the public class you can use to register your session options factory with ADF.
ConfigUtils :: public static void setSessionOptionsFactory(ADFContext context, SessionOptionsFactory factory)
See your ADF API documentation for further detail on these interfaces.
Note:
If you are using Oracle Composer components, you can use theComposerSessionOptionsFactory
interface to specify modified MDS session options with Composer.
ComposerSessionOptionsFactory :: public SessionOptions createSessionOptions(SessionOptions defaultOptions, String mode);
oracle.adf.view.page.editor.webapp.WebCenterComposerFilter
loads your ComposerSessionOptionsFactory
implementation from the current thread context class loader. See the Oracle Fusion Middleware Developer's Guide for Oracle WebCenter for more information.
You register your sessionOptionsFactory
with ADF or Composer in a filter implementation so that ADF can get modified session options from your implementation before the MDS session is created in request lifecycle.
Example 34-9 shows how you can implement sessionOptionsFactory
. This example sets a modified customization configuration for the session to use the site
customization layer alone regardless of the customization configuration specified in the adf-config.xml
file. See the Javadoc for oracle.mds
for more information.
Example 34-9 Sample sessionOptionsFactory Class
package mycompany; import oracle.adf.share.mds.SessionOptionsFactory; import oracle.mds.config.CustClassListMapping; import oracle.mds.config.CustConfig; import oracle.mds.config.MDSConfigurationException; import oracle.mds.core.SessionOptions; import oracle.mds.cust.CustClassList; import oracle.mds.cust.CustomizationClass; public class MySessionOptionsFactory implements SessionOptionsFactory { public MySessionOptionsFactory() { super(); } /** * Called to allow the application code to create a new SessionOptions object. * The application code should make sure to read the values from the * defaultOptions object as part of contruction of their new object and make * sure they only override the intended values. * @param defaultOptions * @return modified MDS session options */ public SessionOptions createSessionOptions(SessionOptions defaultOptions) { // create new mds Customization configuration CustConfig custconfig = null; // create customization class array. Just put SiteCC implementation as we // wish to apply site customizations alone. CustomizationClass[] custclassarray = new CustomizationClass[] {new SiteCC()}; CustClassList custclasslist = new CustClassList(custclassarray); // specify the base metdata package namespace mapping on which site // customizations would apply CustClassListMapping[] mappings = new CustClassListMapping[] {new CustClassListMapping("mycompany/package", null, null, custclasslist)}; // create new customization configuration try{ custconfig = new CustConfig(mappings); } catch (Exception ex){ //do nothing } // now return modified sessionOptions to ADF with new mds customization // configuration. Only use newly created customization configuration in here. // For rest of option, use whatever available in defaultOptions. return new SessionOptions(defaultOptions.getIsolationLevel(), defaultOptions.getLocale(), custconfig, defaultOptions.getVersionContext(), defaultOptions.getVersionCreatorName(), defaultOptions.getCustomizationPolicy(), defaultOptions.getServletContextAsObject()); } }