SlideShare a Scribd company logo
ADF
How to Bring Common UI Patterns to ADF




Luc Bors, AMIS, The Netherlands
Wednesday, June 27, 2012
ODTUG KScope 12
San Antonio, Texas, USA
UI PATTERNS
FUSION APPS PATTERNS
RECOGNIZE THESE ?
RECOGNIZE THESE ?
TABBED NAVIGATION
TABBED NAVIGATION
CLOSE ALL / CLOSE OTHERS
CLOSE ALL / CLOSE OTHERS
CLOSE ALL / CLOSE OTHERS

• e
CAN YOU DO THIS IN ADF ?
CREATE THE CONTEXT MENU

<af:popup id="contextMenu" contentDelivery="lazyUncached"
           eventContext="launcher" launcherVar="source">
<af:menu id="men1" text="#{source.attributes.menuInvokedOnTab}">
    <af:commandMenuItem id="cmi1" text="close“
            actionListener="#{viewScope.jhsDynTabContext.closeThis}">
           <af:setPropertyListener
                from="#{source.attributes.menuInvokedOnTab}"
                to="#{viewScope.jhsDynTabContext.menuInvokedOnTab}"
                type="action"/>
    </af:commandMenuItem>
    <af:commandMenuItem id="cmi2" text="close others“
           actionListener="#{viewScope.jhsDynTabContext.closeOthers}">
…….
    </af:commandMenuItem>
    <af:commandMenuItem id="cmi3" text="close all“
            actionListener="#{viewScope.jhsDynTabContext.closeAll}">
  ……………..
    </af:commandMenuItem>
    </af:menu>
</af:popup>
INVOKING THE CONTEXT MENU

<af:navigationPane ...........>
  <af:commandNavigationItem ...............>
     <f:attribute name="tabId" value="#{tab.id}"/>
     <af:clientListener method="showMenu" type="contextMenu"/>
     <af:clientAttribute name="menuInvokedOnTab" value="#{tab.id}"/>
  </af:commandNavigationItem>
</af:navigationPane >




function showMenu(evt) {
      var popup = AdfPage.PAGE.findComponent("pt:contextMenu");
      ……………..
      popup.show(hints);
      evt.cancel();
}
USE EXISTING FUNCTIONALITY
CLOSE THIS TAB

public void closeThis(ActionEvent action) {

    String id = getMenuInvokedOnTab();
    List<String> tabsToRemove = new ArrayList();

    for (DynTab t : getActiveTabList()) {
         String x = t.getId();
         if (id == x) {
             tabsToRemove.add(x);
         }
    }
    for (String t : tabsToRemove) {
         removeTab(t);
    }
}
CLOSE OTHER TABS

public void closeOthers(ActionEvent action) {

    String id = getMenuInvokedOnTab();
    List<String> tabsToRemove = new ArrayList();

    for (DynTab t : getActiveTabList()) {
         String x = t.getId();
         if (id != x) {
             tabsToRemove.add(x);
         }
    }
    for (String t : tabsToRemove) {
         removeTab(t);
    }
}
CLOSE ALL

public void closeAll(ActionEvent action) {


    List<String> tabsToRemove = new ArrayList();

    for (DynTab t : getActiveTabList()) {
         tabsToRemove.add(t.getId());
    }
    for (String t : tabsToRemove) {
         removeTab(t);
    }
}
CLOSE ALL / CLOSE OTHERS
MOST RECENTLY USED (..HISTORY)
IMPLEMENTATION

•   Record activities
     – Use setPropertyListeners

•   Historybean (session scope) that manages the collection of
    navigation events
     – Display Label, Entity Type and Primary Key
     – bean calls …

•   BusinessService to record event in database for this user
     – (Optional) Also remove events for deleted records!
CREATE THE BEAN

      • Create History bean

<managed-bean id=“1">
   <managed-bean-name id=“2">
               recentHistoryBean</managed-bean-name>
   <managed-bean-class id=“3">
               nl.amis.jsf.history.beans.RecentHistoryBean
   </managed-bean-class>
   <managed-bean-scope id=“3">session</managed-bean-scope>
</managed-bean>
INTERCEPT ACTIVITY
<af:commandLink id="ot3" text="#{row.LastName}" action="edit"
     actionListener="#{recentHistoryBean.add}">

  <af:setPropertyListener from="#{row.EmployeeId}“
         to="#{recentHistoryBean.entityInstanceIdentifier}"
         type="action"/>
  <af:setPropertyListener from="#{row.LastName}“
         to="#{recentHistoryBean.entityInstanceDisplayLabel}"
         type="action"/>
   <af:setPropertyListener from="#{'EMP'}"
         to="#{recentHistoryBean.entityType}"
         type="action"/>
