In my article ADF Badge Button Component I showed how to build a special button with a notification ‘badge’:

The declarative component of this sample was build using JDev 11g (11.1.1.9.0 to be exact).

I received a couple of question on how to work with this declarative component in JDev 12c projects. In general, you can use the same source and build the declarative component in JDev 12c. However, as JDev 12c is using a different document type, Facelets instead of JSPX XML, you can use the badge button only on JSPX type pages.

So, in this blog, I show how to create a declarative component which is usable in Facelets type pages. I don’t change the behavior of the badge button but reuse the code. This blog is more about how to create a declarative component in 12c and show the differences to 11g.

JSPX vs. Facelets

With the introduction of JSF 2.0 (JavaServer Faces 2.0 Overview and Adoption Roadmap in Oracle ADF Faces and Oracle JDeveloper 11g) a new document type Facelets was introduced. The difference and the motivation behind this is outlined in the document.

We are only interested in the fact that you can’t mix components designed for JSP XML pages or fragments with Facelets type pages or fragments. This means that you can’t add the badge button created for 11g to a jsf page of jsff fragment of type ‘Facelet’.

Building a Declarative Component for 12c

We start from the old application workspace I created for the 11g implementation. Opening this workspace will migrate it to the 12c.  At the end of the blog, you’ll find a link to download the final workspace for 12c.

After the migration we add a new project ‘BBB12cDeclarativeComponent’ of type ‘ADF ViewController Project’ to the workspace:

After creating a new project for the 12c badge button, we create a new ‘Declarative Component’ in the ‘Web Content’ folder. In the wizard, we now select ‘Facelets’ as the document type (3rd image below). Selecting ‘Facelets’ will create the 12c kind of declarative component.

Once we finished the wizard, we get the skeleton declarative component in the ‘BadgeButton12c.jsf’ file. If you got a file name ‘BadgeButton.jspx’ you did not set the document type to ‘Facelets’.

<?xml version='1.0' encoding='UTF-8'?>
<af:componentDef xmlns:af="http://xmlns.oracle.com/adf/faces/rich" var="attrs" componentVar="compButton"
                 definition="public"
                 xmlns:afc="http://xmlns.oracle.com/adf/faces/rich/component">
    <af:xmlContent>
        <afc:component>
            <afc:description/>
            <afc:display-name>BadgeButton12c</afc:display-name>
            <afc:attribute>
                <afc:attribute-name>label</afc:attribute-name>
                <afc:attribute-class>java.lang.String</afc:attribute-class>
            </afc:attribute>
            <afc:attribute>
                <afc:attribute-name>badgeText</afc:attribute-name>
                <afc:attribute-class>java.lang.String</afc:attribute-class>
            </afc:attribute>
            <afc:component-extension>
                <afc:component-tag-namespace>de.hahn.blog.component12c</afc:component-tag-namespace>
                <afc:component-taglib-uri>/hahnCompLib12c</afc:component-taglib-uri>
                <afc:method-attribute>
                    <afc:attribute-name>baActionListener</afc:attribute-name>
                    <afc:method-signature>void method(javax.faces.event.ActionEvent)</afc:method-signature>
                </afc:method-attribute>
                <afc:method-attribute>
                    <afc:attribute-name>baAction</afc:attribute-name>
                    <afc:method-signature>java.lang.String method()</afc:method-signature>
                </afc:method-attribute>
            </afc:component-extension>
        </afc:component>
    </af:xmlContent>
</af:componentDef>

Now we can copy the code from the original sample written for 11g and copy it after the componentDef tag. Once you copied the code from the original sample you have to change the EL used to address the action and the actionListener to match the componentVar property in the componentDef tag. To make this distinguishable from the 11g sample, I changed the componentVar to ‘compButton’. The other change is to use an af:button tag instead of the af:commandButton tag. While the af:commandButton tag can still be used, 12c application should use the af:button tag.

The final code looks like

