Wednesday, October 19, 2011

ADF 11g : Query Component with ‘dynamic’ view criteria

In my current project use a lot of re usable taskflows. In one particular situation I needed exactly the same taskflow to be re-used with one tiny small difference: The displayed query component needed to have different fields compared to page in the base taskflow. Now there are lots of possible solutions (two query components and a switcher, or two query components using the rendered property). I choose a different solution using ternary operator and EL in the page definition.

Use case

I need to display a different query component when the taskflow is started in a specific mode. For instance I can startup the taskflow a being a HR manager, or I can startup the taskflow as being an employee. In the first case I need to be able to search on items like salary and commission and hiredate. In the second case I need to be able to search on firstname. lastname and more stuff like that, and I can only see employees in my own department.

Setup:

Lets start with the creation of default business components for the Employee table. Next step is the creation of view criteria. I need two view criteria. The first one is called ManagerVC, the second on EmployeeVC.




With this in place I create a simple taskflow with a pagefragment. The taskflow has an inputParameter called 'startupMode'. The pagefragment contains a table with a query component. This is easy to create by dragging the Employees collection from the datacontrol onto the pagefragment and pick "query panel with table".



Make sure to have single row selection enabled.



I also create a testpage in order to run my taskflow. The testpage is a rather simple page containing two buttons, and a bean to hold the value of the button that is pushed.
 <af:toolbar id="t1">  
<af:commandToolbarButton text="Start as Manager" partialSubmit="true" id="ctb1">
<af:setPropertyListener from="mgr" to="#{TesterBean.buttonPushed}" type="action"/>
</af:commandToolbarButton>
<af:commandToolbarButton text="Start as Employee" id="ctb2"partialSubmit="true">
<af:setPropertyListener from="emp" to="#{TesterBean.buttonPushed}" type="action"/>
</af:commandToolbarButton>
</af:toolbar>

I drop my taskflow on the page as a region. I link the inputparameter of the taskflow to the buttonPushed property. Don't forget to set the refresh option to 'ifNeeded', so the region will refresh whenever the input paramaters change.



When I run the page you will see the querycomponent as expected.



The trick:
Now take a look what happened when the query component was created. The page definition states contains an executable binding for the search region.
 <searchRegion Criteria="CriteriaForManager"  
Customizer="oracle.jbo.uicli.binding.JUSearchBindingCustomizer"
Binds="EmployeesView1Iterator"
id="CriteriaForManagerQuery"/>

This is exactly the place where I will use an EL expression (yes you can do that) to dynamically set the viewcriteria to be used by the query component. Lets change the "criteria" attribute. Whenever the taskflow is started by a manager I want the CriteriaForManager viewcriteria to be used by the querycomponent, and in other cases the CriteriaForEmployee.
 <searchRegion Criteria="#{pageFlowScope.startupMode eq 'mgr' ? 'CriteriaForManager' : 'CriteriaForEmployee'}"  
Customizer="oracle.jbo.uicli.binding.JUSearchBindingCustomizer"
Binds="EmployeesView1Iterator"
id="CriteriaForManagerQuery"/>

Now this is really all I changed. No changes to the page whatsoever. When I run the page after this minor change, depending on the startupmode, a different querycomponent is rendered. Or actually, the querycomponent stays the same, only the viewcriteria used are different.



Resources:
This post was initially posted by me on the AMIS technology blog.
The workspace can be downloaded here.

Monday, October 03, 2011

ADF 11g Quicky 3 : Adding Error, Info and Warning messages

How can we add a message programatically ? Last week I got this question for the second time in a months time. I decided to write a short blogpost on how this works.

Adding messages is very easy, you just need to know how it works.
You can add a message to your faces context by creating a new FacesMessage. Set the severity (ERROR, WARNING, INFO or FATAL ), set the message text, and if nessecary a message detail. The fragment below shows the code for an ERROR message.

1:   public void setMessagesErr(ActionEvent actionEvent) {  
2: String msg = "This is a message";
3: AdfFacesContext adfFacesContext = null;
4: adfFacesContext = AdfFacesContext.getCurrentInstance();
5: FacesContext ctx = FacesContext.getCurrentInstance();
6: FacesMessage fm =
7: new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, "");
8: ctx.addMessage(null, fm);
9: }


I created a simple page with a couple of buttons to show the result of setting the message. When the button is pressed the message is shown.
1:  <?xml version='1.0' encoding='UTF-8'?>  
2: <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
3: xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
4: xmlns:f="http://java.sun.com/jsf/core">
5: <af:inputText label="Label 1" id="it1"></af:inputText>
6: <af:inputText label="Label 2" id="it2"
7: binding="#{pageFlowScope.msgsBean.showMessage}"></af:inputText>
8: <af:inputText label="Label 3" id="it3"></af:inputText>
9: <af:commandButton text="error" id="cb1"
10: actionListener="#{pageFlowScope.msgsBean.setMessagesErr}"/>
11: <af:commandButton text="info" id="cb2"
12: actionListener="#{pageFlowScope.msgsBean.setMessagesInf}"/>
13: <af:commandButton text="warn" id="cb3"
actionListener="#{pageFlowScope.msgsBean.setMessagesWrn}"/>
14: 15: actionListener="#{pageFlowScope.msgsBean.setMessagesFat}"/>
16: <af:commandButton text="warn for comp" id="cb4"
17: actionListener="#{pageFlowScope.msgsBean.setMessagesWrnForComp}"/>
18: </jsp:root>



