JDeveloper: Execute Bean Method on Hitting Enter in af:inputText Component

This blog article describes a common use case. A user enters some value into an field on the page and his enter. This should trigger a method on the server (e.g. a bean method).

Use case
Hitting ENTER on a af:intputText component should trigger an action (e.g. executing a bean method).

The sample we implement in this blog shows a page with a splitter component. On the left side we see an input text component which is used to enter a value. On the right side we see the result of the search as a table of countries from the HR schema. The search condition used is to show all countries which names starting with the value entered in the input text component.

Sample Application

Sample Application

As you see there is no button ot other command component to execute the search. The search is triggered by hitting enter in the input text field on the left side of the splitter.

Filtered Output after hitting Enter

Filtered Output after hitting Enter

To implement this we need to use JavaScript af:clientListener to handle the keyboard input. The javascript method then queues a server action using a af:serverlistener.

<af:inputText label="Country" id="it1" value="#{bindings.SelCountryName1.inputValue}" autoSubmit="true">
    <af:clientListener method="handleEnterEvent" type="keyPress"/>
    <af:serverListener type="EnterEvent" method="#{SendEnterBean.handleEnterEvent}"/>

The af:clientListener listens for keyPress event and in the JavaScript method checks weather the key pressed was the enter key or not. If it was the enter key it queues an event for a server side method in a bean. The method name is given in the af:serverListener type=”EnterEvent” method=”#{SendEnterBean.handleEnterEvent}”. The method listen for the event type send from the client AdfCustomEvent.queue(comp, “EnterEvent”, {fvalue:comp.getSubmittedValue()}, false);. This type is defined in the serverListener as type property.

