Tuesday, April 2, 2013

ADF RC Notes.

Using Secured Properties:

Here is an example of how to set secured property on the client side:



<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:f="http://java.sun.com/jsf/core"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <f:view>
        <af:document title="Page1" id="d1">
            <af:form id="f1">
                <af:panelBox text="PanelBox1" id="pb1">
                    <f:facet name="toolbar"/>
                    <af:panelGroupLayout id="pgl1">
                        <af:commandButton text="Say Hello" id="cb1" unsecure="disabled">
                            <af:clientListener method="sayHello" type="action"/>
                        </af:commandButton>
                    </af:panelGroupLayout>
                </af:panelBox>
                <br/>
                <af:subform id="s1">
                    <af:panelGroupLayout id="pgl2">
                        <af:outputText id="greeting" clientComponent="true"/>
                        <af:commandLink text="Link" id="cl1"/>
                    </af:panelGroupLayout>
                </af:subform>
            </af:form>
            <af:resource type="javascript">
            function sayHello(actionEvent)
            {
                var component=actionEvent.getSource();
                //Find the client component for the "greeting" af:outputText
                var id = component.getId();
                var greetingComponent=component.findComponent("s1:greeting");
                //Set the value for the outputText component
                alert("Hello from " + id );
                greetingComponent.setValue("Hello World");
                component.setProperty("disabled", true);

            }
            </af:resource>
        </af:document>
    </f:view>
</jsp:root>

Note 1:

If we add an actionListener to the command button, then that action listener is not getting called in the above case. Without clientListener, its getting called. When I commented out everything in the java script function, then the actionListener is getting called:

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:f="http://java.sun.com/jsf/core"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <f:view>
        <af:document title="Page1" id="d1">
            <af:form id="f1">
                <af:panelBox text="PanelBox1" id="pb1">
                    <f:facet name="toolbar"/>
                    <af:panelGroupLayout id="pgl1">
                        <af:commandButton text="Say Hello" id="cb1" unsecure="disabled"
                                          actionListener="#{Page1Bean.handleSayHello}" partialSubmit="true">
                            <af:clientListener method="sayHello" type="action"/>
                        </af:commandButton>
                    </af:panelGroupLayout>
                </af:panelBox>
                <br/>
                <af:subform id="s1">
                    <af:panelGroupLayout id="pgl2">
                        <af:outputText id="greeting" clientComponent="true"/>
                        <af:commandLink text="Link" id="cl1"/>
                    </af:panelGroupLayout>
                </af:subform>
            </af:form>
            <af:resource type="javascript">
            function sayHello(actionEvent)
            {
                //var component=actionEvent.getSource();
                //Find the client component for the "greeting" af:outputText
                //var id = component.getId();
                //var greetingComponent=component.findComponent("s1:greeting");
                //Set the value for the outputText component
                //alert("Hello from " + id );
                //greetingComponent.setValue("Hello World");
                //component.setProperty("disabled", true);
         

            }
            </af:resource>
        </af:document>
    </f:view>
</jsp:root>

So, something in this java script is blocking the call to actionListener. My guess is that call to alert is causing this. The following java script does not stopped the call to actionListener:

            function sayHello(actionEvent)
            {
                var component=actionEvent.getSource();
                //Find the client component for the "greeting" af:outputText
                var id = component.getId();
                //var greetingComponent=component.findComponent("s1:greeting");
                //Set the value for the outputText component
                alert("Hello from " + id );
                //greetingComponent.setValue("Hello World");
                //component.setProperty("disabled", true);
               
            }
Next try would be to uncomment setProperty call:
            function sayHello(actionEvent)
            {
                var component=actionEvent.getSource();
                //Find the client component for the "greeting" af:outputText
                var id = component.getId();
                //var greetingComponent=component.findComponent("s1:greeting");
                //Set the value for the outputText component
                alert("Hello from " + id );
                //greetingComponent.setValue("Hello World");
                component.setProperty("disabled", true);
               
            }

As soon as I did it, the actionListener is not getting called. Seems like the event is getting cancelled.
So in this case, we need to manually raise the even at the server side.,

Working with Disconnected Properties