A special case is the message that is directly related to a component. For that I use the button that calls the "setMessageForComp" method combined with an inputtext field that is bound to a bean : binding="#{pageFlowScope.msgsBean.showMessage}.
The code behind this button is slightly different from the one show in the java fragment earlier. The important part is that the message is specifically added to the component : getShowMessage().getClientId(ctx).

1:   public void setMessagesWrnForComp(ActionEvent actionEvent) {  
2: // Add event code here...c
3: String msg = "This is a message";
4: AdfFacesContext adfFacesContext = null;
5: adfFacesContext = AdfFacesContext.getCurrentInstance();
6: FacesContext ctx = FacesContext.getCurrentInstance();
7: FacesMessage fm =
8: new FacesMessage(FacesMessage.SEVERITY_WARN, msg, "");
9: ctx.addMessage(getShowMessage().getClientId(ctx), fm);
10: }
11: public void setShowMessage(RichInputText showMessage) {
12: this.showMessage = showMessage;
13: }
14: public RichInputText getShowMessage() {
15: return showMessage;
16: }
17: public void setMessagesWrnForComp(ActionEvent actionEvent) {
18: // Add event code here...c
19: String msg = "This is a message";
20: AdfFacesContext adfFacesContext = null;
21: adfFacesContext = AdfFacesContext.getCurrentInstance();
22: FacesContext ctx = FacesContext.getCurrentInstance();
23: FacesMessage fm =
24: new FacesMessage(FacesMessage.SEVERITY_WARN, msg, "");
25: ctx.addMessage(getShowMessage().getClientId(ctx), fm);
26: }
27: public void setShowMessage(RichInputText showMessage) {
28: this.showMessage = showMessage;
29: }
30: public RichInputText getShowMessage() {
31: return showMessage;
32: }





The code for this quicky can be downloaded here.

Sunday, September 18, 2011

Announcement – Free ADF Webinar for ODTUG

This Tuesday I will present a webinar for ODTUG. In this webinar I will talk about how to provide management information from within your ADF application. Topics : ADF DVT's, Google Maps, MS Excel, and Reporting Solutions.

Tuesday, September 20, 2011, 3:00 PM - 4:00 PM EST
Reaching out from ADF: Management Information using ADF-DVT, Google Maps, MS Excel, and Oracle Reports. Luc Bors, AMIS Services

Usually applications serve purposes such as data entry and process support. Another purpose is to provide management information.In your ADF 11g application you can use Oracle ADF Data Visualization Tools (ADF-DVT) but there are also other options that are not necessarily part of the ADF Framework. This session gives an overview of your possibilities and will answer the following questions:
  • How to integrate ADF-DVT graphs in your application and how to make them interactive for your business users?
  • How to use ADF-DVT maps in your application and how to interact with Google maps?
  • How to interact with Excel?
  • How to add reporting to your application and can you protect your investment in Oracle Reports?
You will learn how to use ADF to provide management information and how to interact with third party tools to add extra functionality to your ADF Application.

You can still register for this webinar. Registration Web Link

Wednesday, August 31, 2011

ADF 11g : Using the ActiveRowKey property

In ADF 11g Release 2, the ADF Table component has a property called 'ActiveRowKey'. According to documentation, this represents the row that is currently active on the client. In click-to-edit mode, the active row will be made editable and is brought into view (if not already visible). Upon initial display, the click-to-edit component defaults the active row to the first visible row.

In this post I will show you how to use the activeRowKey programmatic.

Use Case.

Imagine the following use case: I have a 'click-to-edit' table and I added a 'filter' field with a button in the surrounding panel collection. User enters (in this case) a last name and pushes the button. The table scrolls to the first row that matches the criteria, and the row is active to edit.

Implementation.

I create an ADF table based on ADF business components for the Employees table.
It's a clickToEdit table with singleSelection. After creating it I bind it to a bean. I'll show later why I need to do that. The table code looks like this:
1:        <af:table value="#{bindings.Employees1.collectionModel}" var="row"  

2: rows="#{bindings.Employees1.rangeSize}"
3: emptyText="#{bindings.Employees1.viewable ? 'No data to display.' : 'Access Denied.'}"
4: fetchSize="#{bindings.Employees1.rangeSize}"
5: rowBandingInterval="0"
6: selectionListener="#{bindings.Employees1.collectionModel.makeCurrent}"
7: rowSelection="single" id="t1" editingMode="clickToEdit"
8: selectedRowKeys="#{bindings.Employees1.collectionModel.selectedRow}"
9: binding="#{pageFlowScope.empsBean.empTable}">
10: <af:column ............................


Next I surround it with a panel collection and I turn off a lot of features (also new in R2) of the panel collection. In the toolbar facet I add an inputText component and a commanfbutton. The inputtext will hold the search value, and the button invokes logic to scroll the table and make to row active.

1:       <af:panelCollection id="pc1" featuresOff="viewMenu detach" >  

