September 25, 2009

Task Flow Editor Enhancements

If you've been poking around the Task Flow Editor in the new release of JDeveloper 11g (11.1.1.2), you might have noticed some of the following cool new enhancements:

Bounded Task Flow Identifier
There's now an easy way to identify if the task flow diagram currently in use is a bounded task flow or part of the unbounded task flow. Just look in the upper left corner of the diagram for the new identifier.  It remains hovering in the same location as the diagram is scrolled within the editor.

taskfloweditor1 identifier.GIF

Navigate to Method from Method Call Activity
When method call activities are assigned a managed bean method, double-clicking on the method call activity will navigate directly to the method within its corresponding Java class.

taskfloweditor1 methodcall1.GIF

This same navigation can also be performed by selecting the method call activity and then its "Go to Method" context menu.

taskfloweditor1 methodcall2.GIF

Task Flow Definition - Transaction & Data Control Scope
Task flow definitions contain the two properties <transaction> and <data-control-scope>. Previously in the task flow definition Property Inspector, these two properties appeared to be completely independent from each other. However, that really is not the case. There actually are subtle relationships between the two different properties resulting in specific runtime behaviors. This often caused confusion with developers trying to understand any resulting application problems.

Therefore, in the new release of JDeveloper 11g (11.1.1.2), the user interface for these two properties has been redesigned to express these relationships in a more explicit manner.  Transaction is now a group of related properties. The first is a dropdown specifying the transactional options.

taskfloweditor2 transaction1.GIF taskfloweditor2 transaction2.GIF

Once this value is set the display of the "Share data controls with calling task flow" and "No save point on task flow entry" checkboxes will adjust accordingly.

View and Task Flow Call Activity Thumbnails

When working with task flow diagrams in JDeveloper, it's often easy to forget the general look and feel of the task flows assigned to task flow call activities and pages assigned to view activities. In these situations it can be helpful to quickly refresh ones memory on how a given task flow or page appears. In the previous release of JDeveloper, this was only possible by drilling down into these task flow activities to open their corresponding task flows or pages within their own editor. This could take time and also clutter the workspace. When all that's desired is simply a quick memory refresh or assistance in walking someone through an application flow within JDeveloper this approach could be cumbersome.

A feature is now provided in new release JDeveloper 11g (11.1.1.2) to quickly assist the developer in this situation. The developer selects a task flow call or view activity within a task flow diagram. Then the developer selects the "Show Thumbnail..." context menu. A peek dialog will be displayed containing a thumbnail of the corresponding task flow or page. Using the "Show Thumbnail..." context menu does not dirty the containing task flow diagram. It also will not allow modifications to the task flows and pages displayed within the peek dialog.

Task flow call activity thumbnails provide the additional ability to pan and zoom the appropriate portion of the diagram into view.

taskfloweditor3 thumbnail1.GIF

View activity thumbnails do not provide the capability to pan and zoom.taskfloweditor3 thumbnail1.GIF

View activities; however, do provide an additional context menu item "Expand Thumbnail" to display an image of the corresponding page within the task flow diagram context. Expanding view activity thumbnails can also be performed by selecting the expand icon in the upper left corner of a view activity. Changing the expanded state of a view activity thumbnail dirties the task flow diagram. Therefore, the expanded state of view activity thumbnails can be saved and restored when the same containing task flow diagram is once again opened for editing.taskfloweditor3 thumbnail3.GIF

Task Flow Call Activity Run As Dialog Using a Popup

In the previous JDeveloper 11g release, it was possible to declaratively define a task flow call activity to be "Run As a Dialog". When using this approach, the dialogs presented at runtime could only be displayed as external windows. Implementation involved declaratively setting the task flow activity <run-as-dialog> property to "true" and also setting the launching UI component useWindow attribute to "true". At runtime when the UI component was selected, the task flow specified by the task flow call activity was presented within a dialog using an external window.

In the new release of JDeveloper 11g (11.1.1.2), a new option has been added. It allows the developer to declaratively define a task flow call activity to be "Run As a Dialog" using a popup or an external window. This can be very helpful due to the prevalence of application popups. The developer must still set the task flow activity <run-as-dialog> property to "true" and also the launching UI component useWindow attribute to "true". Then, a new task flow activity property for dialog Display Type is set to either "external-window" (default) or "inline-popup". Therefore, to run the dialog as a popup, the developer sets the task flow call activity Display Type to "inline-popup".

