Monday, September 24, 2012

ADF: Preventing user actions on UI when a process is running

There are often requirements when we want users not to click here and there on a JSFF page, when an important process is running.

ADF out of the box provides a way to achieve the same


af:resource type="JavaScript"
                  function preventOperation(event){
                      event.preventUserInput();
                  }

Use this JS method in the clientListener of your UI components on which you want Users to prevent clicking.

CSS: Gradient class for all browsers


@agent ie{

  .application-container {
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#cccccc', endColorstr='#000000');
  }
}

@agent webkit{
  .application-container {
    background-image: -webkit-gradient(linear, left top, left bottom, from(RED), to(GREEN)); /* for webkit browsers */
  }
}

@agent gecko{
  .application-container {
    background-image: -moz-linear-gradient(top,  YELLOW,  BLUE); /* for firefox 3.6+ */
  }
}

MDS ChangeManager code for af:carousel

When your ADF application is MDS enabled,you may see the MDS persistence behaviour across user sessions.
Here is a piece of code to avoid the same.


    public void spinEvent(CarouselSpinEvent carouselSpinEvent) {

        // Add event code here...
        try {
            ChangeManager cm =
                RequestContext.getCurrentInstance().getChangeManager();
            System.out.println(this.getCarouselComp().getCurrentItemKey().getClass());
            ComponentChange change =
                new AttributeComponentChange("currentItemKey", null);
            if (cm != null)
                cm.addComponentChange(FacesContext.getCurrentInstance(),
                                      getCarouselComp(), change);
        } catch (Exception e) {
            // TODO: Add catch code
            e.printStackTrace();
        }      
    }

JSTL:Print Java List Size in JSFF

#{fn:length(DemoBean.testList)}

Tuesday, September 11, 2012

Execute an expensive VO Iterator after page Load happens(using af:poll)-1

We may have scenario where we want the ADF Page to be loaded as soon as possible without waiting for all the PageDef iterators to be executed, hence reducing the page load time.

A possible solution is using a polling component.When the page loads, the UI component with the expensive SQL wont get rendered.After the page loads, the af:poll gets fired after (t) time, say 5 seconds, execute the VO Iterator and make the UI component "visible= true".

Here are the code snippets we need to use

Page.jsff


    <af:panelBox text="Announcements" id="pb1">

        <f:facet name="toolbar">
            <af:poll id="p1" interval="5000"
                     pollListener="#{DemoBean.refreshAnnouncements}"/>
        </f:facet>
        <af:panelFormLayout id="pfl1" partialTriggers="p1" visible="false"
                            binding="#{DemoBean.announcementForm}">
            <af:panelLabelAndMessage label="#{bindings.Subject.hints.label}"
                                     id="plam2">
                <af:outputText value="#{bindings.Subject.inputValue}" id="ot2"/>
            </af:panelLabelAndMessage>
            <af:panelLabelAndMessage label="#{bindings.Description.hints.label}"
                                     id="plam1">
                <af:outputText value="#{bindings.Description.inputValue}"
                               id="ot1"/>
            </af:panelLabelAndMessage>
            <f:facet name="footer">
                <af:panelGroupLayout layout="horizontal" id="pgl1">
                    <af:commandButton actionListener="#{bindings.Previous.execute}"
                                      text="Previous"
                                      partialSubmit="true" id="cb2"/>
                    <af:commandButton actionListener="#{bindings.Next.execute}"
                                      text="Next"
                                      partialSubmit="true" id="cb1"/>
                </af:panelGroupLayout>
            </f:facet>
        </af:panelFormLayout>
    </af:panelBox>

PageDef.xml(Note the refresh property of iterator = never, so that on page load, the SQL doesnt get executed)

    <iterator Binds="AtkHpAnnouncementsVO1" RangeSize="25"
              DataControl="AnnouncementAMDataControl"
              id="AtkHpAnnouncementsVO1Iterator" ChangeEventPolicy="ppr"
              Refresh="never"/>

ManagedBean code for af:poll pollListener code

import oracle.adf.model.BindingContext;


import oracle.adf.view.rich.component.rich.RichPoll;
import oracle.adf.view.rich.component.rich.layout.RichPanelFormLayout;

import oracle.adf.view.rich.context.AdfFacesContext;

import oracle.binding.BindingContainer;

import oracle.binding.OperationBinding;

import org.apache.myfaces.trinidad.event.PollEvent;

public class DemoBean {
    private RichPanelFormLayout announcementForm;

    public DemoBean() {
    }

    public void refreshAnnouncements(PollEvent pollEvent) {
        // Add event code here...
         BindingContainer bindings =   BindingContext.getCurrent().getCurrentBindingsEntry();
         OperationBinding operationBinding = bindings.getOperationBinding("Execute");
         Object result = operationBinding.execute();  
         System.out.println(result);
         this.getAnnouncementForm().setVisible(true);
         AdfFacesContext.getCurrentInstance().addPartialTarget(this.getAnnouncementForm());
         RichPoll pollComp = (RichPoll)pollEvent.getComponent();
         pollComp.setInterval(-1);//Disable the polling now
         AdfFacesContext.getCurrentInstance().addPartialTarget(pollComp);
    }

    public void setAnnouncementForm(RichPanelFormLayout announcementForm) {
        this.announcementForm = announcementForm;
    }

    public RichPanelFormLayout getAnnouncementForm() {
        return announcementForm;
    }
}

Monday, September 03, 2012

SharedAM Examples

SharedAM VOs can be refreshed using 2 mechanisms.

DataBase Change Notification

SharedAM test(DB Change Notification=>AutoRefresh = true)
  • Make Default AM configuration to Shared
  • grant change notification to fusion
  • Model->Project properties->ApplicationModeul->Shuttle to Application Level
  • For the Shared VO autorefresh=true
  • Create a ViewAccessor of the SharedVO and expose in Client Interface
  • From DataControl Pallete, use 
<af:forEach items="#{bindings.return.attributeDefs}" var="def">
            <af:column headerText="#{bindings.return.labels[def.name]}"
                       sortable="true" sortProperty="#{def.name}" id="c1">
              <af:outputText value="#{row[def.name]}" id="ot1"/>
            </af:column>


  • In DataBindings.cpx->AM DatAControl->Use Configuration=Shared
  • For the VA Iterator in pagedef, set ChangeEventPolicy=ppr

TimeOut Feature for refreshing the Query Collection

  • jbo.ampool.timetolive="86400000" jbo.qcpool.maxinactiveage="86400000"
Maintains the SharedAM VO cache for 24 hours and then invalidates.