2: <f:facet name="menus"/>
3: <f:facet name="toolbar">
4: <af:toolbar id="t2">
5: <af:group id="g1">
6: <af:inputText label="enter last name" value="#{pageFlowScope.empsBean.searchValue}" id="it11"/>
7: <af:commandToolbarButton text="goto employee" id="ctb1"
8: actionListener="#{pageFlowScope.empsBean.gotoPressed}"/>
9: </af:group>
10: </af:toolbar>
11: </f:facet>


In the actionListener I first get a hold of the RowSetItetator. For each and every row in the rowSetIterator, I check if it matches the entered search string. I do that in a separate method called matchFound() (see line 8).

1:   public void gotoPressed(ActionEvent actionEvent) {  

2: // Add event code here...
3: DCIteratorBinding it = ADFUtils.findIterator("Employees1Iterator");
4: RowSetIterator rsi = it.getRowSetIterator();
5: RowKeySet oldSelection = empTable.getSelectedRowKeys();
6: if (rsi.first() != null) {
7: Row r = rsi.first();
8: while (rsi.hasNext() && getKey() == null && (!matchFound(r,oldSelection))) {
9: r = rsi.next();
10: }
11: }
12: }


In the matchFound() method I compare the value of the LastName attribute with the value entered by the user (see line 7). If it is a match there are two more things I need to do. First I add the key of the row found to be the activeRowKey (see line 11). Finally I need to make the row current. If I dont do this, it will still work, but by making the row current, it just looks a lot nicer. The trick I use here (see line 13) is a method (line 18) that I borrowed from Frank Nimphius' blog.

1:   private boolean matchFound (Row r,RowKeySet oldSelection){  

2: setKey(null);
3: ArrayList lst = new ArrayList(1);
4: RowKeySetImpl newSelection = new RowKeySetImpl();
5: Key key = null;
6: String rowValue = (String)r.getAttribute("LastName");
7: if (rowValue.toString().contains(searchValue)) {
8: System.out.println("now setting key to " + key);
9: key = r.getKey();
10: lst.add(key);
11: empTable.setActiveRowKey(lst);
12: newSelection.add(lst);
13: makeCurrent(empTable, newSelection, oldSelection);
14: return true;
15: }
16: return false;
17: }
18: private void makeCurrent(RichTable empTable, RowKeySet newCurrentRow, RowKeySet oldCurrentRow) {
19: //To make a row current, we need to create a SelectionEvent which
20: //expects the following arguments: component, unselected_keys,
21: //selected_keys. In our example, we don't have unselected keys and
22: //therefore create an empty RowSet for this
23: SelectionEvent selectionEvent =
24: new SelectionEvent(oldCurrentRow, newCurrentRow, empTable);
25: selectionEvent.queue();
26: AdfFacesContext.getCurrentInstance().addPartialTarget(empTable);
27: }


The works.

Start the application, type some searchText, push the button and of you go.


The row is found, and immediate available for edit.


Resources.

ADF Code Corner Oracle JDeveloper OTN Harvest

A copy of the workspace for this post can be downloaded here.

Wednesday, July 27, 2011

ADF 11g : Show PDF in a Popup

In one of my previous posts I showed how to use ADF popup components to display external content such as webpages like wikipedia in an inline frame. Based on this post a colleague of mine tried to display a PDF document. That didn't work. In this post I explain how you can use a servlet to open a PDF document in the inline frame. I will not explain how to invoke popups. If you need to know how to do that, refer to the post mentioned earlier.

How to create the servlet ?

The solution for showing a PDF in a popup is to use a servlet. It's possible to have a servlet deliver PDF content to the browser by specifying the content type of the servlet response to be the 'application/pdf' MIME type via 'response.setContentType("application/pdf")'.
In JDeveloper you can create a HTTP servlet very easy via the new gallery. I decided to call the servlet ShowPdfServlet which actually is a pretty descriptive name for this servlet.


For the servlet mapping I accept the default, meaning that all request containing "/showpdfservlet" in the URL will invoke the servlet. The "create servlet" wizard of JDeveloper will make sure that teh servlet and its mapping is added to the web.xml of your application.


The servlet will get the filename form a request parameter. So in the servlet I can get this value by invoking getParameter on the request.
1: String requestedFile = request.getParameter("name");

With this parameter value, and the file path (which I hardcoded for this post) I am now able to create a new File Object.
1:     // I want to invoke a pdf that is located on the machine where the application is running
2: this.filePath =
"C:\\JDeveloper\\mywork\\11gR2\\showPdfInPopup\\ViewController\\public_html\\WEB-INF\\pdf-docs";
3: // Decode the file name (might contain spaces and on) and prepare file object.
4: File file = new File(filePath, URLDecoder.decode(requestedFile, "UTF-8"));

Next step is to initiate the servlet response:
1: response.reset();
2: response.setBufferSize(DEFAULT_BUFFER_SIZE);
3: response.setContentType(contentType);
4: response.setHeader("Content-Length", String.valueOf(file.length()));
5: response.setHeader("Content-Disposition",
"filename=\"" + file.getName() + "\"");

And now finally get the file and write it to the response.
1:    try {  
2: // Open streams.
3: input =
4: new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);
5: output =
6: new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);
7: // Write file contents to response.
8: byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
9: int length;
10: while ((length = input.read(buffer)) > 0) {
11: output.write(buffer, 0, length);
12: }


How to make sure the servlet is invoked ?