runasdialog1.GIF

At runtime when the UI component is selected, the task flow specified by the task flow call activity is presented as a dialog using a popup (not an external browser window).

runasdialog2.GIF


Dynamically Assign TaskFlowId to Task Flow Call Activity

Previously, the Task Flow Reference (TaskFlowId) of a task flow call activity was required to be statically assigned at design time. However, this often brought challenges when the task flow to call was not known until runtime. In these situations, the developer was often forced use a dynamic region rather than a task flow call activity even though a region might not be required by the application design.

dynamicassigntaskflowid1.GIF

But, in the new release of JDeveloper 11g (11.1.1.2) the developer can dynamically assign a Task Flow Reference to a task flow call activity at runtime. This requires simply changing the new Task Flow Reference dropdown value from "Static" to "Dynamic". Then a valid EL Expression can be entered into the Dynamic Task Flow Reference property. When evaluated, the EL Expression should result in a valid Task Flow Reference (TaskFlowId) (e.g. - "/WEB-INF/employees-task-flow.xml#employees-task-flow"). Input parameters and return values can be assigned using a map or name/value pairs in the same manner as invoking a task flow as a region via a taskFlow binding.

dynamicassigntaskflowid2.GIF

New Features in the ADF Debugger

In the new release of JDeveloper 11g (11.1.1.2), the ADF Debugger has some very helpful new features.  Check these out, if you haven't already taken them for a spin...

Page Definition Breakpoints
Page definition breakpoints were available in the prior release of JDeveloper, however, they only provided the ability to pause debugging BEFORE bindings and executables were performed. Now, it's also possible to pause debugging AFTER page definition bindings and executables are performed.  A new column has been added on the right of page definition binding and executable lists for these new AFTER breakpoints. Toggle an AFTER breakpoint "on" by clicking within the new column or select the binding or executable in the list and utilize the context menu.  Stepping is possible from the BEFORE to the AFTER page definition executable location, but no longer continues once the AFTER page definition executable location is reached.

newdebugger1 after breakpoint.GIF

Keep in mind refreshing is NOT the same as executing iteratorBindings. Each data control determines how and when to execute a collection. When using ADFbc, a Java breakpoint is required on the ViewObjectImpl executeQueryForcollection or QueryCollection's executeQuery methods to break on the execute of a particular collection. This Java breakpoint can be made conditional to break only if the VO name or ViewDef name matches how the iteratorBinding is bound.

ADF Lifecycle Phase Breakpoints
It's now possible to pause debugging BEFORE and/or AFTER any ADF lifecycle phase. There are a couple places these new ADF lifecycle phase breakpoints can be created:

  • ADF Lifecycle Phase Dialog - Available from the ADF Structure window or task flow diagram editor using the "ADF Lifecycle Breakpoints..." toolbar item.  ADF lifecycle phase breakpoints are toggled "on" by selecting within the columns on either side of the ADF lifecycle phases listed within the dialog. When paused during debugging runtime, the current ADF lifecycle phase will be displayed within the dialog in bold.
     newdebugger2 adf lifecycle breakpoints.GIF
  • Debugger Breakpoint Window - A new toolbar has been added to the Debugger Breakpoint window. It provides the ability to create, edit, delete, enable, and disable different types of breakpoints, including ADF lifecycle breakpoints. Currently, page definition breakpoints cannot be added within the debugger Breakpoint window.
newdebugger3 breakpoint window.GIF

Once debugging is paused on an ADF lifecycle phase breakpoint, stepping can be performed to advance from the current location the next BEFORE or AFTER ADF lifecycle phase location.

Display of Current ADF Lifecycle Phase
Previously, it was difficult to identify where debugging was paused within the ADF lifecycle. Now, when debugging is paused at any breakpoint the ADF Debugger displays the current ADF Lifecycle Phase at the top of the ADF Structure window.  This can be very helpful information when further inspecting values and/or determining application processing.

