Luc Bors presented ways to bring common UI patterns to Oracle ADF applications, including implementing tabbed navigation, context menus for tabs, closing tabs, and most recently used functionality. The document also discussed implementing real-time updates using database change notification and the active data framework. Finally, it covered patterns still under investigation such as grouping tabs, drag and drop tabs, duplicating tabs, and adding sticky notes.
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);
}
}
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>
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.
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
54. 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