Remember the servlet mapping that I used earlier ? Now I will use this to make sure that I invoke the servlet every time I open the popup containing the iframe. I simply make sure thate the source of the iframe to contains the path that I use in the servletmapping. I also add a 'name' request parameter and set its value to (in this case) a value that I get from a managed bean (line 7).
1:   <af:popup id="popupFileSpecs" animate="default"  
2: contentDelivery="lazyUncached">
3: <af:panelWindow id="pw1" modal="true"
4: title="Extra information for your flight"
5: contentHeight="625" contentWidth="700" resize="on">
6: <af:inlineFrame id="if1" shortDesc="This is an inline frame"
7: source="/showpdfservlet?name=#{pageFlowScope.GeneralBean.pdfUrl}"
8: styleClass="AFStretchWidth" inlineStyle="height:600px;"></af:inlineFrame>
9: </af:panelWindow>
10: </af:popup>


Now run the application, and invoke the popup. There you go !


Simple as that.

Resources

The BalusC Code
What is a servlet ?

A copy of the workspace can be downloaded here.

Tuesday, July 26, 2011

ADF 11g : Printing Directly From Your Application

Last week I was asked this question : "Can we print directly from within our ADF Application, without invoking the printer dialog ?" I wasn't sure but after some investigation the answer was clear. Yes you can ! Here is how...

I decided to create a print start up form where I can select printers and print the document. Most of the functionality needed is provided by the Java Print Service API.

Selecting available printers

I start with a way to show all printers available to the session. For that I simply use the PrinterServiceLookup.
 PrintService[] printers =
PrintServiceLookup.lookupPrintServices(null, null);

The result I can now use to create an Array of SelectItems in order to make the list available in the application.
1:   public SelectItem[] getAllPrinters() {
2: if (allPrinters == null) {
3: PrintService[] printers =
4: PrintServiceLookup.lookupPrintServices(null, null);
5: allPrinters = new SelectItem[printers.length];
6: for (int i = 0; i < printers.length; i++) {
7: SelectItem printer =
8: new SelectItem(printers[i].getName(), printers[i].getName());
9: allPrinters[i] = printer;
10: }
11: }
12: return allPrinters;
13: }

On the pagefragment I use a selectOneChoice component getting the values from the list created above. The code for the pagefragment is like this:
1:    <af:selectOneChoice label="Available Printers" partialTriggers="cb1"  
2: value="#{pageFlowScope.applicationPrinterBean.selectedPrinter}"
3: id="soc1" autoSubmit="true">
4: <f:selectItems value="#{pageFlowScope.applicationPrinterBean.allPrinters}"
5: id="si1"/>
6: </af:selectOneChoice>

When I run the application I see a list of all printers defined om my local machine and I can select any printer I like ...


What is the default printer ?

Usually there is a default printer defined. That is the one I want to use by default in this application. For that to work I need to get hold of the default printer defined. This can be found by invoking lookupDefaultPrintService().
1:   public String getDefaultPrinter() {
2: PrintService defaultPrinter =
3: PrintServiceLookup.lookupDefaultPrintService();
4: return defaultPrinter.getName();
5: }

If no printer is selected yet in the ADF Application, I use the default printer. I need to make an adjustment to the getter of the selected printer to return the default printer.
1:   public String getSelectedPrinter() {
2: if (selectedPrinter == null) {
3: return getDefaultPrinter();
4: } else {
5: return selectedPrinter;
6: }
7: }

Final requirement for the print startup form is to be able to reset the selected printer to the default if another printer was selected previously. For that I use a CommandButton that invokes an actionListener where I simply set the currently selected printer to be the default printer.
1:   public void resetToDefault(ActionEvent actionEvent) {
2: // Add event code here...
3: setSelectedPrinter(getDefaultPrinter());
4: }

By using this button, the default printer will be selected again.


Now what about the actual printing ?

Printing can be done by using the DocPrintJob, FileInputStream and Doc objects.
First is to create a FileInputStream based on the file that I want to print.
Next step is to create a Doc object based on the FileInputStream. Finally create a PrintJob based on the Doc object. I also show the user a message when something goes wrong. All this functionality is implemented in an actionListener behind a command button.
1:   public void invokePrintJob(ActionEvent actionEvent) {
2: // Add event code here...
3: PrintService[] printers =
4: PrintServiceLookup.lookupPrintServices(null, null);
5: Boolean printerFound = false;
6: for (int i = 0; i < printers.length && !printerFound; i++) {
7: if (printers[i].getName().equalsIgnoreCase(getSelectedPrinter())) {
8: printerFound=true;
9: PrintService printer = printers[i];
10: FileInputStream input;
11: try {
12: input =
13: new FileInputStream(theFile);
14: Doc doc = new SimpleDoc(input, DocFlavor.INPUT_STREAM.PNG, null);
15: PrintRequestAttributeSet attrs = new HashPrintRequestAttributeSet();
16: DocPrintJob job = printer.createPrintJob();
17: job.print(doc, attrs);
18: } catch (PrintException e) {
19: System.out.println(e.getMessage());
20: addFacesErrorMessage(e.getMessage());
21: } catch (FileNotFoundException e) {
22: System.out.println(e.getMessage());
23: addFacesErrorMessage(e.getMessage());
24: }
25: }
26: }
27: }

