54
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

How te bring common UI patterns to ADF

Embed Size (px)

DESCRIPTION

Deze presentatie is gegeven tijdens de KScope conferentie 2012 Spreker: Luc Bors Titel: How to Bring Common UI Patterns to ADF Onderwerp: Fusion Middleware - Subonderwerp: ADF Eindgebruikers van bedrijfsapplicaties eisen dezelfde gebruikerservaring die ze kennen van bijvoorbeeld office applicaties en applicaties op het internet. Functies zoals bookmarking, favorieten en het werken met tabs wordt graag gezien in de dagelijkse werk. Het zoekmechanisme van Google, dat suggesties toont op basis van de ingevoerde tekst, is zo ´gewoon´ dat mensen dit in elke applicatie terug willen zien. Twitter en Facebook geven automatisch aan dat je nieuwe berichten hebt zonder dat je daar zelf eerst om moet vragen, dat gebruikers de normaalste zaak van de wereld vinden. Er zijn nog veel meer van deze UI patterns. In deze sessie leer je hoe een aantal van deze UI patterns in je ADF applicatie kunt inbouwen waardoor de eindgebruiker beschikking krijgt over bekende en vanzelfsprekende features. Dit zal leiden tot een snellere acceptatie van de applicatie en prettigere gebruikerservaring.

Citation preview

Page 1: How te bring common UI patterns to ADF

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

Page 2: How te bring common UI patterns to ADF

UI PATTERNS

Page 3: How te bring common UI patterns to ADF

FUSION APPS PATTERNS

Page 4: How te bring common UI patterns to ADF

RECOGNIZE THESE ?

Page 5: How te bring common UI patterns to ADF

RECOGNIZE THESE ?

Page 6: How te bring common UI patterns to ADF

TABBED NAVIGATION

Page 7: How te bring common UI patterns to ADF

TABBED NAVIGATION

Page 8: How te bring common UI patterns to ADF

CLOSE ALL / CLOSE OTHERS

Page 9: How te bring common UI patterns to ADF

CLOSE ALL / CLOSE OTHERS

Page 10: How te bring common UI patterns to ADF

CLOSE ALL / CLOSE OTHERS

• e

Page 11: How te bring common UI patterns to ADF

CAN YOU DO THIS IN ADF ?

Page 12: How te bring common UI patterns to 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>

Page 13: How te bring common UI patterns to ADF

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();

}

Page 14: How te bring common UI patterns to ADF

USE EXISTING FUNCTIONALITY

Page 15: How te bring common UI patterns to ADF

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);

}

}

Page 16: How te bring common UI patterns to ADF

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);

}

}

Page 17: How te bring common UI patterns to ADF

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);

}

}

Page 18: How te bring common UI patterns to ADF

CLOSE ALL / CLOSE OTHERS

Page 19: How te bring common UI patterns to ADF

MOST RECENTLY USED (..HISTORY)

Page 20: How te bring common UI patterns to ADF

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!

Page 21: How te bring common UI patterns to ADF

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>

Page 22: How te bring common UI patterns to ADF

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>

Page 23: How te bring common UI patterns to ADF

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));

Page 24: How te bring common UI patterns to ADF

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});

}

Page 25: How te bring common UI patterns to ADF

THE RESULT

Page 26: How te bring common UI patterns to ADF

DO YOU RECOGNIZE THIS ??

Page 27: How te bring common UI patterns to ADF

GOOGLE SEARCH

Page 28: How te bring common UI patterns to ADF

ADF QUERY COMPONENT ……

Page 29: How te bring common UI patterns to ADF

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

Page 30: How te bring common UI patterns to ADF

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;

Page 31: How te bring common UI patterns to ADF

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)'')';

Page 32: How te bring common UI patterns to ADF

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.

Page 33: How te bring common UI patterns to ADF

CREATE THE MODEL PROJECT

Page 34: How te bring common UI patterns to ADF

CREATE THE MODEL PROJECT

Page 35: How te bring common UI patterns to ADF

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>

Page 36: How te bring common UI patterns to ADF

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>

Page 37: How te bring common UI patterns to ADF

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;

}

Page 38: How te bring common UI patterns to ADF

THE RESULT

Page 39: How te bring common UI patterns to ADF

REAL TIME UPDATES

Page 40: How te bring common UI patterns to ADF

THE CONCEPT

Page 41: How te bring common UI patterns to ADF

THE IMPLEMENTATION; THE DATABASE

grant change notification to <user>;

Page 42: How te bring common UI patterns to ADF

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);

………..

Page 43: How te bring common UI patterns to ADF

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();

Page 44: How te bring common UI patterns to ADF

WHATS NEXT ….

Page 45: How te bring common UI patterns to ADF

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);

}

Page 46: How te bring common UI patterns to ADF

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);

}

Page 47: How te bring common UI patterns to ADF

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>

Page 48: How te bring common UI patterns to ADF

THE RESULT

Page 49: How te bring common UI patterns to ADF

PATTERNS UNDER INVESTIGATION

• Grouping Tabs

• Drag and Drop Tabs in UI Shell

– dragSource and dropTarget

• Duplicating Tabs

– Restarting a new instance of a taskflow

Page 50: How te bring common UI patterns to ADF

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/

Page 51: How te bring common UI patterns to ADF

RESOURCES

Page 52: How te bring common UI patterns to ADF

RESOURCES

Page 53: How te bring common UI patterns to ADF

SUMMARY

Page 54: How te bring common UI patterns to ADF

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