newdebugger4 display life cycle phase.GIF

New ADF Business Component Content
This new release also adds the capability to review the BC4J objects currently instantiated when debugging is paused. To view this information, the ADF Structure window provides an  "Application Data" node within each viewport. Selecting the desired viewport's "Application Data" node will present its corresponding instantiated BC4J objects for display within the ADF Data window. This includes the following BC4J objects:

  • Application Module: identifies the current transaction status
  • Entity Object: displays all rows and the current status of the entity's state.
  • View Object: shows its corresponding SQL Query and the rows it retrieved. The current row is identified with a current row icon.

newdebugger5 adfbc content1.GIF

newdebugger6 adfbc content1.GIF

Enhanced ADF Model Content
Previously, when selecting a binding container node in the ADF Structure window it was difficult to locate the desired ADF Model information displayed within the ADF Data window. Now, the ADF Model content displayed mirrors the same structure as its design time page definition: Data Controls, Parameters, Executables, and Bindings. Each area can be expanded to inspect its current runtime values.

newdebugger7 adfm conten 1.GIF

Data controls based on business services not implemented by BC4J objects will display within the binding container content using raw member variables similar to the standard debugger Data window. For example, the "EmployeeService" bean data control shown below was implemented using a POJO.

newdebugger8 adfm conten pojo.GIF

Hide Page Template Content
When inspecting view contents within the ADF Data window, it's now possible to easily filter out page template content from the content of its associated page. A checkbox labeled "Include Page Template Content" will be displayed on the ADF Data window toolbar if the view displayed is assigned a page template.  The checkbox default is to include page template content. Just uncheck the box to easily filter out any page template content. Then only the content coming from the page will presented within facets.

newdebugger9 page template.GIF



January 23, 2009

What Approach Should I Use for ADF Regions to Share Data or Initiate Navigation?

ADF Regions provide a great deal of application flexibility. Yet, when implementing ADF Regions that same flexibility often leaves the pensive developer wondering how best to share data or initiate navigation. Many different technologies come together to provide these types of application interactions for ADF Regions. Which one best fits what your trying to accomplish? Input parameters? Shared Data Controls? Contextual Framework Events? To help decipher through the appropriate approach to choose, I've created an ADF Region Interaction pattern document available on OTN. It describes each of the different ADF Region interaction development approaches and their recommended uses. Examples are also provided to help demonstrate each of the concepts.

So think globally and interact "regionally"! ;)

November 20, 2008

How Are “Empty” Regions Implemented?

There might be times when ADF Region content should not be displayed on a runtime page. Instead, the page should appear blank where the region was previously located. This is really easy to implement, but it’s not really the region that’s “empty”. It’s actually the task flow definition associated with the region that’s “empty”. But, no need to go to the trouble of creating metadata for a task flow definition containing a view activity associated with a blank page. All you need to do is just set the region or dynamic region taskFlow binding taskFlowId=””. The open-quote closed-quote convention MUST be used as defined by ADF Controller. Setting the taskFlowId to “null” or using parse commands will not work.

This same “empty” task flow approach is often used when region content is hidden and shown as part of an ADF Faces popup or panelTab. It’s important to swap an “empty” task flow into a dynamic region when it’s hidden from view. This ensures memory and recourses for the associated task flow definition are allocated and released appropriately.

For example, the following Java class can be used to swap an “empty” task flow into a dynamic region contained within an ADF Faces popup. Note two VERY IMPORTANT things about the code sample: 1) getDynamicTaskFlowId() returns a String, not a TaskFlowId (currently there is not a formalized TaskFlowId="") 2) the parse() command will NOT work for "".