The code for the page fragment is simple.
1:    <af:toolbar>    
2: <af:commandToolbarButton text="Reset to Default"
3: actionListener="#{pageFlowScope.applicationPrinterBean.resetToDefault}"
4: partialSubmit="true" id="cb1"/>
5: <af:commandToolbarButton text="Print" id="ctb1"
6: actionListener="#{pageFlowScope.applicationPrinterBean.invokePrintJob}"/>
7: </af:toolbar>

And the page now has a print button.

When the print button is pushed, the document is sent directly to the printer.

It is also possible to set job properties such as number of copies, the orientation of the print, and many other properties.
1:  attrs.add(new Copies(2));
2: attrs.add(OrientationRequested.LANDSCAPE);

I can check the result of this in the print properties of the printjob.

Now one last thing to do is to give the printjob a decent name. As you can see, by default, all jobs have the same name, and that has no relation whatsoever with the document name, neither can it be related to a user or client.

I want to use a jobname that is more descriptive. I can do that by adding the JobName to the PrintRequestAttributeSet.
1:  PrintRequestAttributeSet attrs = new HashPrintRequestAttributeSet();
2: attrs.add(new Copies(2));
3: attrs.add(OrientationRequested.LANDSCAPE);
4: JobName name = new JobName(file ,null);
5: attrs.add(name);

The result is obvious.


Conclusion
http://www.blogger.com/img/blank.gif
Printing can be done directly from within the ADF Application. You can use almost any of the properties that can be used in the printer dialog of your browser or operating system. This example can be extended and I will probably create an ADF taskflow library to deploy this functionality.

Resources : javax.print javadoc

You can request a copy of the workspace by emailing me at lucbors at gmail dot com. OR you can download the workspace here.

Monday, July 25, 2011

ODTUG Kscope 11: My story on ADF in the Fusion MiddleWare Track

From June 26th to June 30th the KScope 11 conference was in Long Beach California. Nice setting for a great conference. It was the first time that KScope had a Fusion Middleware Track. For me it was a very busy conference with three presentations, handson workshops, live demonstrations and a Boff session with the EMG. In this post some of my highlights.



Friday and Saturday
On Friday in the airplane and Saturday in Long Beach I wrote a review for Sten Vesterli's book. The review can be found here on the AMIS Technology Blog.