Consider the following page:

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:f="http://java.sun.com/jsf/core"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <f:view>
        <af:document title="Page1" id="d1">
            <af:form id="f1">
                <af:panelBox text="PanelBox1" id="pb1">
                    <f:facet name="toolbar"/>
                    <af:panelGroupLayout id="pgl1">
                        <af:commandButton text="Say Hello" id="cb1" unsecure="disabled"
                                          actionListener="#{Page1Bean.handleSayHello}" partialSubmit="true">
                            <af:clientListener method="sayHello" type="action"/>
                        </af:commandButton>
                    </af:panelGroupLayout>
                </af:panelBox>
                <br/>
                <af:subform id="s1">
                    <af:panelGroupLayout id="pgl2">
                        <af:outputText id="greeting" clientComponent="true"/>
                    </af:panelGroupLayout>
                </af:subform>
            </af:form>
            <af:resource type="javascript">
            function sayHello(actionEvent)
            {
                var component=actionEvent.getSource();
                var greetingComponent=component.findComponent("s1:greeting");
               
                greetingComponent.setValue("Hello World");
                greetingComponent.setProperty("submittedValue", "Hello One");
                alert("Hello from " + greetingComponent.getProperty("submittedValue") );
              
            }
            </af:resource>
        </af:document>
    </f:view>
</jsp:root>
Here, in the alert, the submitted value is visible, but outputtext is updated with the value "Hello World", so the disconnected property is available on client side (in javascript, say alert), but not moved to server side. However, actionListener is getting called in this case.

Working with Bonus Attributes

Consider the following page:

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:f="http://java.sun.com/jsf/core"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <f:view>
        <af:document title="Page1" id="d1">
            <af:form id="f1">
                <af:panelBox text="PanelBox1" id="pb1">
                    <f:facet name="toolbar"/>
                    <af:panelGroupLayout id="pgl1">
                        <af:commandButton text="Say Hello" id="cb1" unsecure="disabled"
                                          actionListener="#{Page1Bean.handleSayHello}" partialSubmit="true">
                            <af:clientListener method="sayHello" type="action"/>
                            <af:clientAttribute name="TestBonusAttr1" value="#{adfFacesContext.skinFamily}"/>
                        </af:commandButton>
                    </af:panelGroupLayout>
                </af:panelBox>
                <br/>
                <af:subform id="s1">
                    <af:panelGroupLayout id="pgl2">
                        <af:outputText id="greeting" clientComponent="true"/>
                    </af:panelGroupLayout>
                </af:subform>
            </af:form>
            <af:resource type="javascript">
            function sayHello(actionEvent)
            {
                var component=actionEvent.getSource();
                alert("Hello from " + component.getProperty("TestBonusAttr1") );
            
            }
            </af:resource>
        </af:document>
    </f:view>
</jsp:root>

Bonus attributes are used to return values from server to client. So in the above example, we are fetching the skin family name in javascript function using bonus attribute.
The above alert shows "Hello from fusionFx".

ADF Lifecycle Notes

If a command button's immediate property is set to true, then after Apply Request Values phase, all other phases are skipped for all other components on the page, and flow goes straight to Render Response phase.

If there are 2 input components, and 2 command buttons, and immediate property is set to true for 1 command button and 1 input component, and if the immediate command button is pressed, then conversion, validation will happen for only that immediate input text field. The conversion/ validation for other input field will be skipped. If any error happens during conversion/validation if the immediate input field, neither the valueChangeListener of the immediate input text field, nor the action listener of the immediate command button will execute. As soon as error happens, the control moves to Render Response phase. So the following statement in Web User Interface Guide, Page 4-8 is not correct:

If an immediate editableValueHolder component fails validation, any immediate actionSource component will still execute.

Optimized Lifecycle (PPR)

Consider the following form:

            <af:form id="f1">
                <af:inputText label="Required Field" required="true"/>
                <af:selectBooleanRadio id="show" autoSubmit="true" text="Show" value="#{Page1Bean.show}" group="a"/>
                <af:selectBooleanRadio id="hide" autoSubmit="true" text="Hide" value="#{Page1Bean.hide}" group="a"/>
                <af:panelGroupLayout partialTriggers="show hide" id="panel">
                    <af:outputText value="You can see me!" rendered="#{Page1Bean.show}"/>
                </af:panelGroupLayout>
            </af:form>

