Monday, August 8, 2016

Seeded Customization : Understanding XML

Seeded Customization :
The very importance part of Oracle ADF framework is MDS. And this is what it’s make biggest different among Java EE framework.
If you observed or everyone know that ADF is heavily relay on XML and same applicable with MDS too. MDS is very wide it is not only used in ADF but other oracle fusion middleware application too.You will able to found a lot of blogs and documents which explained the same topic.
Therefore I will not explained basic thing here which include configuration and enabling customization. 

You can customize Oracle ADF application which basically follow in below category.
1-Seeded Customization
2-User Customization.

This post is limit to seeded customization.

User Case :
Adding component : The this requirement come under seeded customization. I have one page where I am showing all the employee records from employee table of HR schema. However I am only showing four column (employee id , first name , last name and email ). But for site customization layer I need to show one more column. I am using SiteCC customization class which come with Oracle ADF.

1-I have created application with above requirement. And also preconfigure customization layer and open jdeveloper into customization development.If you observer below screen most of files are locked which mean you cannot write code however xml file are available for change.


The below XML file is not available for changes.

1-adfm.xml
2-adf-setting.xml
3-faces-config.xml
4-trinidad-config.xml
5-web.xml
6-All the file under META-INF

Which make sense , there is no purpose of allow customization in these files.

What does this means ? It mean that we can customize pagedef file , data control files , taskflow flies , entity object , view object and application module , fragment pages.

2-After opening jdeveloper in customization mode , I have drag and drop salary attribute from data control to the page and I have observed the below changes.

a-Change inside the fragment page.


<mds:customization version="12.2.1_20151011.0031" xmlns:mds="http://xmlns.oracle.com/mds">
<mds:insert parent="t1" position="last" xmlns:af="http://xmlns.oracle.com/adf/faces/rich"> <af:column xmlns:af="http://xmlns.oracle.com/adf/faces/rich" headerText="#{bindings.EmployeeView1.hints.Salary.label}" id="sc1">

<af:outputText xmlns:af="http://xmlns.oracle.com/adf/faces/rich" value="#{row.Salary}" shortDesc="#{bindings.EmployeeView1.hints.Salary.tooltip}" id="sot1">

<af:convertNumber xmlns:af="http://xmlns.oracle.com/adf/faces/rich" groupingUsed="false" pattern="#{bindings.EmployeeView1.hints.Salary.format}" />

</af:outputText>

</af:column>

</mds:insert>

</mds:customization>


b-Change inside the page def file.

<mds:customization version="12.2.1_20151011.0031" xmlns:mds="http://xmlns.oracle.com/mds">
<mds:insert parent="EmployeeView1(xmlns(mds_ns1=http://xmlns.oracle.com/adfm/uimodel))/mds_ns1:nodeDefinition[@Name='EmployeeView10']/mds_ns1:AttrNames" position="last">
<Item Value="Salary" xmlns="http://xmlns.oracle.com/adfm/uimodel" />
</mds:insert>
</mds:customization>


 If you observer able XML file which is outcome of dragging and dropping component. I feel oracle use DOM java API to parse XML file.

1-First let us try to understand fragment file code. (EmployeeHome.jsff.xml)

The page start and end with <mds:customization>. Since i have added component therefore the child component is <mds:insert>. If you observer this you can see it has parent and position attribute. parent attribute value is ="t1" which is id of table. and since i have added as last therefore position is last.

2-EmployeeHomePageDef.xml.xml file.
This is also start and end with <mds:customization>  and then insert tag.


You can find Sample Application from below location.
1-https://github.com/prateekazam/SeededCustomizationApp.

And i have used jdeveloper 12.2.1.0







Wednesday, July 6, 2016

Customization on Declative component in oracle ADF

Hi All,

Today i will be explaining about how customization work on ADF DC component. This is not a new topic however i will go beyond already present information and i will explain something more and new.It is pretty straight forward and there are a lot of posts and information are present on internet world therefore i am not going to write anything about DC.

The post is basically consist of three main section.The first section is customizing declarative component , the second section is customizing declarative component child element and third section is just a prove that we should always used jspx, jsff  and jsf for Facelets extension file, In 12c we can defined declarative component with xhtml extension {Facelets }.

Section 1-Customization on Declarative component :

i-I have created on declarative component which have only one output text component. Code is below.

