Thursday Sep 05, 2013

JDeveloper 11g R2 and 12c: How-to "virtually" press a button on page load

A frequent asked question is about how to press a command button upon load of a page or view. If you are on JDeveloper 11g R2 or JDeveloper 12c, then the solution to this programming challenge is the use of JavaServer Faces (JSF) 2 system events (If you are on JDeveloper 11g R1 then you are on JSF 1.2 and this JSF functionality doesn't exist).

System events are phase listeners that you  associate with a component instead of a view or page as a whole. In the use case mentioned above, the system event would be added to the command button you want to pres on initial page load, e.g.

<af:commandButton text="Press on Page Load" id="cb1"
       actionListener="#{viewScope.OnLoadHandler.onButtonPressed}"
       partialSubmit="true">
   <f:event listener="#{viewScope.OnLoadHandler.pressButton}" type="postAddToView"/>
</af:commandButton> 

 As you can see the f:event tag is added as a child tag to the af:commandButton (You find the event tag in the JDeveloper component palette under JSF -> Core) pointing to a listener defined in a managed bean that listens for the "postAddToView" phase. The managed bean is configured in viewScope to ensure the button in the use case is only "virtually pressed" once and not upon PPR of the button area. Using a managed bean in view scope, a flag can be kept that determines whether or not the button has been invoked already.

The event handler uses JavaScript to "virtually press" the button after the page or view is loaded:

...

boolean initialPageLoad = false;

...

public void pressButton(ComponentSystemEvent componentSystemEvent) {
 //only execute button once and not on PPR is used
 if (initialPageLoad == false) {
  //get access to the command button to execute "click"
  RichCommandButton rc = (RichCommandButton)componentSystemEvent.getComponent();
  String clientId = rc.getClientId();

  //compose the JavaSCript to invvoke from the server. The button client ID allows 
  //us to locate the button even if it is saved in a naming container (e.g. a region) 
  //so the absolute component access will do
  String javaScript = "var button = AdfPage.PAGE.findComponentByAbsoluteId('"+clientId+"');
                      AdfActionEvent.queue(button,true)";
    
  //invoke the JS
  FacesContext facesContext = FacesContext.getCurrentInstance();
  ExtendedRenderKitService service = Service.getRenderKitService(facesContext, 
                                              ExtendedRenderKitService.class);
  service.addScript(facesContext, javaScript);

  //change flag   
  initialPageLoad = true;
 }
}

 This way, whatever is configured for the command button press is executed upon page / view load.

A valid question is: "why don't you execute the Java method associated with a command button directly instead of  using JavaScript?" The answer to this is that using JavaScript, associated behavior tags (e.g. for printable behavior or to show a popup) are executed too as it "mimic" a user behavior.

Of course, if there is no client side behavior associated with a command button, its better to not use JavaScript but call the Java method associated with the button directly.

 Frank




Tuesday Jun 04, 2013

How-to highlight input field content when accessed from auto-tab

A question on the OTN forum has been how to highlight the content of an input field when navigation to it occurs using the auto tab functionality. As a reminder, the "autotab" property of an input field, if set to "true", tabs out of the field that you currently edit when the maximum length of the field entry is reached.

The problem reported on OTN for JDeveloper 11.1.2.4 (and I am sure its the same on other versions of JDeveloper) is that manual tabbing into a next field will highlight the fields content (value) whereas autotab doesn't. To enforce consistent highlighting behavior, you can use JavaScript as shown in the page sample below:

<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
    <af:document title="AutoTab.jsf" id="d1">
    <af:resource type="javascript">
      function onFocusHandler(inputEvent){
         var textfield = 
             AdfAgent.AGENT.getElementById(inputEvent.getSource().getId()+'::content');
         textfield.select();
     }
    </af:resource>
      <af:form id="f1">
        <af:panelFormLayout id="pfl1">
            <f:facet name="footer"/>
             <af:inputText label="First Name" id="it1" 
                           value="#{viewScope.fieldValues.firstName}" 
                           maximumLength="5" autoTab="true"/>
             <af:inputText label="Last Name" id="it2" 
                           value="#{viewScope.fieldValues.lastname}">
                <af:clientListener method="onFocusHandler" type="focus"/>
             </af:inputText>
          </af:panelFormLayout>
       </af:form>
   </af:document>
</f:view>

The af:clientListener is attached to the input field for which you want to show content highlighting on autotab. Attach the same client listener definition to  all field that should have the content highlighting. Instead of adding the JavaScript to the page, you want to create an external JS library file and link it from the page as the JS code above is reusable.

Note that the use of "'::content" in the JavaScript uses knowledge about the way component IDs are rendered at runtime in ADF Faces. If component rendering changes in a future release (you never know) then your code will break at this point and needs to be corrected. So heads-up on this risk (though should be a small one). To the time of writing this lines there is no other API (option) available to get to the HTML field handle in ADF Faces.

Also note the use of AdfAgent.AGENT.getElementById, which is a performant wrapper API in ADF Faces around the document.findElementById function of the Browser DOM. As a rule of thumb you should always work with ADF Faces JS APIs and don't directly reach out to the DOM yourself.

Wednesday May 15, 2013

Table Pagination with JDeveloper 11.1.1.7

One of the new features listed for JDeveloper 11.1.1.7 is pagination for tables, a frequently requested and long awaited feature (http://www.oracle.com/technetwork/developer-tools/jdev/index-088099.html). The tag documentation about this feature states that to switch pagination on you simply set the scrollPolicy property to page.Truth to be told, there is a little bit more for you to do.

1. You need to set the autoHeightRows property to 0

2. You need to make sure the surrounding container provides a floating layout and doe not stretch (e.g. using a panelGroupLayout)

3. To bring the table into shape (full width) you then set styleClass="AFStretchWidth"

All changes at a glance:

scrollPolicy="page"  autoHeightRows="0" styleClass="AFStretchWidth"

Once you did this, the table renders as shown in the image below.

ADF table


Friday Jan 04, 2013

JavaScript function to intercept or listen for tab remove event

The af:panelTabbed component allows you to remove tabs from display using the tabRemoval property

tabRemoval Valid Values: none, all, allExceptLast

determines if tab removal is enabled.

This attribute supports these tabRemoval types:

  • none - tab removal is not enabled.
  • all - tab removal is enabled on all tabs, regardless if they are disclosed. The last tab in the panelTabbed can be removed.
  • allExceptLast - tab removal is enabled on all tabs, regardless if they are disclosed. The last tab in the panelTabbed cannot be removed.

 src: http://docs.oracle.com/cd/E35521_01/apirefs.111230/e17491/tagdoc/af_panelTabbed.html

Because tab removal is not automatic in ADF Faces, developers configure an item listener on the af:showDetailItem component that make the tabs within a panel tab

 

itemListener javax.el.MethodExpression Only EL a method reference to an item listener

src: http://docs.oracle.com/cd/E35521_01/apirefs.111230/e17491/tagdoc/af_showDetailItem.html

"Choosing to remove a tab will cause an ItemEvent of type 'remove' to be launched. This event can be listened for on a showDetailItem using the itemListener attribute. It is up to the developer to handle this event and code the actual removal of the tab. This is because of the dynamic nature of the panelTabbed component, which may have dynamic children. This also allows a finer level of control by the developer, who can then choose a custom implementation that may (for example) include warning dialogs, and control of which tab gains focus after a tab is removed."

src: http://docs.oracle.com/cd/E35521_01/apirefs.111230/e17491/tagdoc/af_panelTabbed.html

This apparently works with logic written in Java saved on the server. A question on OTN was how to handle or intercept this remove event on the client side using JavaScript. This information - unfortunately - is a bit hidden in our documentation and you have to look into the JavaScript documentation for this.

src: http://docs.oracle.com/cd/E35521_01/apirefs.111230/e17489/oracle/adf/view/js/event/AdfItemEvent.html

If there is an AdfItemEvent that fires on the ADF Faces client side, then there also must be a configuration available on the af:clientListener to listen for such an event. And there is (just not obvious)

 <af:panelTabbed id="pt1" tabRemoval="all">  
    <af:showDetailItem text="TAB 1" id="sdi1" stretchChildren="first" clientComponent="false">
         ...
         <af:clientListener method="alertTabClose" type="item"/>
     </af:showDetailItem>
</af:panelTabbed
 

The JavaScript function to this looks similar to

function alertTabClose (closureEvent){
     var tab = closureEvent.getSource();  
     ...

This allows you to handle (and suppress) the tab remove event on the client using JavaScript in ADF Faces

Monday Dec 17, 2012

Accessing ADF Faces components that are read-only from JavaScript

Almost as a note to myself and to justify the time I spent on analyzing aproblem, a quick note on what to watch out for when working trying to access read-only ADF Faces components from JavaScript. 

Those who tried JavaScript in ADF Faces probably know that you need to ensure the ADF Faces component  is represented by a JavaScript object on the client. You do this either implicitly by adding an af:clientListener component (in case you want to listen for a component event) or explicitly by setting the ADF Faces component clientComponent property to true.

For the use case I looked at in JDeveloper 11g R1 (11.1.1.7) I needed to make an output text component clickable to call a JavaScript function in response. Though I added the af:clientListener tag to the component I recognized that it also needed the clientComponent property set to true.

Though I remember this as not being required in 11.1.1.6, I like the new behavior as it helps preventing read-only components from firing client side events unless you tell it to do so by setting the clientComponent property to true.

Note: As the time of writing, JDeveloper 11.1.1.7 is not publicly available and I put the note in this blog as a reminder in case you ever hit a similar challenge so you know what to do.


Wednesday Sep 19, 2012

Oracle ADF Coverage at OOW

Below is the schedule for all ADF related sessions at a glance. Note the Meet and greet session added for Wednesday Octiber 3rd from 4.30 pm to 5:30.

Oracle ADF and Fusion Development

General Session



Time Title Location
10:45 AM - 11:45 AM General Session: The Future of Development for Oracle Fusion—From Desktop to Mobile to Cloud Marriott Marquis - Salon 8
12:15 PM - 1:15 PM General Session: Extend Oracle Fusion Apps to Tablets/Smartphones with Oracle Mobile Technology Moscone West - 3014
1:45 PM - 2:45 PM General Session: Extend Oracle Applications to Mobile Devices with Oracle’s Mobile Technologies Moscone West - 3002/3004
4:45 PM - 5:45 PM General Session: Building Mobile Applications with Oracle Cloud Moscone West - 2002/2004

Conference Session



Time Title Location
12:15 PM - 1:15 PM Understanding Oracle ADF and Its Role in Oracle Fusion Moscone South - 306
1:45 PM - 2:45 PM Building Performant Oracle ADF Business Components to Meet Tomorrow’s Needs Marriott Marquis - Golden Gate C3
3:15 PM - 4:15 PM End-to-End Oracle ADF Development in Eclipse Marriott Marquis - Golden Gate C3
4:45 PM - 5:45 PM Classic Mistakes with Oracle Application Development Framework Marriott Marquis - Salon 7


Time Title Location
10:15 AM - 11:15 AM One Size Doesn’t Fit All: Oracle ADF Architecture Fundamentals Marriott Marquis - Golden Gate C2
10:15 AM - 11:15 AM Oracle Business Process Management/Oracle ADF Integration Best Practices Marriott Marquis - Golden Gate C3
11:45 AM - 12:45 PM Mobile-Enable Oracle Fusion Middleware and Enterprise Applications with Oracle ADF Moscone South - 306
11:45 AM - 12:45 PM Secrets of Successful Projects with Oracle Application Development Framework Marriott Marquis - Golden Gate C2
1:15 PM - 2:15 PM Develop On-Device iPhone and iPad Apps Without Writing Any Objective-C Code Marriott Marquis - Golden Gate C2
1:15 PM - 2:15 PM BPM, SOA, and Oracle ADF Combined: Patterns Learned from Oracle Fusion Applications Moscone West - 3003
1:15 PM - 2:15 PM The Future of Forms Is … Oracle Forms (and Friends) Moscone South - 306
5:00 PM - 6:00 PM Best Practices for Integrating SOAP and REST Service into Oracle ADF Marriott Marquis - Golden Gate C2


Time Title Location
10:15 AM - 11:15 AM Mobile Apps for Oracle E-Business Suite with Oracle ADF Mobile and Oracle SOA Suite Moscone West - 3001
10:15 AM - 11:15 AM Visualize This! Best Practices for Data Visualization in Desktop and Mobile Apps Marriott Marquis - Golden Gate C3
10:15 AM - 11:15 AM Set Up Your Oracle ADF Project and Development Team for Productivity: Seven Essential Tips Marriott Marquis - Golden Gate C2
11:45 AM - 12:45 PM How to Migrate an Oracle Forms Application to Oracle ADF Marriott Marquis - Golden Gate C2
1:15 PM - 2:15 PM Oracle ADF: Lessons Learned in Real-World Implementations Moscone South - 309
3:30 PM - 4:30 PM Oracle ADF Implementations Around the Globe: Best Practices Marriott Marquis - Golden Gate C2
3:30 PM - 4:30 PM Oracle Developer Cloud Services Marriott Marquis - Salon 7
4:30 PM - 5:30 PM Oracle JDeveloper and Oracle ADF: What’s New Hilton San Francisco - Continental Ballroom 5
5:00 PM - 6:00 PM Mobile Solutions for Oracle E-Business Suite Applications: Technical Insight Moscone West - 2020
5:00 PM - 6:00 PM Extending Social into Enterprise Applications and Business Processes Marriott Marquis - Golden Gate C3
5:00 PM - 6:00 PM The Tie That Binds: An Introduction to Oracle ADF Bindings Marriott Marquis - Golden Gate C2


Time Title Location
11:15 AM - 12:15 PM Using Oracle ADF with Oracle E-Business Suite: The Full Integration View Moscone West - 3003
11:15 AM - 12:15 PM Deep Dive into Oracle ADF: Advanced Techniques Marriott Marquis - Golden Gate C2
12:45 PM - 1:45 PM Monitor, Analyze, and Troubleshoot Your Oracle ADF Application Marriott Marquis - Golden Gate C2
2:15 PM - 3:15 PM Oracle WebCenter Portal: Creating and Using Content Presenter Templates Marriott Marquis - Golden Gate C2

HOL (Hands-on Lab)



Time Title Location
10:45 AM - 11:45 AM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A
1:45 PM - 2:45 PM Build Mobile Applications for Oracle E-Business Suite Marriott Marquis - Salon 10A
3:15 PM - 4:15 PM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A
3:15 PM - 4:15 PM Introduction to Oracle ADF: Hands-on Lab Marriott Marquis - Salon 3/4
4:45 PM - 5:45 PM Application Lifecycle Management with Oracle JDeveloper: Hands-on Lab Marriott Marquis - Salon 3/4


Time Title Location
10:15 AM - 11:15 AM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A
5:00 PM - 6:00 PM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A


Time Title Location
10:15 AM - 11:15 AM Introduction to Oracle ADF: Hands-on Lab Marriott Marquis - Salon 3/4
11:45 AM - 12:45 PM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A
1:15 PM - 2:15 PM Build Mobile Applications for Oracle E-Business Suite Marriott Marquis - Salon 10A
3:30 PM - 4:30 PM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A
5:00 PM - 6:00 PM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A


Time Title Location
11:15 AM - 12:15 PM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A
11:15 AM - 12:15 PM Introduction to Oracle ADF: Hands-on Lab Marriott Marquis - Salon 3/4
12:45 PM - 1:45 PM Oracle ADF for Java EE Developers with Oracle Enterprise Pack for Eclipse Marriott Marquis - Salon 3/4

BOF (Birds-of-a-Feather)



Time Title Location
6:15 PM - 7:00 PM How to Get Started with Oracle ADF Marriott Marquis - Club Room
7:15 PM - 8:00 PM Building Next-Generation Applications with Oracle ADF and Oracle BPM Marriott Marquis - Golden Gate C3
7:15 PM - 8:00 PM The Future of Oracle Forms: Upgrade, Modernize, or Migrate? Marriott Marquis - Golden Gate C2
7:15 PM - 8:00 PM Oracle ADF Faces: One Site for Many Devices Marriott Marquis - Golden Gate C1 -

User Group Forum (Sunday Only)



Time Title Location
9:00 AM - 10:00 AM Oracle ADF Immersion: How an Oracle Forms Developer Immersed Himself in the Oracle ADF World Moscone South - 305
10:15 AM - 11:15 AM Deploy with Joy: Using Hudson to Build and Deploy Your Oracle ADF Applications Moscone South - 305
11:30 AM - 12:30 PM ADF EMG User Group: A Peek into the Oracle ADF Architecture of Oracle Fusion Applications Moscone South - 305
12:45 PM - 3:45 PM ADF EMG User Group: Oracle Fusion Middleware Live Application Development Demo Moscone South - 305
3:15 PM - 4:15 PM Mobile Development with Oracle JDeveloper and Oracle ADF Moscone West - 2010

Demos

Demo Location
Developer Moscone North, Upper Lobby - N-002
Oracle ADF Mobile Development Moscone North, Upper Lobby - N-001
Oracle Eclipse Projects Hilton San Francisco, Grand Ballroom - HHJ-008
Oracle Enterprise Pack for Eclipse Moscone South, Right - S-208
Oracle JDeveloper and Oracle ADF Moscone South, Right - S-207
Exhibits
0
Exhibitor Location
Accenture Moscone South - 1813
Moscone South - 2221
Infosys Moscone South - 1701
Moscone South - SMR-005
Innowave Technology Moscone South - 2309
ODTUG Moscone West, Level 2 Lobby - Kiosk in the User Groups Pavilion

Oracle ADF Developers Meet Up

Time Activity Location
4:30 PM - 5:30 PM Stop by the OTN Lounge and meet other Oracle ADF & Fusion developers as well as product managers and engineers who work on Oracle ADF, ADF Mobile and ADF Essentials. Feedback and questions welcome, or simply stop by and say ‘hi!’ and enjoy free beer. OTN Lounge

Tuesday Jul 17, 2012

How-to add new ADF bound table row at the end of a table

A frequent question on OTN, which I often see answered with new rows created on the ADF BC view object level instead the ADF binding layer, is about how to create a new row for a table and append it as the last row in the table. The following code below shows how to do this properly using the binding layer only. Note that while it adds the row as the last row of the table, it doesn't do this as the last row of all possible rows that haven't yet been queried from the database. There is a difference between the last row in a table and the last row in the database.

public String onRowCreate() {
 BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
 //access the name of the iterator the table is bound to. Its "allDepartmentsIterator"
 //in this sample
 DCIteratorBinding dciter = (DCIteratorBinding) bindings.get("allDepartmentsIterator");
 //access the underlying RowSetIterator
 RowSetIterator rsi = dciter.getRowSetIterator();
 //get handle to the last row
 Row lastRow = rsi.last();
 //obtain the index of the last row
 int lastRowIndex = rsi.getRangeIndexOf(lastRow);
 //create a new row
 Row newRow = rsi.createRow();
 //initialize the row
 newRow.setNewRowState(Row.STATUS_INITIALIZED);
 //add row to last index + 1 so it becomes last in the range set
 rsi.insertRowAtRangeIndex(lastRowIndex +1, newRow); 
 //make row the current row so it is displayed correctly
 rsi.setCurrentRow(newRow);                          
 return null;
}  

For the table to show the newly created row after this ensure:

1. The table is configured to always show the current selected row by setting  its displayRow property to selected

2. The table is PPR'ed after the row is created, which can be done declarative using the PartialTriggers property of the table pointing to the ID of the command creating the new row

But what is wrong with the approach of doing the same on the View Object level in ADF BC if it works? Well, it works but it doesn't ensure separation of the layers unless the functionality is exposed as a method on the view object interface. The code in this blog entry is generic and works the same for other business services, like EJB, POJO and Web Services for creating new table rows (which then however you need to persist explicitly in opposite to what you have to do when using ADF BC). So while the other code works, the one in this is the proper solution.

Sunday Jun 24, 2012

How-to dynamically filter model-driven LOV

Often developers need to filter a LOV query with information obtained from an ADF Faces form or other where. The sample below shows how to define a launch popup listener configured on the launchPopupListener property of the af:inputListOfValues component to filter a list of values.

<af:inputListOfValues id="departmentIdId"
   value="#{bindings.DepartmentId.inputValue}"                                      
   model="#{bindings.DepartmentId.listOfValuesModel}"
   launchPopupListener="#{PopupLauncher.onPopupLaunch}" … >      
   …
</af:inputListOfValues>

A list of values is queried using a search binding that gets created in the PageDef file of a view when a lis of value component gets added. The managed bean code below looks this search binding up to then add a view criteria that filters the query.

public void onPopupLaunch(LaunchPopupEvent launchPopupEvent) {
  BindingContext bctx = BindingContext.getCurrent();
  BindingContainer bindings = bctx.getCurrentBindingsEntry();
  JUCtrlListBinding lov = 
       (JUCtrlListBinding)bindings.get("DepartmentId");
  ViewCriteriaManager vcm = 
       lov.getListIterBinding().getViewObject().getViewCriteriaManager();          
  //make sure the view criteria is cleared
  vcm.removeViewCriteria(vcm.DFLT_VIEW_CRITERIA_NAME);
  //create a new view criteria
  ViewCriteria vc = 
         new ViewCriteria(lov.getListIterBinding().getViewObject());
  //use the default view criteria name
  //"__DefaultViewCriteria__"
  vc.setName(vcm.DFLT_VIEW_CRITERIA_NAME);
  //create a view criteria row for all queryable attributes
  ViewCriteriaRow vcr = new ViewCriteriaRow(vc);
  //for this sample I set the query filter to DepartmentId 60. 
  //You may determine it at runtime by reading it from a managed bean
  //or binding layer 
  vcr.setAttribute("DepartmentId", 60);
  //also note that the view criteria row consists of all attributes 
  //that belong to the LOV list view object, which means that you can
  //filter on multiple attributes
  vc.addRow(vcr);           
  lov.getListIterBinding().getViewObject().applyViewCriteria(vc);
} 

Note: Instead of using the vcm.DFLT_VIEW_CRITERIA_NAME name you can also define a custom name for the view criteria.

Thursday Jun 21, 2012

Partial Submit vs. Auto Submit

Partial Submit

ADF Faces adds the concept of partial form submit to JavaServer Faces 1.2 and beyond. A partial submit actually is a form submit that does not require a page refresh and only updates components in the view that are referenced from the command component PartialTriggers property. Another option for refreshing a component in response to a partial submit is call AdfContext.getCurrentInstance.addPartialTarget(component_instance_handle_goes_here)in a managed bean. If a form contains required fields that the user left empty invoking the partial submit, then errors are shown for each of the field as the full form gets submitted.

Autosubmit

An input component that has its autosubmit property set to true also performs a partial submit of the form. However, this time it doesn't submit the entire form but only the component that triggers the submit plus components referenced it in their PartialTriggers property.

For example, consider a form that has three input fields inpA, inpB and inpC with autosubmit=true set on inpA and required=true set on inpB and inpC.

use case 1: Running the view, entering data into inpA and then tabbing out of the field will submit the content for inpA but not for inpB and inpC. Further more, none of the required field settings on inpB and inpC causes an error.

use case 2: You change the configuration of inpC and set its PartialTriggers property to point to the ID of component inpA. When rerunning the sample, entering a value into inpA and tabbing out of the field will now submit the inpA and inpC fields and thus show an error for the missing required value on inpC.

Internally, using autosubmit=true on an input component sets the event root to just this field, which good to have in case of dependent field validation or behavior. The event root can extended to include other components by using the Partial Triggers property on these components to point to the input field that has autosubmit=true defined.

PartialSubmit vs. AutoSubmit

Partial submit set on a command component submits the whole form and leaves it to the developer to decide which UI component is refreshed in response. Client side required field validation (as well as the server side equivalent) is not disabled by executed in this scenario. Setting immediate=true on the command item to skip validation doesn't help as it would also skip the model update.

Auto submit is a functionality on the input components and also performs a partial form submit. However, in addition an event root is defined that narrows the scope for the submitted data and thus the components that are validated on the request.

To read more about this topic, see: http://docs.oracle.com/cd/E23943_01/web.1111/b31973/af_lifecycle.htm#CIAHCFJF

Wednesday Jun 20, 2012

Free Advanced ADF eCourse, part II

A second part of the advanced Oracle ADF online training is available for free. Lynn Munsinger and her team worked hard to deliver this second part of the training as close to the release of the first installment as possible. This two part advanced ADF training provides you with a wealth of advanced ADF know-how and insight for you to adopt in a self-paced manner.

Part 1 (though I am sure you have this bookmarked):

http://tinyurl.com/advadf-part1

Part 2 (the new material):
http://tinyurl.com/advadf-part2

Quoting Lynn:

"This second installment provides you with all you need to know about regions, including best practices for implementing contextual events and other region communication patterns.

It also covers the nitty-gritty details of building great looking user interfaces, such as how to work with (not against!) the ADF Faces layout components, how to build page templates and declarative components, and how to skin the application to your organization’s needs. It wraps up with an in-depth look at layout components, and a second helping of additional region considerations if you just can’t get enough.

Like the first installment, the content for this course comes from Product Management. This 2nd eCourse compilation is a bit of a “Swan Song” for Patrice Daux, a long-time JDeveloper and ADF curriculum developer, who is retiring the end of this month. Thanks for your efforts, Patrice, and bon voyage!"

Indeed: Great job Patrice! (and all others involved)

Thursday Mar 01, 2012

Solving JDeveloper 11gR2 issue with ADF Faces login page in IE8

Using Microsoft IE8, forms based authentication in which the login form is built with ADF Faces doesn't load and instead the browser console report complains about invalid or undefined ADF Faces JavaScript objects. The problem that has been reported for JDeveloper 11g R2 using ADF Faces with Facelets seems to occur only for applications using the ADF Security "ADF Authentication" configuration option in combination with an ADF Faces based login form.

Using the ADF Security "ADF Authentication" option configures the web.xml descriptor to protect the application Java EE context root from unauthenticated access.

 
<security-constraint>
 <web-resource-collection>    
   <web-resource-name>allPages</web-resource-name>    
   <url-pattern>/*</url-pattern>
 </web-resource-collection>
 <auth-constraint>     
   <role-name>valid-users</role-name>
 </auth-constraint>
</security-constraint>

The valid user role name is mapped in the weblogic.xml file and references the WLS users group that all authenticated users are an implicit member of.

<security-role-assignment>   
  <role-name>valid-users</role-name>    
  <principal-name>users</principal-name>
</security-role-assignment>

Protecting the application Java EE root path from unauthenticated access however also means that web resources like pictures or styles sheets, or deferred loaded JavaScript libraries, are blocked until the user has authenticated. For the same reason customers often report missing images on their web login pages.

In the case of an ADF Faces login form, deferred resource loading becomes an issue because subsequent JavaScript requests are all blocked by the security constraint defined in the web.xml file. Surprisingly, this is only a problem in Microsoft IE8 and not with other browsers, which may indicate differences in the handling of login forms and their resource loading. To this time I am not able to say whether IE is doing it right or wrong. Fact however is that the problem only shows on this browser type and that it needs to be handled without opening a security hole, which you would do if you changed the security url-pattern to /faces/* in which case only JSF page requests would require authentication.

Investigating the problem, the following solution has been found by the ADF Faces team: ADF Faces UIs require additional resources that are loaded through the Trinidad resource loader servlet configured in web.xml file.

To allow resources to be loaded when using login forms built with ADF Faces ( in which case the JSF page contains a HTML login form) you need to add another security constraint definition to the web.xml file:

<security-constraint>
  <web-resource-collection>
    <web-resource-name>Allowed ADF Resources</web-resource-name>
    <url-pattern>/adf/*</url-pattern>
    <url-pattern>/afr/*</url-pattern>
    <url-pattern>/bi/*</url-pattern>
  </web-resource-collection>
</security-constraint> 

The above security constraint should do for most of the login pages you would build with ADF Faces. However, if the login screen is more complex and e.g contains DVT graphs or maps, you may have to add more url-patterns for public (anonymous access), like

<url-pattern>/servlet/GraphServlet/*</url-pattern>
<url-pattern>/servlet/GaugeServlet/*</url-pattern>
<url-pattern>/mapproxy/*</url-pattern>
<url-pattern>/adflib/</url-pattern>

In my JDeveloper 11g R2 test-case project, I ended up with three security-constraint definitions added to the web.xml file: "Allowed ADF Resources", "allPages" and "AdfAuthentication".

Always place the "Allowed ADF Resources" security constraint definition first in the web.xml file so it is looked at before all the others are so it takes precedence.

Note that both, the web.xml file and the weblogic.xml file open a visual configuration editor when you double click onto the respective file shown in the JDeveloper Application Navigator (Web Content à WEB-INF folder in the ViewController project.

Wednesday Feb 29, 2012

The infamous Missing IN or OUT parameter error

Often error messages like "attempt to set a parameter name that does not occur in the SQL" and "Missing IN or OUT parameter at index" are caused by developers mixing required and optional bind variables in their SQL queries WHERE clause. If you used bind variables in ADF Business Components SQL queries, make sure the bind variables are set to required. Bind variables that are marked as optional are only good to be used in View Criterias.

In a future version of Oracle JDeveloper, the two bind variable types (the optional ones used in View Criteria and the required ones used in the context of SQL queries) are visually separated in the layout of the View Object editor.

How-to learn ADF Skinning

Recently I observed an increase of questions on OTN and Oracle internal that aim for applying CSS on the generated HTML output of an ADF Faces application. Surely, skinning in ADF is not the same as using CSS in tools like Dreamweaver, but it is the proper way of applying custom images and colors to ADF Faces applications. The biggest risk in styling the generated ADF Faces HTML output with CSS is change in the renderer classes. Oracle constantly works on improving its ADF Faces components, for example using HTML 5 to replace Flash and DHTML on some of the ADF Faces components. If you skinned applications on the generated output, then with each of the changes Oracle applies, your custom styles will break.

ADF sinning applies style sheet definitions to style classes at runtime. In contrast to direct output styling, the style classes are dynamically created and derived from the ADF Faces skin selectors. The component developer ensures that the style classes are always set to the correct location in the generated component output, ensuring that changes last across Oracle JDeveloper versions and component changes. Though I can't save you from learning, I can help you with pointers to sources you want to be aware of:

ADF skinning is documented in the Oracle® Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework

http://docs.oracle.com/cd/E21764_01/web.1111/b31973/af_skin.htm#BAJFEFCJ

An ADF insider recording exists that explains skinning in a 40 minute video. Though this recording doesn't show the new skin editor, you learn a about how skinning works, how you dynamically detect skins at runtime and how you debug skins using FireBug in FireFox.

http://download.oracle.com/otn_hosted_doc/jdeveloper/11gdemos/adf-insider-skinning/adf-insider-skinning.html

As mentioned, a visual skin editor exists that you can use in its stand-alone edition for JDeveloper 11g R1 (11.1.1.4, 11.1.1.5) applications and integrated in JDeveloper 11g R2. An article that explains working with the skin editor and a recommend workflow is published here

http://www.oracle.com/technetwork/issue-archive/2011/11-nov/o61adf-512006.html

To download the stand alone skin editor (JDeveloper 11g R2 has it integrated and no extra download is required), use the link below

http://www.oracle.com/technetwork/developer-tools/adf/downloads/index.html

To learn about the stand alone and the integrate skin editor, refer to the Oracle® Fusion Middleware Skin Editor User's Guide for Oracle Application Development Framework, which you can access online from

http://docs.oracle.com/cd/E16162_01/user.1112/e17456/toc.htm

To try the skin editor on a JDeveloper 11g R2 sample, you can run through the hands-on exercise exposed as part of the Oracle learning library.

http://docs.oracle.com/cd/E18941_01/tutorials/jdtut_11r2_83/jdtut_11r2_83.html

A video recording of how to use the skin editor can be found here

https://blogs.oracle.com/shay/entry/adf_faces_skin_editor_how

 And finally, a list of all skin selectors and ADF Faces components can be read up in the Oracle Fusion Middleware Tag Reference for Oracle ADF Faces Skin Selectors

http://docs.oracle.com/cd/E21764_01/apirefs.1111/e15862/toc.htm

This document is a well written by the ADF Faces component developers and provides information that you don't find in other documentation. If you worked through all of this, Skinning should no longer be a problem for you.

Wednesday Jan 11, 2012

Display selected table row number and total rows

A question on OTN was how to display the current row number and the number of totally available rows in a formatted output string. In the example used below, the format is
row no. [<row index>] of max rows [<total numbers of rows>]

For this example, I used an af:outputText component to display the information on the page. The value of the af:outputText component is calculated from expression language (EL) accessing the ADF binding layer as shown below. Note that for better readability the EL includes line breaks, which in your application you should not add.

 row no. [

#{(bindings.allDepartmentsIterator.rangeStart < 0 ?
1 : bindings.allDepartmentsIterator.rangeStart+1) +

( bindings.allDepartmentsIterator.currentRowIndexInRange == -1 ?

0 : bindings.allDepartmentsIterator.currentRowIndexInRange)}
]

of max rows[

#{bindings.allDepartmentsIterator.estimatedRowCount}]

Note how the expression uses the iterator binding in the ADF binding layer to determine the maximum number of table rows. It then uses the same iterator to determine the current row. Because iterators are zero based, the EL uses additional logic to compensate this.

The af:outputText component needs to have its PartialTriggers property pointing the the af:table component ID to ensure the displayed information is refreshed when the table row currency changes.

 <af:outputText value="row no. [#{(bindings.allDepartmentsIterator.rangeStart &lt; 0 ? 1  :  bindings.allDepartmentsIterator.rangeStart+1) +( bindings.allDepartmentsIterator.currentRowIndexInRange ==  -1 ? 0 : bindings.allDepartmentsIterator.currentRowIndexInRange)}] of max rows [#{bindings.allDepartmentsIterator.estimatedRowCount}]"
                id="ot1" partialTriggers="pc1:t1"/>


Tuesday Dec 27, 2011

Using JSTL in ADF Faces

The JavaServer Pages Standard Tag Library (JSTL) provides expressions for common web application functionalities. Though JavaServer Faces Expression Language (EL) is different from JSTL expressions, the two can be used in combination for functional for which it makes sense. For example, the table below lists JSTL expressions that operate on String values.

Function

Description

fn:contains()

Tests if an input string contains the specified substring.

fn:containsIgnoreCase()

Tests if an input string contains the specified substring in a case insensitive way.

fn:endsWith()

Tests if an input string ends with the specified suffix.

fn:escapeXml()

Escapes characters that could be interpreted as XML markup.

fn:indexOf()

Returns the index withing a string of the first occurrence of a specified substring.

fn:length()

Returns the number of items in a collection, or the number of characters in a string.

fn:replace()

Returns a string resulting from replacing in an input string all occurrences with a given string.

fn:startsWith()

Tests if an input string starts with the specified prefix.

fn:substring()

Returns a subset of a string.

fn:substringAfter()

Returns a subset of a string following a specific substring.

fn:substringBefore()

Returns a subset of a string before a specific substring.

fn:toLowerCase()

Converts all of the characters of a string to lower case.

fn:toUpperCase()

Converts all of the characters of a string to upper case.

fn:trim()

Removes white spaces from both ends of a string.

Src: http://www.tutorialspoint.com/jsp/jsp_standard_tag_library.htm

To use JSTL in Oracle ADF Faces component EL references, you need to add the JSTL namespace of the tags you want to reference. For the JSTL functions shown in the table above, you need to manually add the name space highlighted in red to the JSPX document or page fragment.

<jsp:root  
 xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"         
 xmlns:f="http://java.sun.com/jsf/core"         
 xmlns:h="http://java.sun.com/jsf/html"         
 xmlns:af="http://xmlns.oracle.com/adf/faces/rich"        
 xmlns:fn="http://java.sun.com/jsp/jstl/functions">

The value expression below, referenced in an af:outputText component, displays the substring (first, second and third character) for a value read from the ADF binding layer.

<af:outputText value="#{fn:substring(bindings.employeeName.inputValue,1,3)}" id="ot7"/>

About

The Oracle JDeveloper forum ranks in the Top 5 of the most active forums on the Oracle Technology Network (OTN).



The OTN Harvest blog is a summary of selected topics posted on the OTN Oracle JDeveloper forum.



It is an effort to turn knowledge exchange into an interesting read for developers who enjoy little nuggets of wisdom





Frank Nimphius

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today