Here
  • inputTextField is set as required.
  • selectBooleanRadio's autosubmit is set to true.
  • Radion buttons are set as Partial Trigger on PGL.

Here inputTextField is set as required, but that field's validation is not fired when we just toggle show/hide radio button. Nice explaination is given in Web User Interface Guide, as shown below:

Because the autoSubmit attribute is set to true on the radio buttons, when they are selected, a SelectionEvent is fired, for which the radio button is considered the root. Because the panelGroupLayout component is set to be a target to both radio components, when that event is fired, only the selectOneRadio (the root), the panelGroupLayout component (the root’s target), and its child component (the outputText component) are processed through the lifecycle. Because the outputText component is configured to render only when the Show radio button is selected, the user is able to select that radio button and see the output text, without having to enter text into the required input field above the radio buttons.

So, in the above  case, the inputText field is isolated from the radio button changes. If we go for full page refresh, then the input text field will complain as usual.

Subform

Consider the following form:

            <af:form id="f1">
                <af:subform id="s1" default="true">
                    <af:panelGroupLayout id="pgl1">
                        <af:inputText label="Label 1" id="it1" required="true" />
                        <af:commandButton text="Subform 1" id="cb1"/>
                    </af:panelGroupLayout>
                </af:subform>
                <af:subform id="s2">
                    <af:panelGroupLayout id="pgl2">
                        <af:inputText label="Label 1" id="it2" required="true"/>
                        <af:commandButton text="Subform 2" id="cb2"/>
                    </af:panelGroupLayout>
                </af:subform>
                <af:commandButton text="DefaultForm" id="cb3"/>
            </af:form>

Here, for the first subform, the default attribute is set to true.
There is a button on each form(Subform 1, Subform 2, and default Form).
When the page renders, and DefaultForm button is clicked, the it1 complains for missing value.
Thats because of the subform's default attribute.
Subform1 and Subform 2 command button causes required validation failure in their respectative subforms only.

Event Handling Notes

In addition to server-side action and value change events, ADF Faces components also invoke client-side action and value change events, and other kinds of server and client events. Some events are generated by both server and client components (for example, selection events); some events are generated by server components only (for example, launch events); and some events are generated by client components only (for example, load events).
By default, most client events are propagated to the server. Changes to the component state are automatically synchronized back to the server to ensure consistency of state, and events are delivered, when necessary, to the server for further processing.
However, you can configure your event so that it does not propagate. In addition, any time you register a client-side event listener on the server-side Java component, the ADF Faces framework assumes that you require a JavaScript component, so a client-side component is created.

Here is an example of how an actionEvent is being cancelled from being propagated to the server:

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:f="http://java.sun.com/jsf/core"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <f:view>
        <af:document title="Page1" id="d1">
            <af:resource type="javascript">
            function showAlert(actionEvent) {
                  var component = actionEvent.getSource();
                  var id = component.getId();
                  alert("Hello from " + id );
                  actionEvent.cancel();
              }
            </af:resource>
            <af:form id="f1">
                        <af:commandButton text="Subform 1" id="cb1" actionListener="#{Page1Bean.handleSayHello}">
                    <af:clientListener type="action" method="showAlert"/>
                </af:commandButton>
            </af:form>
        </af:document>
    </f:view>
</jsp:root>

If we comment out actionEvent.cancel() line, then actionListener, ="#{Page1Bean.handleSayHello},  is called. But if we dont, then actionListener is not called.

Canceling an event may also block some default processing. For example, canceling an AdfUIInputEvent event for a context menu will block the browser from showing a context menu in response to that event.

Using Client and Server Listener

Consider the following page:

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:f="http://java.sun.com/jsf/core"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <f:view>
        <af:document title="Page1" id="d1">
            <af:resource type="javascript">
              function buttonPressed(event) {
                  var source = event.getSource();
                  var target = source.findComponent("eventTarget");
                  AdfCustomEvent.queue(target, "callFromClient", {},false);
              }
            </af:resource>
            <af:form id="f1">
                <af:inputText label="Event Target" id="eventTarget">
                    <af:serverListener type="callFromClient" method="#{Page1Bean.callFromClientToServer}"/>
                </af:inputText>
                <af:commandButton text="commandButton 1" id="cb1">
                    <af:clientListener method="buttonPressed" type="action"/>
                </af:commandButton>
            </af:form>
        </af:document>
    </f:view>