Sunday Symposium
The symposium started very early. That is 7.30 including breakfast and registration.
Then some great sessions on ADF and SOA and Webcenter. Chris Muir and John King talked about ADF, Sten Vesterli and Hajo Norman about WebCenter, Lonneke Dikmans and Chris Judson talked about SOA and BPM. Finally Madhuri Kolhatkar \was presenting on User Experience Design Patterns. She pointed out a very usefull resource where you can find OBIEE Design Patterns that are just as well applicable to FMW and ADF Applications. Image
Too bad that currently the site is down (http://blogs.oracle.com/usableapps/entry/usableapps_web_site_down).

Monday
Day started after a hilarious opening session in the Long Beach Performing Arts Center. I attended two sessions and spent some time on preparing my own sessions for Tuesday. The first session "WebCenter Spaces: A Beginner's Guide to Enterprise 2.0 By Maicho Rocha of Oracle Corporation."
In this webcenter spaces session maiko showed how to recreate the kscope website with spaces. Very nice. Maiko also revealed that Webcenter Release 12 will introduce 'iGoogle' like functionality to add components to your personal space. Maiko had a live kscope WebCenter portal that we could play with during his presentation. Very cool indeed !

The other one "Introduction to JPA and How to Use it with Oracle ADF by Shay Shmeltzer of Oracle Corporation." Introducing the key concepts of JPA and explain how it works. It will show you how you can leverage JPA as the database access layer in an Oracle ADF application, and what special features you get from this integration. I didn't learn a lot new features, however, the fact that in JDeveloper 11gR2 named criteria, UI hints, validations and more ADF BC related features are also available for JPA was new for me. As was the fact that named criteria defined on a JPA entity can be dragged from the datacontrol and dropped as an adf queryform.

Monday evening there was the ADF-EMG Boff Session. A (for a Boff) nice headcount in the audience (about 25), and we discussed existing and new topics for the EMG, derived from the 'new member questionnaire'.

Tuesday
A busy (Actually way too busy) day for me with two sessions. The presentations can be found on slideshare. The first one "ADF Developers : Make the database work for you" did go very good. In this session I discussed the various points of interaction between database and ADF and when to use which. I also highlighted some special database features - flashback, View with Instead Of Trigger, and Analytical Functions and DB Query ResultSet Change Notification.

The second one : "A Picture paints a thousand words" did also go pretty good. It was about how to present data with ADF DVT and how to use DVT components for data analysis. From pretty straightforward usage of gauges, graphs, and maps, to more sophisticated features like time selectors, drill down functionality, data manipulation in DVT, and real time update via server push. A had a good crowd, considering that @DuncanMills was presenting next door on ADF debugging.

In between I also managed to follow two other sessions. The first one called Going Social: Enriching Your ADF Applications with Webcenter by Maiko Rocha of Oracle Corporation.

The second one Skinning ADF - Getting the Look You Want by Shay Shmeltzer of Oracle Corporation.
Some very nice demos of the new visual skin editor. Also a nice tip on how to use firebug in order to know what elements you actually need to skin. Just add an entry to the web.xml file to prevent ADF Faces from compressing the HTML that is generated. The entry is for you will be looking for is:
org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION
Set it to true. This is very useful when you work on creating the skin, but don't forget to un-set it before you go production. And look what was created in just under an hour.....


More resources on this session can be found here : the video of the #JDeveloper ADF Faces Skin Editor, based on Shays KScope session http://t.co/KksU3vR and a blog http://t.co/KtdtbFG.

Wednesday
The day started with the third of my sessions "....and thus your forms automagically disappear", about considerations to make when you are about to decide whether or not to leave Forms and go for ADF. You will see the process of conversion step by step starting with the business case and ending at the new ADF application. You will hear about issues you run into when using Forms2ADF for automated conversion and you will get hints on how to use Forms2ADF.

Because of the cancellation of my "ADF Mobile client" session I helped out Steven Davelaar with organizing two JHeadstart Handson sessions. Besides that I had a great discussion with the 3 people that did show up for my cancelled ADF Mobile session about Mobile development with ADF. The handson session were pretty well visited and Steven Davelaar, Wilfred van der Deijl and me were around to help people out when needed.
Oracle JHeadstart: Superior Productivity in Developing Best-practice ADF Web Applications by Steven Davelaar of Oracle Corporation.
The day ended with an excellent party at the Queen Mary.

Thursday
The final day of KScope 11, but what a day that was. Thursday thunder was a huge succes. A bunch of FMW cracks (Peter Ebell, Edwin Biemond, Ronald van Luttikhuizen, Steven Davelaar and Luc Bors (thats me)) set down to do a 4 hour live development session using the Fusion Middleware toolstack. We build an ADF Dashboard to display statistics on KScope data, and an end to end process for submitting abstracts, using a queue to get an event into the business process, sending an email from the process to notify when the abstract is accepted, and finally uploading the presentation. The session was being moderated by Chris Muir, Lonneke Dikmans and Duncan Mills.

We were somewhat afraid of how the audience (if any) would respond to this session. Would there be an audience, and if so, would they stay, or would they leave after a few minutes. It turned out that we a good audience (I think some 75 people) and most of them returned after the one hour KScope Closing Session. In that session a personal succes for me was announced. It turned out that attendees of the Fusion Middleware Track choose me and one of my sessions to be rewarded the "KScope 2011 FMW track Best Speaker Award". I had to learn that via twitter, because I not attending that session. I was preparing the second part of the Thursday Thunder Session. All in all a great session and according to the blogosphere <http://debrasoracle.blogspot.com/2011/07/fmw-symposium-at-kscope.html> this will be repeated in some form at the UKOUG conference in December.

On my way back home I reviewed Grant Ronalds Whitepaper on Forms Modernization. The result can be found here.

KScope 2012
Next year KScope is in San Antonia TX from June 24th - June 28th. I'll be there.
Registration and abstract submission is now open. Find the links on http://kscope12.com/

Sunday, June 26, 2011

Book Review : Oracle ADF Enterprise Application Development – Made Simple

On my way to Los Angeles (Long Beach) for KScope 2011 (12 Hours in an airplane) I had plenty of time to do some reading and writing.The book I read was an only very recently (june 2011) published ADF Book. This is not a technical deep dive into ADF, but it focuses on the process of application development.



The book is written by Sten Vesterli an Oracle ACE Director and it is absolutely a good read.

When reading I found myself in an environment that I recognize from the many ADF projects that I have been involved in. Many of the questions that newbie ADF Developers have are answered in this book. The book describes the development process, starting with an ADF PoC, all the way to testing, packaging and delivering the application to the end users. You also get hints on how to find more info via google. This might actually work better then providing direct URL’s for reference.
Here’s a short overview of the content.

Chapter 1: The ADF Proof of Concept

The proof of concept chapter gives a brief ADF Primer. Next you learn about how to setup a Proof of Concept for ADF and what goes in that Proof of concept. The chapter continues with actually guiding you through the Proof of Cobcept. While reading you learn how to build your first ADF application, in order to convince your boss that ADF has what it takes to build the next generation” .

Chapter 2: Estimating the Effort

How much will it cost and how long will it take. Boy, do I get that question a lot. Luckily I know by now but I had to find out the hard way. Chapter two provides you with some guidelines on how to make an estimate that is as accurate as possible. A valuable remark is the one where Sten tells you to take only 50% efficiency for every one as long as you don’t have any reliable data on efficiency. Gather that data during your first ADF Projects.

Chapter 3: Getting Organized

When starting on ADF, organizing the team an be tricky. In this chapter Sten describes what expertise is nesecary in an ADF project. You will also learn about the tools you need. No not JDeveloper, but tools like versioning tools, issue tracking tools, tools for collaboration and tools for automating builds. Finally there is a part dedicated to naming conventions.
The part on Graphics User Interface Designers refers to the ADF Rich Client online demo, where they can see how ADF RC components work. Sten doesn’t mention the Visio Stencils provided by oracle at the sample code site. You might want to take a look at these visio stencils. I blogged on this on my personal Blog. You can find that post here http://lucbors.blogspot.com/2011/03/adf-11g-ui-designer-meets-adf-developer.html. These also can give you a helping hand when designing the User Interface.

Chapter 4: Productive Teamwork

This chapter talks about team work, and how you can use the JDeveloper Oracle Team Productivity Center Extension. This makes it very easy to work in a team where not all developers are actually working at the same physical location (hint hint ;-) ). The final part covers the use of subversion from within JDeveloper.

