In the past few days, I have been working hard on several projects – both ADF and (plain) Java based, with quite a bit of JavaScript involved as well. The three main functional challenges:
- support keyboard (function key based) navigation in rich ADF Web pages (in addition to mouse based actions)
- support online and inline editing of customized (per context) resource bundle entries
- create a stand-alone viewer that allows users to inspect images (jpeg, tiff), PDF documents and Word and Excel documents
While working on these requirements, I have used – through Google, my main tool – a large number of very valuable resources on the internet. From the Oracle Technology Network Forums (OTN) to StackOverflow (http://stackoverflow.com), from personal blogs to corporate white papers as well as formal documentation – I have picked an incredible number of brains in a very condensed period of time.
I did not stop to leave notes of gratitude on all the sites I have come across. So I thought – for my own future reference as well as to pay some hommage to all these sites and individuals that helped me and to provide some insight in what challenges I faced and how I addressed them – to write down some notes on my explorations. They may be helpful to some of you as well.
Regular Expressions in JavaScript
I had a need to find all :<SomeNumber>: occurrences in a string (actually a complex component id inside a table). For example: extract :34:, :45: and :3: from someElement:34:child:parent:45:aaa:higher:3:andmore. I started with this article on Stack Overflow: http://stackoverflow.com/questions/7954022/javascript-regular-expression-multiple-match?rq=1 and continued with http://stackoverflow.com/questions/5440714/find-end-index-of-a-regular-expression-search-match – a clear explanation on how the match operation can be used on strings in JavaScript to do a Regular Expression based search and have multiple results returned. The code I ended up with:
Regular Expression in Java
A similar situation in (server side) Java code: how to find numbers surrounded by colons in a string. In a manageable and performant way. StackOverflow helped me with some insights into Pattern and Matcher (http://stackoverflow.com/questions/3862917/pattern-matcher-vs-pattern-matches). This quickly gave me what I needed. This other article warned about the performance costs of compiling the Pattern and suggested the use of a private static to compile the pattern only once: http://stackoverflow.com/questions/237061/using-regular-expressions-to-extract-a-value-in-java. One of my favorite authors of course published a great article on Regular Expressions in Java – http://www.vogella.com/articles/JavaRegularExpressions/article.html by Lars Vogel – only this time it gave me much more than I needed.
The Java snippet that in the end found its way into my code:
Keyboard short-cuts in major browsers
One of the projects I am involved in has a requirement to provide users with familiar key combinations- familiar that is from a previous generation technology based application – for key functions in the brand new web application. Unfortunately, as it turned out, many of those familiar function keys are not available in (all) modern browsers. Keys such as F3 and ALT+F are hijacked in all major browsers, as are F12 and Shift-F12. F4 is already reserved in IE – though not in Chrome and Firefox. So the list goes on – whatever the end users considered familiar, was typically not available in at least one of the browsers we have to support.
The complete lists of function keys – for easy reference – are on these URLs:
- https://support.google.com/chrome/bin/answer.py?hl=en&answer=157179 (for Chrome),
- http://windows.microsoft.com/en-US/windows7/Internet-Explorer-keyboard-shortcuts (for Internet Explorer)
- http://support.mozilla.org/en-US/kb/keyboard-shortcuts-perform-firefox-tasks-quickly (for Firefox)
Programmatic Manipulation of ADF Tables
Programmatically moving around in ADF Tables is not a trivial thing. There is some support for doing things on the client side – but these are not well documented and I was not able to get to work as expected some of the things that are documented. The holy grail I was after was to provide end users with easy key combinations that allow navigation to the next and previous record as well as the first and last record in the (editable!) table. Of course navigation in the table should be synchronized on the server with navigation in the underlying iterator as well as associated (detail) iterators and dependent client components. Some of the resources I have consulted on ADF Table manipulation:
- A new method to scroll the ADF Table to a specified row number – https://blogs.oracle.com/raghuyadav/entry/scroll_to_specified_row_number
- ADF Code Corner on Programmatically scrolling to a specific row-number: http://www.oracle.com/technetwork/developer-tools/adf/learnmore/28-ctrl-g-table-scrolling-169170.pdf – very important: the code to get to the IteratorBinding under any ADF RichTable
- My introduction to partialUpdateNotify() – https://forums.oracle.com/forums/thread.jspa?threadID=2364920
- Insert record (server side) in RowSetIterator under Table and scroll table to new record – https://forums.oracle.com/forums/thread.jspa?threadID=1037879&tstart=0
- The ADF Face Rich Client JavaScript API – http://docs.oracle.com/cd/E15523_01/apirefs.1111/e12046/overview-summary.html
- An Oracle White Paper – July 2011 – ADF Design Fundamentals – Using JavaScript in ADF Faces Rich Client Applications – http://www.oracle.com/technetwork/developer-tools/jdev/1-2011-javascript-302460.pdf
- Declaratively setting the current row in a ViewObject – http://jobinesh.blogspot.nl/2011/01/declaratively-setting-current-row-key.html on the wonderful blog Decomping ADF Binaries by Jobinesh Purushothaman
- Oracle Documentation on built in short-cuts in ADF Faces components: http://docs.oracle.com/cd/E24382_01/web.1112/e16181/ap_kbd.htm
- OTN Forum: https://forums.oracle.com/forums/thread.jspa?threadID=1024124 – “Need help with adf table row selection”
- OTN Forum: https://forums.oracle.com/forums/thread.jspa?threadID=2182930 – “Iterate Table rows in JavaScript”
- OTN Forum: https://forums.oracle.com/forums/thread.jspa?threadID=722697 – “Move to the next inputtext with the ENTER key instead of TAB “
- OTN Forum: https://forums.oracle.com/forums/thread.jspa?threadID=1106692 – “Moving the row of the table up/down/start/end “
- OTN Forum: https://forums.oracle.com/forums/thread.jspa?threadID=2238032 – “row selection on a table (Data pushed by ADS) “
- JavaScript with ADF Faces Samples – http://sameh-nassar.blogspot.nl/2010/02/javascript-functions-sample.html – useful collection of JavaScript snippets for use with ADF Faces by Sameh Nassar
- Programmatically executing a clientside behavior – both from JavaScript as well as from Java: https://blogs.oracle.com/jdevotnharvest/entry/invoking_af_exportcollectionactionlistener_from_java by Frank Nimphius
Viewing various Document Types in Java
While Java (Swing, AWT and more recently JavaFX) offers various out of the box facilities for displaying different types of files, for other file types we will need to use additional libraries and tools. Some findings on this:
OpenOffice has (Java based) programmatic facilities for converting Word and Excel files to OpenOffice format and from OpenOffice format to PDF. Some tools and libraries have been published that leverage those facilities. This article describes the API in OpenOffice that can be used for exporting PDF documents: http://wiki.services.openoffice.org/wiki/API/Tutorials/PDF_export.
docx4j is a Java library for creating and manipulating Microsoft Open XML (Word docx, Powerpoint pptx, and Excel xlsx) files. See: http://www.docx4java.org/trac/docx4j It can export DOCX documents to PDF.
PDF previewer in Java: https://technology.amis.nl/2008/11/28/java-generating-pdf-and-previewing-it-as-an-image-itext-and-pdf-renderer/ . LGPL edition of jPedal: http://www.jpedal.org/open_source_pdf_viewer_download.php.
Example of loading and displaying an image in a JavaFX 2.0 application: http://lawrencepremkumar.wordpress.com/2011/07/03/getting-percentage-of-image-loading-in-javafx-2-0/.
jPedal JavaFX 2.0 PDF Viewer – http://www.idrsolutions.com/jpedalfx-viewer/ – provided under LPGL license. Discussion on showing PDF from JavaFX on OTN Forum: https://forums.oracle.com/forums/thread.jspa?threadID=2326735.
Open source project JODConverter, the Java OpenDocument Converter, converts documents between different office formats.
It leverages OpenOffice.org, which provides arguably the best import/export filters for OpenDocument and Microsoft Office formats available today. (Word to PDF; Excel to PDF; PowerPoint to PDF) : www.artofsolving.com/opensource/jodconverter.
Java Advanced Imaging API Home Page : http://java.sun.com/products/java-media/jai/iio.html (for working with TIFF images)
Miscellaneous
Some important observations I should remember:
- putting focus on a component too quickly can easily happen with JavaScript being executed after returning from a partial page refresh request – the actual creation of the component seems to lag sometimes a little bit behind. A good way of working around this problem is by deferring the execution of the code that puts the focus, through the use of a JavaScript Timer – for example setTimeOut(function () { codeToExecute; , 250)
- debugging Java classes that have been imported from an ADF Library can be done by deploying the sources to a normal JAR that is imported as well – see: https://technology.amis.nl/2010/04/03/adf-11g-debugging-task-flows-embedded-from-adf-libraries-using-source-code-jars/
- Useful snippets for doing API stuff with ADF: http://delivers2u.blogspot.nl/2011/10/how-to-access-adf-definitions-using.html (How to access the ADF definitions using Managed Bean by Ankit Shah) and http://biemond.blogspot.nl/2009/03/some-handy-code-for-backing-beans-adf.html (Some handy code for backing beans ( ADF & JSF ) by Edwin Biemond)
- The locale can be set in JSF using: FacesContext.getCurrentInstance().getViewRoot().setLocale(locale); At ADF level, you can use:
BindingContext.getCurrent().setLocaleContext(new DefLocaleContext(locale));
ADFContext.getCurrent().setLocale(locale);