<?xml version='1.0' encoding='UTF-8'?>
<af:componentDef xmlns:af="http://xmlns.oracle.com/adf/faces/rich" var="attrs"
                 componentVar="dcComp" definition="private"
                 xmlns:afc="http://xmlns.oracle.com/adf/faces/rich/component">
    <af:xmlContent>
        <afc:component>
            <afc:description/>
            <afc:display-name>JSFDC</afc:display-name>
            <afc:attribute>
                <afc:attribute-name>backGroundColor</afc:attribute-name>
                <afc:attribute-class>java.lang.String</afc:attribute-class>
            </afc:attribute>
            <afc:attribute>
                <afc:attribute-name>visible</afc:attribute-name>
                <afc:attribute-class>java.lang.Boolean</afc:attribute-class>
                <afc:default-value>true</afc:default-value>
            </afc:attribute>
            <afc:component-extension>
                <afc:component-tag-namespace>dc.component</afc:component-tag-namespace>
                <afc:component-taglib-uri>http://adfwithejb.blogspot.com</afc:component-taglib-uri>
            </afc:component-extension>
        </afc:component>
    </af:xmlContent>
    <af:panelGroupLayout id="dc_pgl1" inlineStyle="#{attrs.backGroundColor}"
                         visible="#{attrs.visible}">
        <af:outputText value="I Am inside Declarative component" id="dc_ot1"/>
    </af:panelGroupLayout>
</af:componentDef>

ii-Then, i have used this component inside one page , i have used this component twice on same page and code is below.

<f:view xmlns:af="http://xmlns.oracle.com/adf/faces/rich" xmlns:dc="http://adfwithejb.blogspot.com" xmlns:f="http://java.sun.com/jsf/core">
    <af:document id="d1" title="Testing.jsf">
        <af:form id="f1">
            <af:panelstretchlayout id="psl1">
                <f:facet name="start">
                <f:facet name="end">
                <f:facet name="top">
                    <af:toolbar id="t1">
                        <af:button actionlistener="#{backingBeanScope.SampleBackingBean.onClickMDS}" id="b1" text="Save">
                    </af:button></af:toolbar>
                </f:facet>
                <f:facet name="bottom">
                <f:facet name="center">
                    <af:panelsplitter binding="#{backingBeanScope.SampleBackingBean.panelSplitterBinding}" id="ps1">
                        <f:facet name="first">
                            <dc:jsfdc binding="#{backingBeanScope.SampleBackingBean.dcSampleBinding}" id="dcs1">
                        </dc:jsfdc></f:facet>
                        <f:facet name="second">
                            <dc:jsfdc id="dcs2">
                        </dc:jsfdc></f:facet>
                    </af:panelsplitter>
                </f:facet>
            </f:facet></f:facet></f:facet></af:panelstretchlayout>
        </af:form>
    </af:document>
</f:view>

iii- On the same page there is one command button which save visible property into MDS repository programmatically.

    public void onClickMDS( ActionEvent actionEvent )
    {
        MDSUtils.persistComponentAttribute( dcSampleBinding , "visible", false );
        AdfFacesContext.getCurrentInstance().addPartialTarget( panelSplitterBinding );
    }

The above code are pretty straight forward. Below is the generated XML document.
<?xml version = '1.0'?>
<mds:customization version="12.2.1_20151011.0031" xmlns:mds="http://xmlns.oracle.com/mds" motype_local_name="view" motype_nsuri="http://java.sun.com/jsf/core">
   <mds:modify element="dcs1">
      <mds:attribute name="visible" value="false"/>
   </mds:modify>
</mds:customization>

So the conclusion of customization declarative component inside page is same as customization of any adf component.

Section  2: Customizing any Child of declarative component :

This section is little tricky but also straight forward. The main point is that the customization on child component of the declarative component is different than customization on any adf component. Customization on normal component will persist against the same page.I have used the same declarative component and now instead of persisting on declarative component, now i am trying to persist it's first child. Now i want to change background color of the panel group layout. Therefore updating inlineStyle property.

        public void onClickMDS(ActionEvent actionEvent) {
        List<UIComponent> children = dcSampleBinding.getChildren(); // getting the child list from declarative component binding
        //MDSUtils.persistComponentAttribute( dcSampleBinding , "visible", false );  //This is for declative declarative
        MDSUtils.persistComponentAttribute(children.get(0), "inlineStyle", "background-color:InfoBackground;");  //saving for child component.
        AdfFacesContext.getCurrentInstance().addPartialTarget(panelSplitterBinding);
    }

If you observer above code , now i am persisting customization for child component of declarative component. The location of generated XML file is against the declarative component not the component where we used this.