</jsp:root>
Here client listener is queueing an event on the target input text field. The server listener registered on the input component receives the custom event, and the associated bean method executes. The source can also work as target. So, instead of using a separate text field as target, we can add clientListener and serverListener both to command button and still the bean method will be called. The event is queued to the component passed as first parameter to AdfCustomEvent.queue() method.

Marshalling and Unmarshalling of data between JavaScript on the client(browser) and java code on server happens using JSON (Java Script Object Notation) and XML.

Note on Client Behavior Tags

Declarative client behavior tags like showPopupBehavior cancel server side event delivery automatically. Therefore, any actionListener or action attributes on the parent component will be ignored. This cannot be disabled. If you want to also trigger server-side functionality, you should use either a client-side event, or add an additional client listener that uses AdfCustomEvent and af:serverListener to deliver a server-side event.

The Poll Component

Consider the following example:

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:f="http://java.sun.com/jsf/core"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <f:view>
        <af:document title="Page1" id="d1">
            <af:form id="f1">
                <af:inputText label="Event Target" id="eventTarget" value="#{Page1Bean.inputValue}"
                              binding="#{Page1Bean.targetInput}"/>
                <af:poll id="p1" pollListener="#{Page1Bean.pollListener}"/>
            </af:form>
        </af:document>
    </f:view>
</jsp:root>

And here is the poll listener:

package view;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
import oracle.adf.view.rich.component.rich.input.RichInputText;
import oracle.adf.view.rich.context.AdfFacesContext;
import oracle.adf.view.rich.render.ClientEvent;
import org.apache.myfaces.trinidad.event.PollEvent;
public class Page1Bean {
    private String inputValue;
    public void setInputValue(String inputValue) {
        this.inputValue = inputValue;
    }
    public String getInputValue() {
        return inputValue;
    }
    public void pollListener(PollEvent pollEvent) {
        // Add event code here...
        this.setInputValue(new Long(System.currentTimeMillis()).toString());
        AdfFacesContext.getCurrentInstance().addPartialTarget(getTargetInput());
    }
    public void setTargetInput(RichInputText targetInput) {
        this.targetInput = targetInput;
    }
    public RichInputText getTargetInput() {
        return targetInput;
    }
}

The poll listener is just updating the inputText field value with current time in millisecond value. The poll component is used with default values. The input text field is updated after every 5 seconds. Do consider to configure the oracle.adf.view.rich.poll.TIMEOUT context-parameter when using the poll component.

Conversion and Validation Notes

We can add more than one validator tags to a component.
Only one converted can be added to a component.
ADF Faces Converters/Validators extends standard JSF Converters/Validators.
ADF Faces validators/converters can operate on both the client and the server side.
A backing bean method can not work as a converter.

Naming Containers

pageTemplate, subform, table, and tree are examples of naming containers.



1 comment:

  1. Dear Website Owner:

    I am really sorry to bother you with this and would like to apologize up front for the inconvenience.

    Unfortunately in the past we utilized an SEO company that may have been guilty of using a variety of questionable techniques to secure links to my website podaimaperformance.com. These links were placed purely for SEO purposes, with the intention of manipulating search rankings.

    As a result, links like this have been placed on your site in the past.

    Google has now penalized my site's rankings because of these manipulative links, and unfortunately, retaining them may also be potentially harmful to your website's reputation.

    I am writing to ask if you could please remove any links on your site that point to podaimaperformance.com

    There are (or have been) links at these URLs:
    http://adfblogs.blogspot.de/2011/08/adf-integration-with-soa-1-business.html


    Once again, I am very sorry that your site has been implicated in these bad practices and would greatly appreciate your help with resolving this problem.

    You can also let me know once the links to podaimaperformance.com have been removed by return email.

    If you need any more information, please email me and I will be happy to assist.

    I apologize for any inconvenience this has caused you and do appreciate your help.

    ReplyDelete