public class popupDynamicRegion {

private String taskFlowId = "";
private String popupTaskFlowId = "/WEB-INF/employee-update.xml#employee-update";
private String emptyTaskFlowId = "";

public PopupDynamicRegion() {
}

public String getDynamicTaskFlowId() {
if (taskFlowId != null)
return taskFlowId;
else
return getEmptyTaskFlowId();
}

public String getEmptyTaskFlowId() {
return emptyTaskFlowId;
}

public void swapEmptyTaskFlow(ClientEvent event) {
setDynamicTaskFlowId("");

// if event delivery set to immediate="true", short-circuit to renderResponse.
// Forcing an empty taskflow releases the bindings and view port.
Boolean immediate = (Boolean)event.getParameters().get("immediate");
if (immediate != null && immediate) {
FacesContext context = FacesContext.getCurrentInstance();
context.renderResponse();
}

String popupId = (String)event.getParameters().get("popupId");
System.out.println("**** Swapping Empty Taskflow on popupClosed for " +
popupId + " ****");
}

public void setDynamicTaskFlowId(String newTaskFlowId) {
taskFlowId = newTaskFlowId;

// For HA Applications
//if (taskFlowId != null)
//{
// ControllerContext.getInstance().markScopeDirty(pageFlowScope);
//}
}
}

When Are Regions & Dynamic Regions Refreshed?

Regions and dynamic regions are initially refreshed in the ADF Lifecycle prepareModel phase when the binding container of the containing page is refreshed. On subsequent requests, the region or dynamic region will be refreshed during the ADF Lifecycle prepareRender phase depending on its taskFlow binding Refresh and RefreshCondition attributes and parameter values. Task flow definitions associated with dynamic regions are only switched during the ADF Lifecycle prepareRender phase.

For further information on ADF region taskFlow binding Refresh and RefreshCondition attributes, refer to the Fusion Developer’s Guide for ORACLE ADF section 17.1.7 “What You May Need to Know About Refreshing an ADF Region”.

November 17, 2008

How Do I Initiate Region Navigation From the Parent Page?

There are often cases when a page requires some type of interaction with one or more of its regions. If the interaction depends on application data being shared between the two, typically either input parameters or a <data-control-scope> of "shared" is utilized by the region. If only a small payload of application data is to be shared without restarting the region, contextual framework events can be used. But, when a page must initiate control flow navigation within one of its regions the best approach is to utilize the queueActionEventInRegion(...) method located within the oracle.adf.view.rich.component.rich.fragment.RichRegion class.

To help describe the required development approach, I've created a Initiate Control Flow Within Region From Its Parent Page pattern document available on OTN. It contains a link to download a sample application. The pattern document and sample application also describe how to use region capabilities to enable/disable buttons on the parent page based on the current state of the region. Just follow the recommended development approach. It's easy to navigate your way through it. :)

How Do I Include a Region Within an <af:popup>?

Regions can be incorporated into ADF Faces popup content to support tasks requiring complex navigation through a series of pages. Another important benefit of including regions within ADF Faces popups is content reuse. These great benefits make ADF Faces popups containing regions a commonly used application development pattern.

Incorporating regions into <af:popup> content can seem similar to incorporating regions into a page, especially since an <af:popup> is actually considered part of a page. However, there are some important differences to keep in mind. Many of these differences are the result of <af:popup> behavior being mainly client-side only. When a user discloses an <af:popup>, JavaScript on the client unhides the <af:popup> created previously when the page was initially displayed. When the <af:popup> is dismissed, JavaScipt on the client simply hides the <af:popup> again. By default in both cases, no event or request is sent to the server to refresh the region content or retrieve data based on the current application state. If the <af:popup> is displayed a second time, it simply redisplays the <af:popup> content remaining from the previous disclosure.

The default behavior limitations of <af:popup> content can be overcome quite easily though. To help describe the required development approach, I've created an Embeding Regions Inside PopUp Windows pattern document available on OTN. The pattern document also provides a link to download a sample application. Just follow the simple approach to ensure region content within an <af:popup> is newly refreshed for each launch of the <af:popup>. Soon you'll be seeing regions popping up all over!

blogpopupregion.gif

November 14, 2008

Expression Language: “#” or “$”?

When looking at the source code of JSF application pages have you ever noticed some EL Expressions might begin with an “#” (e.g.: #{foo.bar}) while others begin with an “$” (e.g.: ${foo.bar}). If you ever wondered why, check out the following Sun Developer Network article on Unified Expression Language which does a good job of describing the difference between immediate “$” vs. deferred “#” expression language evaluation. Typically, ADF applications will utilize the deferred “#” style to evaluate the expression at the appropriate time during the page life cycle. I guess “$” is not always the answer… ;)