Chapter 5: Prepare to Build

First time that I actually hear (or in this case read) someone say out loud that you should base all your taskflows on taskflow templates. Finally it is written down somewhere. It is something that I strongly advise as well. Read more on this in the first pages of chapter 5. Chapter 5 continuous with more on templates and framework extension classes. You really learn what you need to setup before you can start building. And believe me, you don’t want to be found in a situation where you have to create extension classes after you started building your app.

Chapter 6: Building the Enterprise Application

This chapter describes how to use Framework extension classes that you created in the previous chapter, and how to create and use ADF Libraries for both Model and ViewController (read Taskflows). Read the remark on page 161 very carefully, and don’t you ever forget that remark. I ran into the issue several times, and i t can be very hard to resolve this issue. It is very good that this note is in the book. I’ve never seen this in any book before, and I think you can’t even find it on the forum. The ADF_EMG discussed the issue briefly I think. The chapter also describes how to bring together all Taskflow libraries in the MasterApplication, and how to work with menu’s, dynamic regions and how you can switch between taskflows in this dynamic region.

Chapter 7: Testing your Application

The testing part. Why test software anyway ? Read it and weep. You will learn how to create test for all parts and aspects of your ADF Application. From Business Components with JUnit, to the ADF Faces part with Selenium (which in fact is a very nice tool as long as you don’t use browser popup like the ones invoked by the old fashioned ADF Dialog framework). Also read how to test passivation / activation, and how to use JMeter for stress testing.

Chapter 8: Look and Feel