And generated file location is  system12.2.1.0.42.151011.0031\o.mds.ide.deploy.base\adrs\DCCustomizationSample\AutoGeneratedMar\mds_adrs_writedir\component\mdssys\cust\user\testuser 

Which if you observe,this location it is same where the declarative component is created folder name is component.

Below is XML file code.

<?xml version = '1.0' encoding = 'UTF-8'?>
<mds:customization version="12.2.1_20151011.0031" xmlns:mds="http://xmlns.oracle.com/mds" motype_local_name="componentDef" motype_nsuri="http://xmlns.oracle.com/adf/faces/rich">
   <mds:modify element="dc_pgl1">
      <mds:attribute name="inlineStyle" value="background-color:InfoBackground;"/>
   </mds:modify>
</mds:customization>

If you pay close attention on above code, the customization is save against id dc_pgl1 which is id of panel group layout. But the disadvantage of this is this customization will applicable whole application. Since i have used this component twice on same page we can see this apply on both page.



Perhaps you are thinking this is not right and definitely there is some way to solve this problem. And yes you are right we can solve this issue via creating one new attribute for declarative component and refer this property where we need.

In this case i have created one new attribute called backGroundColor for declarative component and referring this to panel group layout like inlineStyle="#{attrs.backGroundColor}". So when you have this kind of requirement please exposed via declarative component property.

Section 3: In this section , i would like to explain the file extension also used for customization. And below information is mentioned on Oracle site.
https://docs.oracle.com/middleware/1212/adf/ADFFD/customize.htm#ADFFD19642

MDS requires that pages be XML-based to be customized. Therefore, customizations are not allowed on .jsp files; use .jspx files instead.
Additionally, facelets files must have a .jsf extension to be customizable. MDS uses this extension to recognize it as a Facelets file.

I have tried to see how and what error we get if we do not follow above guide like. I have created one declarative component which .xtml extension. and try to persist one property.




And if you are try to save this , you will get below error.

<oracle.adf.view> <MDSDocumentChangeManager> <addDocumentChangeWithOutcome> <Attempt to persist a DocumentChange failed : >
oracle.mds.exception.MDSRuntimeException: MDS-02401: The operation ModifyAttribute on the panelGroupLayout node is not allowed.  
oracle.mds.exception.MDSRuntimeException: MDS-02406: Customization of /component/DCXHTML.xhtml#(xmlns(af=http://xmlns.oracle.com/adf/faces/rich))/af:componentDef/af:panelGroupLayout/@visible is not allowed because it is not explicitly allowed by any type definition nor any extended metadata entry.
    at oracle.mds.core.ChangeHandler.handleChangeEvent(ChangeHandler.java:543)
    at oracle.mds.internal.model.event.ChangeEventDispatcherUtil.dispatchEvent(ChangeEventDispatcherUtil.java:191)
    at oracle.mds.internal.model.event.dom.DOMMutationEventAdapter.handleEvent(DOMMutationEventAdapter.java:507)
    at oracle.xml.parser.v2.XMLNode.dispatchEvent(XMLNode.java:1394)
    at oracle.xml.parser.v2.XMLNode.dispatchEvent(XMLNode.java:1435)
    at oracle.xml.parser.v2.XMLNode.fireDOMMutationEvent(XMLNode.java:3962)
    at oracle.xml.parser.v2.XMLAttr.setNodeValue(XMLAttr.java:668)
    at oracle.xml.parser.v2.XMLElement.xdkAddAttr(XMLElement.java:3483)
    at oracle.xml.parser.v2.XMLElement.setAttribute(XMLElement.java:1143)
    at org.apache.myfaces.trinidad.change.AttributeDocumentChange.changeDocument(AttributeDocumentChange.java:83)
    at oracle.adf.view.rich.change.MDSDocumentChangeManager._applyChanges(MDSDocumentChangeManager.java:307)
    at oracle.adf.view.rich.change.MDSDocumentChangeManager._addDocumentChangeImpl(MDSDocumentChangeManager.java:271)
    at oracle.adf.view.rich.change.MDSDocumentChangeManager.addDocumentChangeWithOutcome(MDSDocumentChangeManager.java:177)
    at dc.view.beans.MDSUtils.persistComponentAttribute(MDSUtils.java:25)
    at dc.view.beans.SampleBackingBean.onClickMDSSecond(SampleBackingBean.java:45)


"is not allowed because it is not explicitly allowed by any type definition nor any extended metadata entry."

Just for your information i have change log to finest for 
MDSDocumentChangeManager class.




Please is code.

https://github.com/prateekazam/DCCustomizationSample