<af:resource type="javascript">
    function handleEnterEvent(evt) {
      var _keyCode = evt.getKeyCode();
      //check for Enter Key
      if (_keyCode == AdfKeyStroke.ENTER_KEY ){    
          var comp = evt.getSource();
          AdfCustomEvent.queue(comp, "EnterEvent", {fvalue:comp.getSubmittedValue()}, false);

The server side method now calles the “executeWithParams” method on the courntries iterator which filters the countries table for countries starting with the value given by the input field.

    public void handleEnterEvent(ClientEvent ce) {
        _logger.info("Got event " + ce.getType());
        // get the binding container
        BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
        // get an Action or MethodAction
        OperationBinding method = bindings.getOperationBinding("ExecuteWithParams");
        if (method == null) {
        _logger.info("Method ExecuteWithParams not found in current bindings");

        // get the parameter from the event
        String message = (String) ce.getParameters().get("fvalue");
        //This can be used too if one doesn't like to send the parameter to the method
        // get an ADF attributevalue from the ADF page definitions
        //AttributeBinding attr = (AttributeBinding)bindings.getControlBinding("SelCountryName1");
        //String v = (String)attr.getInputValue();

        //Set the parameter
        Map params;
        Map map = method.getParamsMap();
        map.put("bindName", message);

        // check for errors
        if (!method.getErrors().isEmpty()){
            Exception ex =(Exception) method.getErrors().get(0);
            _logger.warning("Error: " + ex.getLocalizedMessage());

        // PPR refresh a jsf component

The missing part is how the countries table get filtered. For this in the model layer we created a ViewObject “CountriesView” for the COUNTRIES table of the HR schema. Then we define a ViewCriteria “CountriesByNameVC”:

ViewCriteria CountriesByNameVC

ViewCriteria CountriesByNameVC

In the data model of the application module we use the view object instance CountriesView1 and select the ViewCriteria as query.

Edit View Instance CountriesView1 to use ViewCriretia CountriesByNameVC

Edit View Instance CountriesView1 to use ViewCriretia CountriesByNameVC

Now in the ViewController project we only need to store the value entered by the user in the af:inputText field and add add a method binding for the “executeWithParams” method which we use in the bean method to filter the table.

Final pageDef

Final pageDef

and the source for the pageDef file:

<pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel" version="" id="BSE2BPageDef" Package="de.hahn.blog.sendenter2bean.view.pageDefs">
    <variableIterator id="variables">
      <variable Name="SelCountryName" Type="java.lang.String"/>
    <iterator Binds="CountriesView1" RangeSize="25" DataControl="BSE2BAppModuleDataControl" id="CountriesView1Iterator"/>
    <tree IterBinding="CountriesView1Iterator" id="CountriesView1">
      <nodeDefinition DefName="de.hahn.blog.sendenter2bean.model.dataaccess.CountriesView" Name="CountriesView10">
          <Item Value="CountryId"/>
          <Item Value="CountryName"/>
          <Item Value="RegionId"/>
    <attributeValues IterBinding="variables" id="SelCountryName1">
        <Item Value="SelCountryName"/>
    <action IterBinding="CountriesView1Iterator" id="ExecuteWithParams" RequiresUpdateModel="true" Action="executeWithParams">
      <NamedData NDName="bindName" NDValue="#{bindings.SelCountryName1.inputValue}" NDType="java.lang.String"/>

You can download the sample, which is build using JDeveloper and uses the HR schema, from ADF Sample Source Code Repository

Validate Data before Export via af:exportCollectionActionListener or af:fileDownloadActionListener

ADF rich faces offer a nice and easy feature to stream data to the client (e.g. Excel) using the af:exportCollectionActionListener or af:fileDownloadActionListener component. Both of the components get the output stream from the response, so the application an add the data.
One problem is that the two components fire before the application has a chance to validate other data on the page or do some other needed work.
To overcome this shortcoming you can implement the trick I’m outlining in this blog. The idea is to use a normal af:commandbutton or af:commandToolbarButton on the page which calls an actionListener in a bean. In there you can validate other page data or do some other stuff in the model, and then queue an event inside the bean method to call another invisible button on the page which has the af:exportCollectionActionListener attached.

As it turned out (thanks Jiandong Xin for pointing it out), there is a problem if the button we queue the action event to has a client behavior tag attached. This is the case for af:exportCollectionActionListener or af:fileDownloadActionListener. These tags don’t work properly if we only queue an event to the parent button. As Jobinesh pointed out in his blog we need to insert a JavaScript function into the page which handles the event queuing from JavaScript and call it from the bean. This way we are able to set the needed parameters (e.g. not to wait for a response).

Now lets implement this: Lets start with a toolbar button which resides on a panel collection holding the table we want to export. The button has a binding to the bean (binding=”#{exportBean.exportCollectionButton}”) to make it easier to call it from the bean. If you don’t like to bind the button to the bean, you can search for the component by name inside the action listener we implement below. The page contains the custom handler (customHandler(event)) which we call from the bean method. This handler then queues the event to activate the button which starts the file download. The connection between the customHander and hte commandToolbarButton is the ID of the commandToolbarButton (“ctb1”). You have to change this if your button has a different ID.

<af:resource type="javascript">
  function customHandler(event){
    var exportCmd = AdfPage.PAGE.findComponentByAbsoluteId("ctb1");
    var actionEvent = new AdfActionEvent(exportCmd);
<af:panelCollection id="pc1">
  <f:facet name="menus"/>
    <f:facet name="toolbar">
      <af:toolbar id="t2" binding="#{exportBean.toolbar}">
        <af:commandToolbarButton text="Export..." id="ctb1"
          <af:exportCollectionActionListener type="excelHTML" exportedId="t1"

The vital part is that the visible property is set to “false”, so that the button will not show up on the page, but is fully functional. Somewhere else on the page (or even on the same toolbar) we have an with an action listener pointing to a bean method (exportBean in the sample). This button is visible and used to initiate the export.

<af:commandButton text="export via bean" id="cb8" 

The exportBean actionListener looks like this

    // toolbar button with export listner attatch bound from page
    private RichCommandToolbarButton exportCollectionButton;
    public void exportprgActionListener(ActionEvent actionEvent) {
        // Add event code (validation or other) here...

        // queue the event via a JavaScript inserted into the page
        FacesContext context = FacesContext.getCurrentInstance();
        ExtendedRenderKitService erks =
        Service.getService(context.getRenderKit(), ExtendedRenderKitService.class);
        erks.addScript(context, "customHandler();");

In the action listener above you can validate other data on the page or call service methods in your application module before starting the export, or cancel the export if you like. The export runs as if you click the af:exportCollectionActionListener directly.
You can download a sample workspace BlogFileDownLoadTest.zip
After download remove the ‘.doc’ suffix!