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
Oracle ADF 11g Tutorial
Rakesh Gujjarlapudi
 
DOCX
Oracle adf online training
o2education
 
PDF
13088674 oracle-adf-11g-learning-application-my-procurement-application
muzaffar1986
 
PPTX
Future of UI Automation testing and JDI
COMAQA.BY
 
PPTX
ADO.NET Entity Framework by Jose A. Blakeley and Michael Pizzo
Hasnain Iqbal
 
PPTX
Роман Иовлев «Open Source UI Automation Tests on C#»
SpbDotNet Community
 
PPT
2005 - .NET Chaostage: 1st class data driven applications with ASP.NET 2.0
Daniel Fisher
 
PPTX
Odtug2011 adf developers make the database work for you
Luc Bors
 
PDF
Discovering the Plan Cache (#SQLSat 206)
Jason Strate
 
PDF
Oracle ADF Quick Handy Reference
Deepak Bhagat
 
PDF
Mastering Oracle ADF Bindings
Euegene Fedorenko
 
ODP
JavaEE Spring Seam
Carol McDonald
 
ODP
How To Build a Multi-Field Search Page For Your XPages Application
Michael McGarel
 
PPTX
Reuse in adf applications
Matthieu De Graaf
 
PDF
Jpa
vantinhkhuc
 
PPTX
Multi-tier-performance-analysis-of-ADF-applications.pptx
Kuncoro21
 
PPTX
ADF Mobile - an intro for Developers
Luc Bors
 
PPTX
Oracle ADF Training| Oracle ADF Developer Training
Vasudha India
 
PDF
Oracle ADF Tutorial/Training Study Guide
Deepak Bhagat
 
Oracle ADF 11g Tutorial
Rakesh Gujjarlapudi
 
Oracle adf online training
o2education
 
13088674 oracle-adf-11g-learning-application-my-procurement-application
muzaffar1986
 
Future of UI Automation testing and JDI
COMAQA.BY
 
ADO.NET Entity Framework by Jose A. Blakeley and Michael Pizzo
Hasnain Iqbal
 
Роман Иовлев «Open Source UI Automation Tests on C#»
SpbDotNet Community
 
2005 - .NET Chaostage: 1st class data driven applications with ASP.NET 2.0
Daniel Fisher
 
Odtug2011 adf developers make the database work for you
Luc Bors
 
Discovering the Plan Cache (#SQLSat 206)
Jason Strate
 
Oracle ADF Quick Handy Reference
Deepak Bhagat
 
Mastering Oracle ADF Bindings
Euegene Fedorenko
 
JavaEE Spring Seam
Carol McDonald
 
How To Build a Multi-Field Search Page For Your XPages Application
Michael McGarel
 
Reuse in adf applications
Matthieu De Graaf
 
Multi-tier-performance-analysis-of-ADF-applications.pptx
Kuncoro21
 
ADF Mobile - an intro for Developers
Luc Bors
 
Oracle ADF Training| Oracle ADF Developer Training
Vasudha India
 
Oracle ADF Tutorial/Training Study Guide
Deepak Bhagat
 
Ad

More from Luc Bors (17)

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
An ADF Special Report
Luc Bors
 
PPTX
...and thus your forms automagically disappeared
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
 
An ADF Special Report
Luc Bors
 
...and thus your forms automagically disappeared
Luc Bors
 

Recently uploaded (20)

PDF
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
PDF
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PPTX
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
PPTX
MuleSoft MCP Support (Model Context Protocol) and Use Case Demo
shyamraj55
 
PDF
NLJUG Speaker academy 2025 - first session
Bert Jan Schrijver
 
PDF
🚀 Let’s Build Our First Slack Workflow! 🔧.pdf
SanjeetMishra29
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PDF
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
PDF
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
PPTX
Mastering ODC + Okta Configuration - Chennai OSUG
HathiMaryA
 
PDF
“Computer Vision at Sea: Automated Fish Tracking for Sustainable Fishing,” a ...
Edge AI and Vision Alliance
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
PDF
Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
PDF
UiPath DevConnect 2025: Agentic Automation Community User Group Meeting
DianaGray10
 
PPTX
Designing_the_Future_AI_Driven_Product_Experiences_Across_Devices.pptx
presentifyai
 
PPTX
Agentforce World Tour Toronto '25 - MCP with MuleSoft
Alexandra N. Martinez
 
PDF
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
PPTX
Seamless Tech Experiences Showcasing Cross-Platform App Design.pptx
presentifyai
 
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
MuleSoft MCP Support (Model Context Protocol) and Use Case Demo
shyamraj55
 
NLJUG Speaker academy 2025 - first session
Bert Jan Schrijver
 
🚀 Let’s Build Our First Slack Workflow! 🔧.pdf
SanjeetMishra29
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
Mastering ODC + Okta Configuration - Chennai OSUG
HathiMaryA
 
“Computer Vision at Sea: Automated Fish Tracking for Sustainable Fishing,” a ...
Edge AI and Vision Alliance
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
UiPath DevConnect 2025: Agentic Automation Community User Group Meeting
DianaGray10
 
Designing_the_Future_AI_Driven_Product_Experiences_Across_Devices.pptx
presentifyai
 
Agentforce World Tour Toronto '25 - MCP with MuleSoft
Alexandra N. Martinez
 
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
Seamless Tech Experiences Showcasing Cross-Platform App Design.pptx
presentifyai
 

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