</af:commandLink>
RECORD ACTIVITY
public void add(ActionEvent actionEvent) {
   // Add event code here...

  recentHistory.add(new HistoryEvent(new oracle.jbo.domain.Date(
                  , entityType
                  , entityInstanceIdentifier
                  , entityInstanceDisplayLabel));

  HRServiceImpl hrAppMod = (HRServiceImpl)
     pageTemplateBc.getDataControl().getApplicationModule();
  hrAppMod.recordAndPersistHistoryEntry(recentHistory.get(0));
PERSIST ACTIVITY
public void recordAndPersistHistoryEntry(HistoryEvent event) {
  String statement =
     "RECENT_HISTORY_MANAGER.RECORD_AND_PERSIST_ENTRY(?,?,?,?)";

 callStoredProcedure(statement, new Object[]
           {event.getEntityType()
          , event.getKey().toString()
          , event.getDisplayLabel(), null});
   }
THE RESULT
DO YOU RECOGNIZE THIS ??
GOOGLE SEARCH
ADF QUERY COMPONENT ……
PREPARE THE DATABASE



 • Make sure that the HR user is allowed to use the
   ctxsys.ctx_ddl package


grant EXECUTE on CTXSYS.CTX_DDL to HR
CREATE A SEARCH PACKAGE


function get_emp_search_item ( p_rowid in rowid     ) return
varchar2 as
begin
   for b in (select e.first_name
                  , e.last_name
                  , e.email
                  , e.phone_number
                  , j.job_title
          from employees e left join jobs j
          using (job_id)
          where e.rowid = p_rowid)
        loop
           return b.first_name || ' ' || b.last_name ||
               ' (' || b.email || ', ' || b.phone_number
                    || ', ' || b.job_title || ')';
        end loop;
end get_emp_search_item;
CREATE THE ORACLE TEXT INDICES


-- Configure preferences...
ctx_ddl.create_preference('emp_datastore', 'user_datastore');
ctx_ddl.set_attribute('emp_datastore', 'procedure'
                    , 'ot_search.create_emp_search_item');




-- Create the indices...
 execute immediate 'create index emp_search_index on
 employees(last_name)
 indextype is ctxsys.context
 parameters (''datastore emp_datastore wordlist wordlist lexer
 lexer stoplist stoplist sync (on commit)'')';
THE BASE CLASSES



• OracleTextSearchSupport:
   • Converts the given user input (the search command):
      <code>searchValue</code> to an Oracle Text search-string.

• BaseViewObjectImpl
   • overrides getCriteriaItemClause(ViewCriteriaItem vci)

• BaseViewDefImpl
   • implementation to provide the following custom properties on ViewObjects:
        •   ORACLE_TEXT_SEARCH_ATTRIBUTE: To mark the column in which the seach info
            is queried
        •   ORACLE_TEXT_INDEX_ATTRIBUTE: To mark the database column on which the
            index was defined in the database.
CREATE THE MODEL PROJECT
CREATE THE MODEL PROJECT
VIEWCONTROLLER : A BEAN
<managed-bean-name id="1">departmentsQuickSearch</managed-bean-name>
 <managed-bean-class id="4">
          adfplus.quicksearch.controller.bean.QuickSearchBean
 </managed-bean-class>
 <managed-bean-scope id="2">pageFlow</managed-bean-scope>
 <managed-property id=“8">
    <property-name id=“10">iteratorBindingName</property-name>
    <property-class>java.lang.String</property-class>
    <value id="9">DepartmentsVO1Iterator</value>
 </managed-property>
 <managed-property id="11">
    <property-name id="13">searchAttribute</property-name>
    <property-class>java.lang.String</property-class>
    <value id="12">DepartmentSearchString</value>
 </managed-property>
 <managed-property id="14">
   <property-name id="15">searchIteratorBindingName</property-name>
   <property-class>java.lang.String</property-class>
   <value id="16">DepartmentsVO1IteratorQuickSearch</value>
  </managed-property>
VIEWCONTROLLER : A SUBFORM

<af:subform id="s1" defaultCommand="cb7">
    <af:panelGroupLayout id="pgl4" layout="horizontal"
                          inlineStyle="margin:10px;">
    <af:inputText label="Search" id="it2“
         value="#{pageFlowScope.departmentsQuickSearch.searchValue}">
       <af:autoSuggestBehavior
            suggestItems=
            "#{pageFlowScope.departmentsQuickSearch.suggestItems}"
             maxSuggestedItems="10"/>
    </af:inputText>

    <af:commandButton text="Search" id="cb7"
            action="#{pageFlowScope.departmentsQuickSearch.go}"
            partialSubmit="true"/>
  </af:panelGroupLayout>
</af:subform>
VIEWCONTROLLER : SEARCH METHOD

private synchronized List<SelectItem> search(String searchValue) {

  DCIteratorBinding iter = getSearchIteratorBinding();
  applySearchCriteria(iter, searchAttribute, searchValue);

  translations.clear();
  lastSuggestList = new ArrayList<SelectItem>();
  lastSearchValue = searchValue;

  Row[] rows = iter.getAllRowsInRange();
    for (Row row : rows) {
       String description = (String)row.getAttribute(searchAttribute);
       lastSuggestList.add(new SelectItem(description));
       translations.put(description, row.getKey());
     }
return lastSuggestList;
  }
THE RESULT
REAL TIME UPDATES
THE CONCEPT
THE IMPLEMENTATION; THE DATABASE




grant change notification to <user>;
REGISTER FOR DBQRCN (STEP 1)


public void startChangeNotification(){
   DatabaseChangeRegistration dcr = null;
   String query = "SELECT * from DEPARTMENTS";
   Properties prop = new Properties();
   prop.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS
       ,"true");
prop.setProperty(OracleConnection.DCN_QUERY_CHANGE_NOTIFICATION
       ,"true");
   try
    {
      dcr = conn.registerDatabaseChangeNotification(prop);
      RdbmsChangeEventListener listener =
            new RdbmsChangeEventListener(this);
      dcr.addListener(listener);
      ………..
REGISTER FOR DBQRCN (STEP 2)


// second step: add objects in the registration:
    Statement stmt = conn.createStatement();

((OracleStatement)stmt).setDatabaseChangeRegistration(dcr);
  ResultSet rs = stmt.executeQuery(query);
      while (rs.next()){}
             rs.close();
             stmt.close();
WHATS NEXT ….
SETUP ACTIVE DATA COMPONENT
public void setupActiveData() {
   ActiveModelContext context =
          ActiveModelContext.getActiveModelContext();
   Object[] keyPath = new String[0];
   context.addActiveModelInfo(
                    this
                  , keyPath
                  , "activemessage");
   System.out.println("add active bean as listener");
   databaseNotificationProcessor.registerAsListener(this);
}
SETUP THE ACTUAL UPDATE
public void triggerDataUpdate(String message) {
    this.message = message;
    counter.incrementAndGet();
    ActiveDataUpdateEvent event =
      ActiveDataEventUtil.buildActiveDataUpdateEvent(
                    ActiveDataEntry.ChangeType.UPDATE,
                    counter.get(),
                    new String[0], null,
                    new String[] { "activemessage" },
                    new Object[] { message });
     System.out.println("fireActiveDataUpdate");
     fireActiveDataUpdate(event);
    }
IMPLEMENTATION IN THE PAGE
 <af:activeOutputText
        value="#{pageFlowScope.trackChangesBean.updates}"
        id="aot1"
        visible="false">
   <af:clientListener method="activeDataCallback"
                      type="propertyChange"/>
</af:activeOutputText>




 <af:resource type="javascript">
    activeDataCallback = function (event) {
    var button =
    AdfPage.PAGE.findComponentByAbsoluteId("pt1:r1:0:cb1");
    button.setVisible(true);
    }
 </af:resource>
THE RESULT
PATTERNS UNDER INVESTIGATION

• Grouping Tabs
• Drag and Drop Tabs in UI Shell
   – dragSource and dropTarget




•   Duplicating Tabs
    – Restarting a new instance of a taskflow
PATTERNS UNDER INVESTIGATION

•   Adding Sticky Notes
    – dragSource and dropTarget
    – Contextual events




    – Concept : http://technology.amis.nl
        • Search for: adf-11g-dragn-drop-and-contextual-events/
RESOURCES
RESOURCES
SUMMARY
ADF
How to Bring Common UI Patterns to ADF


Luc Bors, AMIS, The Netherlands

Luc.Bors@amis.nl
LucBors@gmail.com
Follow me on Twitter : @lucb_


Wednesday, June 27, 2012
ODTUG KScope 12
San Antonio, Texas, USA

More Related Content

What's hot (20)

PDF
Chaining and function composition with lodash / underscore
Nicolas Carlo
 
PDF
Advanced Querying with CakePHP 3
José Lorenzo Rodríguez Urdaneta
 
PDF
Database Design Patterns
Hugo Hamon
 
PDF
The History of PHPersistence
Hugo Hamon
 
PDF
Elm: give it a try
Eugene Zharkov
 
PDF
A Tour to MySQL Commands
Hikmat Dhamee
 
PDF
50 Laravel Tricks in 50 Minutes
Azim Kurt
 
PDF
Agile database access with CakePHP 3
José Lorenzo Rodríguez Urdaneta
 
PDF
Cycle.js: Functional and Reactive
Eugene Zharkov
 
PDF
New in cakephp3
markstory
 
PDF
The Origin of Lithium
Nate Abele
 
PDF
Beyond the DOM: Sane Structure for JS Apps
Rebecca Murphey
 
KEY
Introduction à CoffeeScript pour ParisRB
jhchabran
 
PDF
Php unit the-mostunknownparts
Bastian Feder
 
PDF
Lodash js
LearningTech
 
PDF
international PHP2011_Bastian Feder_jQuery's Secrets
smueller_sandsmedia
 
PDF
Lithium: The Framework for People Who Hate Frameworks
Nate Abele
 
PDF
JavaScript Fundamentals with Angular and Lodash
Bret Little
 
PDF
The State of Lithium
Nate Abele
 
PDF
Internationalizing CakePHP Applications
Pierre MARTIN
 
Chaining and function composition with lodash / underscore
Nicolas Carlo
 
Advanced Querying with CakePHP 3
José Lorenzo Rodríguez Urdaneta
 
Database Design Patterns
Hugo Hamon
 
The History of PHPersistence
Hugo Hamon
 
Elm: give it a try
Eugene Zharkov
 
A Tour to MySQL Commands
Hikmat Dhamee
 
50 Laravel Tricks in 50 Minutes
Azim Kurt
 
Agile database access with CakePHP 3
José Lorenzo Rodríguez Urdaneta
 
Cycle.js: Functional and Reactive
Eugene Zharkov
 
New in cakephp3
markstory
 
The Origin of Lithium
Nate Abele
 
Beyond the DOM: Sane Structure for JS Apps
Rebecca Murphey
 
Introduction à CoffeeScript pour ParisRB
jhchabran
 
Php unit the-mostunknownparts
Bastian Feder
 
Lodash js
LearningTech
 
international PHP2011_Bastian Feder_jQuery's Secrets
smueller_sandsmedia
 
Lithium: The Framework for People Who Hate Frameworks
Nate Abele
 
JavaScript Fundamentals with Angular and Lodash
Bret Little
 
The State of Lithium
Nate Abele
 
Internationalizing CakePHP Applications
Pierre MARTIN
 

Viewers also liked (13)

PDF
ADF Essentials (KScope14)
Luc Bors
 
PDF
AMIS UX Event 2014: Mobile ADF; From Design To Device; The Tools that make it...
Luc Bors
 
PDF
Oracle ADF Mobile OGh (Oracle User Group Netherlands)
Luc Bors
 
PPTX
ΑΡΧΕΣ ΣΧΕΔΙΑΣΜΟΥ ΕΚΠΑΙΔΕΥΤΙΚΟΥ ΥΛΙΚΟΥ
Archontia Mantzaridou
 
PDF
Real life forms to adf
Luc Bors
 
PDF
Doag wysiwyg
Luc Bors
 
PDF
Real Life MAF (2.2) Oracle Open World 2015
Luc Bors
 
PPS
Profesiones
Leonardo Carrillo
 
PPTX
Real life-maf-2015
Luc Bors
 
PPTX
Ppt pk
Nia Ismail
 
PDF
ADF Mobile: 10 Things you don't get from the developers guide
Luc Bors
 
PDF
MAF push notifications
Luc Bors
 
PPTX
Push to the limit - rich and pro-active user interfaces with ADF (Oracle Ope...
Lucas Jellema
 
ADF Essentials (KScope14)
Luc Bors
 
AMIS UX Event 2014: Mobile ADF; From Design To Device; The Tools that make it...
Luc Bors
 
Oracle ADF Mobile OGh (Oracle User Group Netherlands)
Luc Bors
 
ΑΡΧΕΣ ΣΧΕΔΙΑΣΜΟΥ ΕΚΠΑΙΔΕΥΤΙΚΟΥ ΥΛΙΚΟΥ
Archontia Mantzaridou
 
Real life forms to adf
Luc Bors
 
Doag wysiwyg
Luc Bors
 
Real Life MAF (2.2) Oracle Open World 2015
Luc Bors
 
Profesiones
Leonardo Carrillo
 
Real life-maf-2015
Luc Bors
 
Ppt pk
Nia Ismail
 
ADF Mobile: 10 Things you don't get from the developers guide
Luc Bors
 
MAF push notifications
Luc Bors
 
Push to the limit - rich and pro-active user interfaces with ADF (Oracle Ope...
Lucas Jellema
 
Ad

Similar to How to Bring Common UI Patterns to ADF (20)

PDF
EclipseCon2011 Cross-Platform Mobile Development with Eclipse
Heiko Behrens
 
DOCX
VPN Access Runbook
Taha Shakeel
 
PDF
Backbone.js — Introduction to client-side JavaScript MVC
pootsbook
 
PDF
Understanding backbonejs
Nick Lee
 
PDF
Windows 8 Training Fundamental - 1
Kevin Octavian
 
PDF
Android best practices
Jose Manuel Ortega Candel
 
PDF
Backbone - TDC 2011 Floripa
Rafael Felix da Silva
 
PDF
Aplicacoes dinamicas Rails com Backbone
Rafael Felix da Silva
 
PDF
Taming Core Data by Arek Holko, Macoscope
Macoscope
 
DOC
Ex[1].3 php db connectivity
Mouli Chandira
 
PDF
Separation of concerns - DPC12
Stephan Hochdörfer
 
KEY
Scala on Your Phone
Michael Galpin
 
PPTX
Getting started with Elasticsearch and .NET
Tomas Jansson
 
KEY
Object-Oriented JavaScript
kvangork
 
KEY
Object-Oriented Javascript
kvangork
 
PDF
Practical Google App Engine Applications In Py
Eric ShangKuan
 
PPTX
Knockoutjs UG meeting presentation
Valdis Iljuconoks
 
PDF
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Thomas Fuchs
 
PDF
Writing Maintainable JavaScript
Andrew Dupont
 
PDF
Practica n° 7
rafobarrientos
 
EclipseCon2011 Cross-Platform Mobile Development with Eclipse
Heiko Behrens
 
VPN Access Runbook
Taha Shakeel
 
Backbone.js — Introduction to client-side JavaScript MVC
pootsbook
 
Understanding backbonejs
Nick Lee
 
Windows 8 Training Fundamental - 1
Kevin Octavian
 
Android best practices
Jose Manuel Ortega Candel
 
Backbone - TDC 2011 Floripa
Rafael Felix da Silva
 
Aplicacoes dinamicas Rails com Backbone
Rafael Felix da Silva
 
Taming Core Data by Arek Holko, Macoscope
Macoscope
 
Ex[1].3 php db connectivity
Mouli Chandira
 
Separation of concerns - DPC12
Stephan Hochdörfer
 
Scala on Your Phone
Michael Galpin
 
Getting started with Elasticsearch and .NET
Tomas Jansson
 
Object-Oriented JavaScript
kvangork
 
Object-Oriented Javascript
kvangork
 
Practical Google App Engine Applications In Py
Eric ShangKuan
 
Knockoutjs UG meeting presentation
Valdis Iljuconoks
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Thomas Fuchs
 
Writing Maintainable JavaScript
Andrew Dupont
 
Practica n° 7
rafobarrientos
 
Ad

More from Luc Bors (19)

PDF
Talk to me Goose: Going beyond your regular Chatbot
Luc Bors
 
PDF
Extending Oracle SaaS Using Oracle Cloud UX Rapid Development Kit
Luc Bors
 
PDF
NO CODE : Or How to Extend Oracle SaaS with Oracle Visual Builder Cloud Service
Luc Bors
 
PDF
Real life-maf-2015-k scope-final
Luc Bors
 
PDF
Reaching out from ADF Mobile (ODTUG KScope 2014)
Luc Bors
 
PDF
OgH Data Visualization Special Part III
Luc Bors
 
PDF
OgH Data Visualization Special Part II
Luc Bors
 
PDF
OgH Data Visualization Special Part I
Luc Bors
 
PDF
amis-adf-enterprise-mobility
Luc Bors
 
PDF
Oracle day 2014-mobile-customer-case
Luc Bors
 
PDF
Oracle MAF real life OOW.pptx
Luc Bors
 
PPTX
oow2013-adf-mo-bi-le
Luc Bors
 
PDF
Goodbye Nightmare : Tops and Tricks for creating Layouts
Luc Bors
 
PDF
Dont Reinvent the Wheel: Tips and Tricks for reuse in ADF
Luc Bors
 
PDF
ADF Mobile : Best Practices for Developing Applications with Oracle ADF Mobile
Luc Bors
 
PPTX
ADF Mobile - an intro for Developers
Luc Bors
 
PPTX
An ADF Special Report
Luc Bors
 
PPTX
...and thus your forms automagically disappeared
Luc Bors
 
PPTX
Odtug2011 adf developers make the database work for you
Luc Bors
 
Talk to me Goose: Going beyond your regular Chatbot
Luc Bors
 
Extending Oracle SaaS Using Oracle Cloud UX Rapid Development Kit
Luc Bors
 
NO CODE : Or How to Extend Oracle SaaS with Oracle Visual Builder Cloud Service
Luc Bors
 
Real life-maf-2015-k scope-final
Luc Bors
 
Reaching out from ADF Mobile (ODTUG KScope 2014)
Luc Bors
 
OgH Data Visualization Special Part III
Luc Bors
 
OgH Data Visualization Special Part II
Luc Bors
 
OgH Data Visualization Special Part I
Luc Bors
 
amis-adf-enterprise-mobility
Luc Bors
 
Oracle day 2014-mobile-customer-case
Luc Bors
 
Oracle MAF real life OOW.pptx
Luc Bors
 
oow2013-adf-mo-bi-le
Luc Bors
 
Goodbye Nightmare : Tops and Tricks for creating Layouts
Luc Bors
 
Dont Reinvent the Wheel: Tips and Tricks for reuse in ADF
Luc Bors
 
ADF Mobile : Best Practices for Developing Applications with Oracle ADF Mobile
Luc Bors
 
ADF Mobile - an intro for Developers
Luc Bors
 
An ADF Special Report
Luc Bors
 
...and thus your forms automagically disappeared
Luc Bors
 
Odtug2011 adf developers make the database work for you
Luc Bors
 

Recently uploaded (20)

PDF
Why Orbit Edge Tech is a Top Next JS Development Company in 2025
mahendraalaska08
 
PDF
2025-07-15 EMEA Volledig Inzicht Dutch Webinar
ThousandEyes
 
PPTX
Earn Agentblazer Status with Slack Community Patna.pptx
SanjeetMishra29
 
PDF
UiPath vs Other Automation Tools Meeting Presentation.pdf
Tracy Dixon
 
PDF
Are there government-backed agri-software initiatives in Limerick.pdf
giselawagner2
 
PDF
Market Wrap for 18th July 2025 by CIFDAQ
CIFDAQ
 
PPTX
Building and Operating a Private Cloud with CloudStack and LINBIT CloudStack ...
ShapeBlue
 
PDF
HR agent at Mediq: Lessons learned on Agent Builder & Maestro by Tacstone Tec...
UiPathCommunity
 
PDF
Human-centred design in online workplace learning and relationship to engagem...
Tracy Tang
 
PDF
Impact of IEEE Computer Society in Advancing Emerging Technologies including ...
Hironori Washizaki
 
PPTX
Machine Learning Benefits Across Industries
SynapseIndia
 
PDF
TrustArc Webinar - Data Privacy Trends 2025: Mid-Year Insights & Program Stra...
TrustArc
 
PDF
Novus-Safe Pro: Brochure-What is Novus Safe Pro?.pdf
Novus Hi-Tech
 
PDF
HydITEx corporation Booklet 2025 English
Георгий Феодориди
 
PPTX
Top Managed Service Providers in Los Angeles
Captain IT
 
PDF
Upskill to Agentic Automation 2025 - Kickoff Meeting
DianaGray10
 
PDF
Upgrading to z_OS V2R4 Part 01 of 02.pdf
Flavio787771
 
PDF
SWEBOK Guide and Software Services Engineering Education
Hironori Washizaki
 
PPTX
Extensions Framework (XaaS) - Enabling Orchestrate Anything
ShapeBlue
 
PDF
Arcee AI - building and working with small language models (06/25)
Julien SIMON
 
Why Orbit Edge Tech is a Top Next JS Development Company in 2025
mahendraalaska08
 
2025-07-15 EMEA Volledig Inzicht Dutch Webinar
ThousandEyes
 
Earn Agentblazer Status with Slack Community Patna.pptx
SanjeetMishra29
 
UiPath vs Other Automation Tools Meeting Presentation.pdf
Tracy Dixon
 
Are there government-backed agri-software initiatives in Limerick.pdf
giselawagner2
 
Market Wrap for 18th July 2025 by CIFDAQ
CIFDAQ
 
Building and Operating a Private Cloud with CloudStack and LINBIT CloudStack ...
ShapeBlue
 
HR agent at Mediq: Lessons learned on Agent Builder & Maestro by Tacstone Tec...
UiPathCommunity
 
Human-centred design in online workplace learning and relationship to engagem...
Tracy Tang
 
Impact of IEEE Computer Society in Advancing Emerging Technologies including ...
Hironori Washizaki
 
Machine Learning Benefits Across Industries
SynapseIndia
 
TrustArc Webinar - Data Privacy Trends 2025: Mid-Year Insights & Program Stra...
TrustArc
 
Novus-Safe Pro: Brochure-What is Novus Safe Pro?.pdf
Novus Hi-Tech
 
HydITEx corporation Booklet 2025 English
Георгий Феодориди
 
Top Managed Service Providers in Los Angeles
Captain IT
 
Upskill to Agentic Automation 2025 - Kickoff Meeting
DianaGray10
 
Upgrading to z_OS V2R4 Part 01 of 02.pdf
Flavio787771
 
SWEBOK Guide and Software Services Engineering Education
Hironori Washizaki
 
Extensions Framework (XaaS) - Enabling Orchestrate Anything
ShapeBlue
 
Arcee AI - building and working with small language models (06/25)
Julien SIMON
 

How to Bring Common UI Patterns to ADF

  • 1. ADF How to Bring Common UI Patterns to ADF Luc Bors, AMIS, The Netherlands Wednesday, June 27, 2012 ODTUG KScope 12 San Antonio, Texas, USA
  • 8. CLOSE ALL / CLOSE OTHERS
  • 9. CLOSE ALL / CLOSE OTHERS
  • 10. CLOSE ALL / CLOSE OTHERS • e
  • 11. CAN YOU DO THIS IN ADF ?
  • 12. CREATE THE CONTEXT MENU <af:popup id="contextMenu" contentDelivery="lazyUncached" eventContext="launcher" launcherVar="source"> <af:menu id="men1" text="#{source.attributes.menuInvokedOnTab}"> <af:commandMenuItem id="cmi1" text="close“ actionListener="#{viewScope.jhsDynTabContext.closeThis}"> <af:setPropertyListener from="#{source.attributes.menuInvokedOnTab}" to="#{viewScope.jhsDynTabContext.menuInvokedOnTab}" type="action"/> </af:commandMenuItem> <af:commandMenuItem id="cmi2" text="close others“ actionListener="#{viewScope.jhsDynTabContext.closeOthers}"> ……. </af:commandMenuItem> <af:commandMenuItem id="cmi3" text="close all“ actionListener="#{viewScope.jhsDynTabContext.closeAll}"> …………….. </af:commandMenuItem> </af:menu> </af:popup>
  • 13. INVOKING THE CONTEXT MENU <af:navigationPane ...........> <af:commandNavigationItem ...............> <f:attribute name="tabId" value="#{tab.id}"/> <af:clientListener method="showMenu" type="contextMenu"/> <af:clientAttribute name="menuInvokedOnTab" value="#{tab.id}"/> </af:commandNavigationItem> </af:navigationPane > function showMenu(evt) { var popup = AdfPage.PAGE.findComponent("pt:contextMenu"); …………….. popup.show(hints); evt.cancel(); }
  • 15. CLOSE THIS TAB public void closeThis(ActionEvent action) { String id = getMenuInvokedOnTab(); List<String> tabsToRemove = new ArrayList(); for (DynTab t : getActiveTabList()) { String x = t.getId(); if (id == x) { tabsToRemove.add(x); } } for (String t : tabsToRemove) { removeTab(t); } }
  • 16. CLOSE OTHER TABS public void closeOthers(ActionEvent action) { String id = getMenuInvokedOnTab(); List<String> tabsToRemove = new ArrayList(); for (DynTab t : getActiveTabList()) { String x = t.getId(); if (id != x) { tabsToRemove.add(x); } } for (String t : tabsToRemove) { removeTab(t); } }
  • 17. CLOSE ALL public void closeAll(ActionEvent action) { List<String> tabsToRemove = new ArrayList(); for (DynTab t : getActiveTabList()) { tabsToRemove.add(t.getId()); } for (String t : tabsToRemove) { removeTab(t); } }
  • 18. CLOSE ALL / CLOSE OTHERS
  • 19. MOST RECENTLY USED (..HISTORY)
  • 20. IMPLEMENTATION • Record activities – Use setPropertyListeners • Historybean (session scope) that manages the collection of navigation events – Display Label, Entity Type and Primary Key – bean calls … • BusinessService to record event in database for this user – (Optional) Also remove events for deleted records!
  • 21. CREATE THE BEAN • Create History bean <managed-bean id=“1"> <managed-bean-name id=“2"> recentHistoryBean</managed-bean-name> <managed-bean-class id=“3"> nl.amis.jsf.history.beans.RecentHistoryBean </managed-bean-class> <managed-bean-scope id=“3">session</managed-bean-scope> </managed-bean>
  • 22. INTERCEPT ACTIVITY <af:commandLink id="ot3" text="#{row.LastName}" action="edit" actionListener="#{recentHistoryBean.add}"> <af:setPropertyListener from="#{row.EmployeeId}“ to="#{recentHistoryBean.entityInstanceIdentifier}" type="action"/> <af:setPropertyListener from="#{row.LastName}“ to="#{recentHistoryBean.entityInstanceDisplayLabel}" type="action"/> <af:setPropertyListener from="#{'EMP'}" to="#{recentHistoryBean.entityType}" type="action"/> </af:commandLink>
  • 23. RECORD ACTIVITY public void add(ActionEvent actionEvent) { // Add event code here... recentHistory.add(new HistoryEvent(new oracle.jbo.domain.Date( , entityType , entityInstanceIdentifier , entityInstanceDisplayLabel)); HRServiceImpl hrAppMod = (HRServiceImpl) pageTemplateBc.getDataControl().getApplicationModule(); hrAppMod.recordAndPersistHistoryEntry(recentHistory.get(0));
  • 24. PERSIST ACTIVITY public void recordAndPersistHistoryEntry(HistoryEvent event) { String statement = "RECENT_HISTORY_MANAGER.RECORD_AND_PERSIST_ENTRY(?,?,?,?)"; callStoredProcedure(statement, new Object[] {event.getEntityType() , event.getKey().toString() , event.getDisplayLabel(), null}); }
  • 26. DO YOU RECOGNIZE THIS ??
  • 29. PREPARE THE DATABASE • Make sure that the HR user is allowed to use the ctxsys.ctx_ddl package grant EXECUTE on CTXSYS.CTX_DDL to HR
  • 30. CREATE A SEARCH PACKAGE function get_emp_search_item ( p_rowid in rowid ) return varchar2 as begin for b in (select e.first_name , e.last_name , e.email , e.phone_number , j.job_title from employees e left join jobs j using (job_id) where e.rowid = p_rowid) loop return b.first_name || ' ' || b.last_name || ' (' || b.email || ', ' || b.phone_number || ', ' || b.job_title || ')'; end loop; end get_emp_search_item;
  • 31. CREATE THE ORACLE TEXT INDICES -- Configure preferences... ctx_ddl.create_preference('emp_datastore', 'user_datastore'); ctx_ddl.set_attribute('emp_datastore', 'procedure' , 'ot_search.create_emp_search_item'); -- Create the indices... execute immediate 'create index emp_search_index on employees(last_name) indextype is ctxsys.context parameters (''datastore emp_datastore wordlist wordlist lexer lexer stoplist stoplist sync (on commit)'')';
  • 32. THE BASE CLASSES • OracleTextSearchSupport: • Converts the given user input (the search command): <code>searchValue</code> to an Oracle Text search-string. • BaseViewObjectImpl • overrides getCriteriaItemClause(ViewCriteriaItem vci) • BaseViewDefImpl • implementation to provide the following custom properties on ViewObjects: • ORACLE_TEXT_SEARCH_ATTRIBUTE: To mark the column in which the seach info is queried • ORACLE_TEXT_INDEX_ATTRIBUTE: To mark the database column on which the index was defined in the database.
  • 33. CREATE THE MODEL PROJECT
  • 34. CREATE THE MODEL PROJECT
  • 35. VIEWCONTROLLER : A BEAN <managed-bean-name id="1">departmentsQuickSearch</managed-bean-name> <managed-bean-class id="4"> adfplus.quicksearch.controller.bean.QuickSearchBean </managed-bean-class> <managed-bean-scope id="2">pageFlow</managed-bean-scope> <managed-property id=“8"> <property-name id=“10">iteratorBindingName</property-name> <property-class>java.lang.String</property-class> <value id="9">DepartmentsVO1Iterator</value> </managed-property> <managed-property id="11"> <property-name id="13">searchAttribute</property-name> <property-class>java.lang.String</property-class> <value id="12">DepartmentSearchString</value> </managed-property> <managed-property id="14"> <property-name id="15">searchIteratorBindingName</property-name> <property-class>java.lang.String</property-class> <value id="16">DepartmentsVO1IteratorQuickSearch</value> </managed-property>
  • 36. VIEWCONTROLLER : A SUBFORM <af:subform id="s1" defaultCommand="cb7"> <af:panelGroupLayout id="pgl4" layout="horizontal" inlineStyle="margin:10px;"> <af:inputText label="Search" id="it2“ value="#{pageFlowScope.departmentsQuickSearch.searchValue}"> <af:autoSuggestBehavior suggestItems= "#{pageFlowScope.departmentsQuickSearch.suggestItems}" maxSuggestedItems="10"/> </af:inputText> <af:commandButton text="Search" id="cb7" action="#{pageFlowScope.departmentsQuickSearch.go}" partialSubmit="true"/> </af:panelGroupLayout> </af:subform>
  • 37. VIEWCONTROLLER : SEARCH METHOD private synchronized List<SelectItem> search(String searchValue) { DCIteratorBinding iter = getSearchIteratorBinding(); applySearchCriteria(iter, searchAttribute, searchValue); translations.clear(); lastSuggestList = new ArrayList<SelectItem>(); lastSearchValue = searchValue; Row[] rows = iter.getAllRowsInRange(); for (Row row : rows) { String description = (String)row.getAttribute(searchAttribute); lastSuggestList.add(new SelectItem(description)); translations.put(description, row.getKey()); } return lastSuggestList; }
  • 41. THE IMPLEMENTATION; THE DATABASE grant change notification to <user>;
  • 42. REGISTER FOR DBQRCN (STEP 1) public void startChangeNotification(){ DatabaseChangeRegistration dcr = null; String query = "SELECT * from DEPARTMENTS"; Properties prop = new Properties(); prop.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS ,"true"); prop.setProperty(OracleConnection.DCN_QUERY_CHANGE_NOTIFICATION ,"true"); try { dcr = conn.registerDatabaseChangeNotification(prop); RdbmsChangeEventListener listener = new RdbmsChangeEventListener(this); dcr.addListener(listener); ………..
  • 43. REGISTER FOR DBQRCN (STEP 2) // second step: add objects in the registration: Statement stmt = conn.createStatement(); ((OracleStatement)stmt).setDatabaseChangeRegistration(dcr); ResultSet rs = stmt.executeQuery(query); while (rs.next()){} rs.close(); stmt.close();
  • 45. SETUP ACTIVE DATA COMPONENT public void setupActiveData() { ActiveModelContext context = ActiveModelContext.getActiveModelContext(); Object[] keyPath = new String[0]; context.addActiveModelInfo( this , keyPath , "activemessage"); System.out.println("add active bean as listener"); databaseNotificationProcessor.registerAsListener(this); }
  • 46. SETUP THE ACTUAL UPDATE public void triggerDataUpdate(String message) { this.message = message; counter.incrementAndGet(); ActiveDataUpdateEvent event = ActiveDataEventUtil.buildActiveDataUpdateEvent( ActiveDataEntry.ChangeType.UPDATE, counter.get(), new String[0], null, new String[] { "activemessage" }, new Object[] { message }); System.out.println("fireActiveDataUpdate"); fireActiveDataUpdate(event); }
  • 47. IMPLEMENTATION IN THE PAGE <af:activeOutputText value="#{pageFlowScope.trackChangesBean.updates}" id="aot1" visible="false"> <af:clientListener method="activeDataCallback" type="propertyChange"/> </af:activeOutputText> <af:resource type="javascript"> activeDataCallback = function (event) { var button = AdfPage.PAGE.findComponentByAbsoluteId("pt1:r1:0:cb1"); button.setVisible(true); } </af:resource>
  • 49. PATTERNS UNDER INVESTIGATION • Grouping Tabs • Drag and Drop Tabs in UI Shell – dragSource and dropTarget • Duplicating Tabs – Restarting a new instance of a taskflow
  • 50. PATTERNS UNDER INVESTIGATION • Adding Sticky Notes – dragSource and dropTarget – Contextual events – Concept : http://technology.amis.nl • Search for: adf-11g-dragn-drop-and-contextual-events/
  • 54. ADF How to Bring Common UI Patterns to ADF Luc Bors, AMIS, The Netherlands [email protected] [email protected] Follow me on Twitter : @lucb_ Wednesday, June 27, 2012 ODTUG KScope 12 San Antonio, Texas, USA