Pages

Saturday, July 5, 2008

Customize and personalize your jsf pages with MDS

This large blog entry is about MDS (Metadata Services) which was introduced jdev 10.1.3.2 but for this MDS example I use JDeveloper 11g TP4. In 11g you can use mds in your jsf applications. In this blog I will show you, how to customize a table in a jsf page for a particular user. This is called seeded customization. For this you have to start jdeveloper in the customize mode and change the properties of the jsf components for this particular user. The changes are saved in a separate xml file. Off course this should never be done for a user ( use a role ). When this particular user start the web application the customized page is shown. Other users will only see the original page.
We can also use MDS to personalize the jsf pages. The user can change the jsf pages at runtime. This is called User Customization or change persistence. In the web application we have to define what the user can change. In this blog I will allow the user to change the order of columns in a table and the user can change the width of a column. The changes are saved in a MDS repository ( I will use a file based mds repository).
Step 1 is to create a fusion web application. Add database table to the bc4j model project. So we can use this as table in a jsf page then we have to change the mds properties of the viewcontroller project. See the picture what to change.
  • We have to enable Enable User customations then Across Sessions using MDS and at last Enable Seeded Customizations. Across sessions will store the changes in the mds repository, so the next time the user still sees the changes.
    Step 2 is the configuration of the adf-config.xml file

    In this file we have to add three things. The first thing we have to do is to define a mds repository. Make sure that you add the following folders ViewController/public_html , ViewController/adfmsrc and Model/src to the metadata-path property.
    The second thing are the customizations classes. You can use different classes at the same time. I use in this blog only one ( UserCC ) . You can also use SiteCC or SecurityRoleCC.

  • Now we only have to define which changes are stored in the mds repository


      In my case you can change the order of culumns in a table and the width of the column.
      Here is my adf-config.xml

      <?xml version="1.0" encoding="windows-1252" ?>
      <adf-config xmlns="http://xmlns.oracle.com/adf/config"
      xmlns:sec="http://xmlns.oracle.com/adf/security/config">
      <sec:adf-security-child xmlns="http://xmlns.oracle.com/adf/security/config">
      <CredentialStoreContext credentialStoreClass="oracle.adf.share.security.providers.jps.CSFCredentialStore"
      credentialStoreLocation="../../src/META-INF/jps-config.xml"/>
      <sec:JaasSecurityContext initialContextFactoryClass="oracle.adf.share.security.JAASInitialContextFactory"
      jaasProviderClass="oracle.adf.share.security.providers.jps.JpsSecurityContext"
      authorizationEnforce="true"
      authenticationRequire="true"/>
      </sec:adf-security-child>
      <app-config type="MDS" name="default"
      xmlns="http://xmlns.oracle.com/adf/mds/config">
      <mds-config version="11.1.1.000" xmlns="http://xmlns.oracle.com/mds/config">
      <persistence-config>
      <metadata-namespaces>
      <namespace path="/" metadata-store-usage="one"/>
      </metadata-namespaces>
      <metadata-store-usages>
      <metadata-store-usage id="one">
      <metadata-store name="mymetadatastore"
      class-name="oracle.mds.persistence.stores.file.FileMetadataStore">
      <property name="metadata-path"
      value="D:/projecten/workspace/11g/mds_user_cc/ViewController/public_html;D:/projecten/workspace/11g/mds_user_cc/ViewController/adfmsrc;D:/projecten/workspace/11g/mds_user_cc/Model/src"/>
      </metadata-store>
      </metadata-store-usage>
      </metadata-store-usages>
      </persistence-config>
      <cust-config>
      <match>
      <customization-class name="oracle.adf.share.config.UserCC"/>
      </match>
      </cust-config>
      </mds-config>
      </app-config>
      <adf-faces-config xmlns="http://xmlns.oracle.com/adf/faces/config">
      <persistent-change-manager>
      <persistent-change-manager-class>
      oracle.adf.view.rich.change.MDSDocumentChangeManager
      </persistent-change-manager-class>
      </persistent-change-manager>
      <taglib-config>
      <taglib uri="http://xmlns.oracle.com/adf/faces/rich">
      <tag name="column">
      <attribute name="displayIndex">
      <persist-changes>true</persist-changes>
      </attribute>
      <attribute name="width">
      <persist-changes>true</persist-changes>
      </attribute>
      </tag>
      </taglib>
      </taglib-config>
      </adf-faces-config>
      </adf-config>

      We are ready with the MDS settings. Now we can add security to the project and add some example users. I use the ADF Security wizard for this. The wizard is located in the tools menu. This are the wizard steps. 1. enforce authorization 2. no identity store 3. Enable Credential store 4. No policy store 5. No anomymous providor 6. Select idstore.loginmodule 7. HTTP Basic authentication with jazn.com as realm and press finish.
      Let's create two test users named test and test1. Go the tools menu and select the preferences menu item.

      Open the embedded oc4j server preferences and add the user test and test1 to the jazn.com identity store. Create a new role users and those users to this role.
      At last we can create the jsf page with a table ( drag a viewobject from the datacontrol and drop this on the page select a readonly table). You have to add a button with no action to the page too. This is necessary else the changes are not submitted to mds repository.

      We have to check if the customization is enabled on the page. Select the jsp:root in the structure window and see in the property window if customization is allowed. The second thing we have to check if there is a unique customizationId on every table column. Select the table column, go to the property window -> behavior -> advanced -> customizationId
      Now we can go the page definition to add security to this page. Select the page definition permission value by the permission class combobox and select the view action to all the operations.

      We have to add the view permission to the users role. go to the structure window of the pagedef and the select the pagedef. Use the right button to select edit authorization menu item.

      Select all the options by the users role.

      Finally we can run the web application. If we log in as test or test1 and change the size of a column ( press the submit button) or the change the column order we will see that these setting are stored in the public_html folder. Every user has it's own folder and page xml.

      This is how a mds xml looks like for a particular user.


      The second part is about seeded customizations. Here can the developer customize the page for a particular user. In this blog I will make sure the salary column has a red background with white characters for only the user test. First we have to change the CustomizationLayerValues.xml in the jdev folder. Here we have to add the users test and test1 to the user custimatization layer.

      Startup jdeveloper and select the customization developer. If you don't get this option you have to go the preferences windows ( tools menu) and go to the roles entry. Here you can change the role.

      We can see a new window called Customizations. In this window we can select the test user.

      If we open the jsf page and change the properties of the jsf components then these changes are stored in the mds repository under the selected user in the customizations window.
      We can start the web application again. First we use the test user.

      Now we use the test1 user.

      I hope you got a good impression what MDS can do for you.

      8 comments:

      1. Great! Thanks for the writeup. One note is that if you have Enable User Customizations Across Sessions using MDS or Enable Seeded Customizations enabled, the default for any new pages will be to allow customization and customization ids will always be auto generated for your components. If you have existing pages, you will need to do what you indicated in your entry. However, there are two audit rules under 'ADFFaces MDS Integration Rules' that will identify all components that do not have a customization id and provide a way to mass assign the customizationid with the 'fix all' feature.

        ReplyDelete
      2. Superb Post, even as a beginner for ADF, i was able to understand your post very clearly, thanks for your step by step mode, keep posting more, thank you very much

        ReplyDelete
      3. Hi,

        how to use seeded customization for roles instead of users as suggested in your blog?

        regards
        Peter

        ReplyDelete
      4. Hi Peter,

        you can use roles too but I think you can use it only for page Customizations.

        Change adf-config.xml and add an extra Customizations class and use
        SecurityRoleCC.

        change the customizationLayerValues.xml in the jdev folder and add roles with its values.

        Startup jdeveloper in customization mode and select the right role and do the changes.

        the rest is the same.

        ReplyDelete
      5. Edwin,

        Thanks for the useful info in your blog post. I managed to get User Customization working from within JDeveloper (11g Technical Preview 4), ie. using the embedded OC4J.

        I know there isn't an 11g standalone OC4J available, so we run an instance of the OC4J that ships with JDeveloper TP4 by simply running the startup script in the jdev/bin directory.

        However, I cannot get User Customization working when I run OC4J "standalone" like that. It reads values from the files in the "metadata-path" as defined in adf-config.xml, but when I change, say, a table column width and submit the form, then it doesn't write those changes back to the file.

        The only difference I've noticed so far is that when I select "Enable User Customizations" and choose "Across Sessions using MDS" in JDeveloper, it adds a few things to our .jpr project file, which is not used when running standalone OC4J.

        Have you, or anyone, managed to get User Customization working with a "standalone" OC4J?

        Thanks,
        Johan.

        ReplyDelete
      6. Hi can you check the ear if all the files are included.

        And maybe your metadata-path has changed because your are now running the app in the applications folder of the oc4j container.

        thanks Edwin

        ReplyDelete
      7. Hi,

        I am new to JDev11/ADF and I need to implement user customization persistence acoss sessions using MDS for an application which consists of multiple model, view projects. I have some questions related to that:
        1. In the adf-config.xml file, is it possible to specify a relative path value for "metadata-path" property ? e.g: something like "../../prj_name/ViewController/public_html". If it is possible should it be relative to the location where adf-config.xml file is ?
        2. Should I set "Enable User Customizatios -> Across Sessions using MDS" for all view projects ?
        3. When I try to run the main page, I am getting the following error:
        SEVERE: Failed to build object name for MDSAppConfig.
        Jul 10, 2009 10:40:05 AM oracle.adf.mbean.share.config.ADFConfigMXBeanImpl configObjectReloaded
        SEVERE: Failed to reload the config object.
        java.lang.RuntimeException: Failed to build object name for MDSAppConfig.
        at oracle.adf.mbean.share.config.ADFConfigMXBeanImpl.registerBean(ADFConfigMXBeanImpl.java:235)
        at oracle.adf.mbean.share.config.ADFConfigMXBeanImpl.configObjectReloaded(ADFConfigMXBeanImpl.java:91)
        at oracle.as.jmx.framework.util.PMConfigMBeanSupport.setConfigObject(PMConfigMBeanSupport.java:125)
        at oracle.as.jmx.framework.util.DocumentChangeListenerSupport.documentChanged(DocumentChangeListenerSupport.java:161)
        at oracle.as.config.notification.filesystem.WatchingDocumentChangeNotifier$DocumentChangeListenerWrapper.documentChanged(WatchingDocumentChangeNotifier.java:446)
        at oracle.as.config.notification.filesystem.WatchingDocumentChangeNotifier.checkUsingListeners(WatchingDocumentChangeNotifier.java:180)
        at oracle.as.config.notification.filesystem.WatchingDocumentChangeNotifier.checkFiles(WatchingDocumentChangeNotifier.java:126)
        at oracle.as.config.notification.filesystem.WatchingDocumentChangeNotifier.run(WatchingDocumentChangeNotifier.java:115)
        at java.lang.Thread.run(Thread.java:619)
        Caused by: java.lang.NullPointerException
        at oracle.adf.mbean.share.config.ADFConfigMXBeanImpl.buildObjectName(ADFConfigMXBeanImpl.java:213)
        at oracle.adf.mbean.share.config.ADFConfigMXBeanImpl.registerBean(ADFConfigMXBeanImpl.java:229)
        ... 8 more

        Thank you,
        Alina

        ReplyDelete
      8. Hi please take a look at my latest post this will work with 11g http://biemond.blogspot.com/2009/07/customize-and-personalize-your-jsf.html

        Oracle has change it and in the EM website you can change the file repos to a database.

        ReplyDelete