Saturday, April 21, 2018

User Personalization With MDS in Oracle ADF


(ADF/JDeveloper/Weblogic 12.2.1.3, Oracle Database 12.1.0.2)


In this post, I want to list the steps involved in setting up the User Personalization Configuration for an ADF Application with MDS Repository in the Database.

This is all documented very well in Oracle Documentation and a lot of blog posts, but most of the information is scattered across different sources. The errors which are encountered while implementing this may not give much information to find out the actual issue and it can be sometimes frustrating. The error is mentioned in point 7 below.

In this post I will try to put all of the steps together so that anyone who is trying to do this for the first time will find it easy to implement it. I personally found it difficult to find what I was missing and it took a lot of research and help form others to get this working. This particular gap I am mentioning below in the steps 4 and 5

Assuming that you have already done the following ***
ADF Application is enabled with Security
Deployed on a clustered Weblogic Server environment
MDS Repository is already created
Data Source is configured in Weblogic Console.

Personalization will work only if security is enabled as the personalizations are stored against each authenticated user.

1.      First we need to enable the User Customization Settings in the View Controller Project Properties


2.      Then we need to enable the MDS Customization Settings for the ADF Application
This should be done in adf-config.xml file


We may have to go to the source of the file to change the XML as below for the section ‘adf-mds-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="oracle.adf.share.config.UserCC"/>
        </match>
      </cust-config>
      <persistence-config>
        <metadata-namespaces>
          <namespace path="/persdef" metadata-store-usage="MAR_TargetRepos"/>
        </metadata-namespaces>
        <metadata-store-usages>
          <metadata-store-usage id="MAR_TargetRepos" deploy-target="true" default-cust-store="true">
            <metadata-store class-name="oracle.mds.persistence.stores.db.DBMetadataStore"> 
              <property name="jndi-datasource" value="jdbc/mds/DEV_MDS"/> 
              <property name="repository-name" value="mds-APP_MDS"/>
              <property name="partition-name" value="APP_PARTITION"/>
            </metadata-store> 
          </metadata-store-usage>
        </metadata-store-usages>
      </persistence-config>
    </mds-config>
</adf-mds-config>

3.      Select the ADF Faces Components you want the User Personalization to be enabled for

At this stage when we run the application in JDeveloper with Integrated WLS, it may work well as it might use the File based configuration for storing the user personalization settings.

But if you are using an Ant Build Script or Deploy the application from WLS console to a clustered server, then you will have to do one more additional step. And this was what I was missing and took me a while to figure.

4.      We need to create and register a Metadata Repository along with a Partition for the Application

This can be done either manually at the command prompt or using a ‘python’ script.

For this we need to use the Weblogic Scripting Utility that comes along with the JDeveloper installation.
C:\app\oracle\Middleware\jdev12213\oracle_common\common\bin\wlst.cmd

When we run this utility it will give us a set of APIs to call to create and register the repository.
The general steps involved are as follows
                    Connect
                    Register Metadata Repository
                    Create Partition

For Example
    connect(<WLS Admin User>, <WLS Admin Pwd>,  <WLS Admin Console URL>)

    registerMetadataDBRepository(name='mds-APP_MDS', dbVendor='ORACLE', host=<WLS Host>, port=<WLS Port>, 
    dbName=<DB Service Name>, user=<DB Username>, password=<DB Password>, targetServers=<Cluster Name>);
   
    createMetadataPartition('mds-APP_MDS', 'APP_PARTITION');
   
    exit()
   
This can be run on any machine as long as we give the correct server parameters
This is typically a one time operation.

5.      Update the Application EAR file with the Metadata Repository information

Once the application EAR file is built, we need to update the EAR file with the MDS Repository and Partition Information. For this also, we need to use the WLST commands or write a python script.
The general steps involved are as follows
                    Connect
                    Open EAR file
                    Set Application Metadata Repository Information
                    Save the EAR file

For Example
    connect(<WLS Admin User>, <WLS Admin Pwd>,  <WLS Admin Console URL>)
   
    archive = getMDSArchiveConfig(fromLocation=<EAR File Path>)
            
    archive.setAppMetadataRepository(repository='mds-APP_MDS', partition='APP_PARTITION', type='DB', 
    jndi='jdbc/mds/APP_MDS')
   
    archive.save()
   

6.      Now, the EAR file is ready to be deployed to a clustered server with User Personalizations enabled with MDS Repository

7.      Error when deploying without updating the EAR file
     [exec] weblogic.deploy.api.tools.deployer.DeployerException: Task 0 failed: [Deployer:149026]deploy application APP on DefaultServer.
     [exec] Target state: deploy failed on Server DefaultServer
     [exec] weblogic.application.ModuleException: oracle.mds.config.MDSConfigurationException: MDS-01335: namespace "/persdef" mapped to metadata-store-usage "MAR_TargetRepos" but its definition was not found in MDS configuration. :oracle.mds.config.MDSConfigurationException:MDS-01335: namespace "/persdef" mapped to metadata-store-usage "MAR_TargetRepos" but its definition was not found in MDS configuration.
     [exec]     at oracle.mds.config.PConfig.populateNamespaceConfigList(PConfig.java:1499)
     [exec]     at oracle.mds.config.PConfig.loadFromBean(PConfig.java:1166)
     [exec]     at oracle.mds.config.PConfig.<init>(PConfig.java:892)
     [exec]     at oracle.mds.config.MDSConfig.loadFromBean(MDSConfig.java:1288)
     [exec]     at oracle.mds.config.MDSConfig.loadFromElement(MDSConfig.java:1360)
     [exec]     at oracle.mds.config.MDSConfig.<init>(MDSConfig.java:905)
……

8.      Reason for the above error is that even though we have added the MDS Configuration in the adf-config.xml file, when the EAR is built initially, this entry will be removed by Ant. This is the expected behavior according to oracle documentation.

So we are supposed to perform the additional step I mentioned in the step 5 to update the EAR file with the repository information.

9.      Some Observations

a.      User Personalization Settings will persist across multiple deployments of the application
b.      The EAR file size that is updated by the WLST API in the step 5 is much lesser than the original EAR
c.      Once the User starts personalizing the pages, after that if we make changes to the adf-config.xml to remove some components from personalization, the change does not seem to be effective.


Friday, April 20, 2018

Sub Query Workarounds for ADF View Object Design Time Issues in JDeveloper

ADF/JDeveloper 12.2.1.3

In this blog, I will show some workarounds for some specific issues we may see in JDeveloper View Object Wizard

When we are designing a View Object in JDeveloper, especially when we modify the query in the expert mode, in some cases as mentioned below, the wizard does not build the attribute mappings as expected.

  • When the Query has an 'extract' clause
  • When the Query has a table or view accessed from a DBLink 
  • When the Query has a synonym for an object from another Schema

We normally see this behavior when we join attributes from tables with one of the above. 
A General Workaround for these kind of issues is to use a Sub Query. 

  • When we use Extract clause in the query to get an attribute, the attribute is not shown as a selected attribute in the Attribute Mappings. This issue comes especially when we join the ‘extract’ attribute with other attributes





  • When we query a table via a DB Link the attributes from the DB Link are not shown in the ‘Attribute Mappings’. This issue comes especially when we join the ‘dblink’ attributes with other attributes





  • When we query columns from a partitioned table the attributes are not shown in the Attribute Mappings. Below table is partitioned on ‘payroll_date’.This happens especially when we join the attributes with other table attributes.Other best option in this case is if the table is in a different Schema, then we may have to give the Owner Schema Prefix also