This chapter is largely devoted to the new Visual Skin Editor, which was released just in time to make it into the book (although based on a pre production release but that doesn’t make it less interesting at all. Also worth mentioning is the passage about resource bundle skinning. Not many starting ADF Developers know that you can actually adjust built-in labels by using this technique.

Chapter 9: Customizing the Functionality

Learn how to use MDS for customization.

Chapter 10: Securing your ADF Application

Here Sten describes how to implement security. Especially the part on “implementing data security” is a valuable section. Also the usability hint on page 313 is nice. Use the #{securityContext} to toggle the visible and/or rendered attribute.

Chapter 11: Package and Deliver

The use of ANT and ojdeploy is described very well. The downside of using ojdeploy is printed in the note at page 338. I have had some customers that didn’t want me to do that at all What strikes me however is that Maven is not mentioned at all in this chapter. As a matter of fact, Maven is only mentioned once in the book, on page 99, where you can find the URL (http://maven.apache.org ) I know that at the time of writing Maven support was not yet integrated in JDeveloper, but neither was the Visual Skin Editor that was described in chapter 8. I really think this is a missed chance. You must try and read some docs about Maven.

Appendix: Internationalization

In the final chapter, or appendix, you learn how to internationalize (i18n) your application. I’m still wondering why this is an appendix instead of a ‘normal’ chapter.

Conclusion.

All in all this is an excellent book, or even better ‘a must read’, if you are about to develop your first (or even 2nd or 3rd) ADF enterprise application. It really helps you to understand how to approach ADF enterprise application development.
By reading this book, it doesn’t get simple but sure becomes a lot less complicated. Thanks Sten for writing this for all of us out here. All in all an excellent addition for the ADF Book Shelf.

X-Post (originally posted here http://technology.amis.nl/blog/12523/book-review-oracle-adf-enterprise-application-development-made-simple)

Tuesday, May 31, 2011

ADF 11g Quicky 2 - Set Focus on MouseOver Event

Another Quick solution here. What if I want to set focus on a field without actually having to click it ? This can be done by using a clientListeners and some java script code.

1:  <?xml version='1.0' encoding='UTF-8'?>  
2: <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
3: xmlns:f="http://java.sun.com/jsf/core"
4: xmlns:h="http://java.sun.com/jsf/html"
5: xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
6: <jsp:directive.page contentType="text/html;charset=UTF-8"/>
7: <f:view>
8: <af:document>
9: <af:resource type="javascript">
10: function makeActive(event){
11: event.getSource().focus();
12: }
13: </af:resource>
14: <af:form id="f1">
15: <af:inputText label="Label 1" id="it1">
16: <af:clientListener type="mouseOver" method="makeActive"/>
17: </af:inputText>
18: <af:inputText label="Label 2" id="it2"/>
19: </af:form>
20: </af:document>
21: </f:view>
22: </jsp:root>



When the user hovers the first input text field, the field gets focus and the user can start (or continue) typing.

Easy as that.

Thursday, April 28, 2011

ADF 11g Quickies - A new series of posts

As an ADF consultant I get lots and lots of questions on ADF (duh..). I usually answer these using a simple sample and some explanations. These effort are hardly ever documented by me. I decided to use this Blog to write all these tiny things down for future 'ADF generations'.

From now on this Blog will host ADF 11g Quickies.

Tuesday, April 26, 2011

ADF 11g Quicky : Select text from a resourcebundle

One of the questions I got lately is how to select a specific text from a resource bundle and use it in an ADF Application. This is easy and can be done as shown below.

All you need is a resourcebundle containing the keys and text values, a selectcomponent to set the actual key and some java code in a valueChangeListener to search the resourcebundle for the key. So first create the resourceBundle file to hold the key/value pairs for the text resources.

Next implement the page holding the selectcomponent, and an output component to show the value retrieved from the resourcebundle.
1:  <af:panelGroupLayout id="pgl1">  
2: <af:selectOneChoice valueChangeListener="#{pageFlowScope.resourceBundleManager.listEntryChanged}"
3: id="soc1" autoSubmit="true" valuePassThru="true"
4: label="#{viewcontrollerBundle.SEL_RESOURCE_KEY}">
5: <af:selectItem label="Value 1" value="WAARDE_EEN" id="si1"/>
6: <af:selectItem label="Value 2" value="WAARDE_TWEE" id="si3"/>
7: <af:selectItem label="Value 3" value="WAARDE_DRIE" id="si2"/>
8: <af:selectItem label="Value 4" value="WAARDE_VIER" id="si4"/>
9: </af:selectOneChoice>
10: <af:spacer width="10" height="20" id="s1"/>
11: <af:outputText value="#{pageFlowScope.resourceBundleManager.textValue}"
12: partialTriggers="soc1"
13: id="ot1"/>
14: </af:panelGroupLayout>

Finally implement the valueChangeListener in which we get the choosen value from the resource bundle.
1:  package com.blogspot.lucbors.view.beans;  
2: import java.util.ResourceBundle;
3: import javax.faces.context.FacesContext;
4: import javax.faces.event.ValueChangeEvent;
5: public class ResourceBundleManager {
6: public ResourceBundleManager() {
7: FacesContext messageContext = FacesContext.getCurrentInstance();
8: messageBundle =
9: ResourceBundle.getBundle("nl.amis.technology.view.ViewControllerBundle",
10: messageContext.getViewRoot().getLocale());
11: }
12: public void listEntryChanged(ValueChangeEvent valueChangeEvent) {
13: // Add event code here...
14: String newValue = (String)valueChangeEvent.getNewValue();
15: System.out.println(newValue);
16: setTextValue(messageBundle.getString(newValue));
17: }
18: public void setMessageBundle(ResourceBundle messageBundle) {
19: this.messageBundle = messageBundle;
20: }
21: public ResourceBundle getMessageBundle() {
22: return messageBundle;
23: }
24: public void setTextValue(String textValue) {
25: this.textValue = textValue;
26: }
27: public String getTextValue() {
28: return textValue;
29: }
30: private String textValue;
31: private ResourceBundle messageBundle;
32: }

And now with changing the selection in the listbox, the value of the text shown in the output text (in the green box) component is read from the resourcebundle and refreshed.

And that's all.

Thursday, March 31, 2011

ADF 11g : UI Designer meets ADF Developer

For years, creating a UI design for ADF Faces pages has been a pain in the ***. I have seen UI designs created in excel, powerpoint, and even photoshop. Designs looking great, however, nine out of ten couldn't be realized using the ADF Component stack. Either because 'non-existing' components were used or because pixel perfect alternatives are not available.

Today I found a valuable resource on OTN that can help us circumvent this problem. Oracle published a set of Visio Templates containing all ADF Faces Components. The set has stencils containing visio components that represent ADF components. You can even set some properties that you would typically use when building the ADF Page. This means that we can now have UI Designs that we can work with. The ADF Faces stencils for Microsoft Visio allow you to mock up ADF user interfaces quickly and easy outside of Oracle JDeveloper. The stencils provide representations of the most common used ADF visual components, divided into categories that can be dragged and dropped into new or existing Visio drawings to present the different ADF pages and/or page fragments within an ADF application.

Let me show you how I mocked a dashboard for example.

I start with a new Visio empty starter drawing which is contained within the download provided by Oracle. I can see the stencils containing the ADF Faces Components as shown below.



My goal was to design a dashboard real quickly. I added some components just like I would do when creating a real ADF page. The difference is that I don't need a datacontrol (placeholder or real one), and no need to run the page to get a feel of what it would look like. I even was able to set active tabs using the properties available for the components.



After reshuffling the components the end result of the UI mockup looks like this.



All of this took me less then 15 minutes. An impossible job without these visio add-ons.

Resources
1) Templates download location
2) Youtube video

Monday, February 28, 2011

Referal: Adding a Keystroke filter to and ADF Shuttle Component

No new technical entry this month. I've been busy preparing training material for my ADF Masterclass on march 25th. Besides that I wrote my column ADF@WORK (in dutch) and prepared a training on building Web services with JDeveloper. I did however post a technical entry on the AMIS technology blog about "Adding a Keystroke Filter to an ADF Shuttle Component"



For more detail on this look here

Monday, January 31, 2011

ADF 11g PS3 : Check Uncommitted Data Behavior

In ADF 11g PS 3 (11.1.1.4) there is a nice little feature that you can use to prevent users to leave a page when there is uncommitted data. It is called "Check Uncommitted Data Behavior" and can be used on all action components. Using it is very easy. You just drop the component from the data control pallet onto your page as a child of a command component.


The component is added to the page resulting in the following code.


Finally, you have to tell the ADF Document component that it should implement the uncommitted data warning.


When you run the page, change data, and push the button you will get a message. This will also work when navigating away from the page, refreshing the page and even when closing the browser.

Simple but useful !