<?xml version='1.0' encoding='UTF-8'?>
<af:componentDef xmlns:af="http://xmlns.oracle.com/adf/faces/rich" var="attrs" componentVar="compButton"
                 definition="public"
                 xmlns:afc="http://xmlns.oracle.com/adf/faces/rich/component">
    <af:xmlContent>
        <afc:component>
            <afc:description/>
            <afc:display-name>BadgeButton12c</afc:display-name>
            <afc:attribute>
                <afc:attribute-name>label</afc:attribute-name>
                <afc:attribute-class>java.lang.String</afc:attribute-class>
            </afc:attribute>
            <afc:attribute>
                <afc:attribute-name>badgeText</afc:attribute-name>
                <afc:attribute-class>java.lang.String</afc:attribute-class>
            </afc:attribute>
            <afc:component-extension>
                <afc:component-tag-namespace>de.hahn.blog.component12c</afc:component-tag-namespace>
                <afc:component-taglib-uri>/hahnCompLib12c</afc:component-taglib-uri>
                <afc:method-attribute>
                    <afc:attribute-name>baActionListener</afc:attribute-name>
                    <afc:method-signature>void method(javax.faces.event.ActionEvent)</afc:method-signature>
                </afc:method-attribute>
                <afc:method-attribute>
                    <afc:attribute-name>baAction</afc:attribute-name>
                    <afc:method-signature>java.lang.String method()</afc:method-signature>
                </afc:method-attribute>
            </afc:component-extension>
        </afc:component>
    </af:xmlContent>
    <af:resource type="css">
        .badge {
        background:             radial-gradient( 5px -9px, circle, white 8%, red 26px );
            background:    -moz-radial-gradient( 5px -9px, circle, white 8%, red 26px );
            background:     -ms-radial-gradient( 5px -9px, circle, white 8%, red 26px );
            background:      -o-radial-gradient( 5px -9px, circle, white 8%, red 26px );
            background: -webkit-radial-gradient( 5px -9px, circle, white 8%, red 26px );
        background-color: red;
        border: 2px solid white;
        border-radius: 12px; /* one half of ( (border * 2) + height + padding ) */
        box-shadow: 1px 1px 1px black;
        color: white;
        font: bold 15px/13px Helvetica, Verdana, Tahoma;
        height: 16px; 
        padding: 4px 3px 0 3px;
        text-align: center;
        min-width: 14px;
        margin: 0px 0px 20px -10px;
        position: relative;
    }
    </af:resource>
    <af:panelGroupLayout id="pgl1" layout="horizontal">
        <af:button text="#{attrs.label}" id="cb1" shortDesc="55" partialSubmit="false"
                   actionListener="#{compButton.handleBaActionListener}"
                              action="#{compButton.handleBaAction}"/>
            <af:outputText value="<div class='badge'>#{attrs.badgeText}</div>" id="ot1" partialTriggers="cb1" escape="false"/>
    </af:panelGroupLayout>
</af:componentDef>

Adding the declarative component to the faces palette

You already know, that to use the declarative component in a project, you first have to add it to the component palette. The difference to the 11g sample is that we have to choose a different node in the project definition to add the library.

First, we need to deploy the declarative component project to an ADF Library. For this, all we need to do is to execute the deployment profile created with the project

Next, we add a ‘File System’ resource which points to the folder the jar is created in

And the jar should show up

To make it usable in the view controller project, we have to add the jar to the project

Now, when we look into the view controller projects properties, we find the new declarative component in the ‘Facelets Tags Libraries’ node. In JDev 11g the tab libraries can be found in the node ‘JSP Tag Libraries’. Again, the difference is where the tags or declarative component are usable. You use JSP tags in JSP XML files and you use Facelets tags in JSF files.

Next step is to create a new JSF Page in the adfc-config.xml, the unbounded task flow.

Again, we make sure to select ‘Facelets’ as document type as we otherwise will not be able to use the declarative component created for ‘Facelets’.

The layout of the page is similar to the one for 11g. 12c uses a panelGridLayout instead of the panelStretchLayout, but that’s all.

As we are now using a JSF page and added the 12c component library and find the badgeButton in the component palette

and use this on the page. The final layout looks like

Or when running the JSF page

Clicking the button we get the log messages

Sample Application

You can download the sample application from GitHub BlogBadgeButton12.2.1.2

Timo Hahn