Using FLEX in ADF / JSF Applications

JDeveloper 11g is going to introduce JSF components with built-in rich client capabilities. However 11g is not out yet. This does not mean that you cannot incorporate rich client components to your application today. One of the alternatives is to embed FLEX components into ADF/JSF applications. (FLEX is a Rich Internet Application technology developed by Adobe)
In this post we are going to demonstrate how to achieve this.

The sample application is fairly straightforward. It contains two input boxes, and two buttons. One of the input boxes is implemented in JSF and the other in FLEX. The application which is a JDeveloper 10.1.3.1 workspace, demonstrates how these two components can pass information to each other. Communication between the two technologies is a critical requirement if both technologies are used in the same application. There are two buttons on the screen to start the communication between the two input boxes. The “from JSF to FLEX” button assigns the value of the JSF Component to its FLEX counterpart, and the “from FLEX to JSF” button does the opposite.


You can download the sample application from here. As mentioned above, the application is a JDeveloper 10.1.3.1 workspace. It does not need a database connection to run.

The instructions below describe the steps to build the sample application. If you are not familiar with FLEX, links to various FLEX resources can be found at the end of this post.

The development process consists of building two separate applications. First, the FLEX Input Box must be built using FLEX Builder. Then, a JDeveloper workspace will be built with a JSF Input Box in it. The FLEX Input Box will be incorporated to the JDeveloper workspace so that it can communicate with the JSF InputBox.

You can download the FLEX InputBox project from here. You need FLEX Builder 2 to open it.

Developing the FLEX Input Box

  • Create a new FLEX project (File > New > Flex Project).

  • Select 'Basic' from the dialog that appears. Click Next.

  • Enter the name of your project. (FlexBox in our case). Click Next.

  • Click Finish on the next screen.

The wizard creates a FlexBox.mxml file. Flex Builder help defines MXML as; “...an XML language that you use to lay out the user-interface for Adobe Flex applications. You also use MXML to declaratively define non visual aspects of an application, such as access to server-side data sources and data bindings between user-interface components and server-side data sources...”
In other words, this is the point where a FLEX application starts to execute.

  • Add the following tag inside the mx:Application tag.

<mx:TextInput id="myTextBox" width="200" fontsize="13"
fontfamily="Arial"/>
  • Add the script tag inside the mx:Application tag. This is where the ActionScript code is going to reside.

<mx:Script>
<![CDATA[
]]>
</mx:Script>
  • Modify the mx:Application tag and add the creationComplete attribute. The creationComplete attribute specifies the code that will execute when the FLEX Object is created in client's web browser.

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" creationComplete="initApp();">
  • In the initApp() function the external JavaScript functions are coupled with their corresponding ActionScript counterparts. This is done by using the ExternalInterface class. The addCallback method in this class is utilized to provide access to ActionScript methods from within JavaScript. The call method, which is not used in our application, handles access to JavaScript functions from within FLEX.

public function initApp():void {
ExternalInterface.addCallback("fromJsfToFlex",
setMyTextBoxValue);
ExternalInterface.addCallback("fromFlexToJsf",
getMyTextBoxValue);
}
  • Add the setMyTextBoxValue and getMyTextBoxValue function inside the mx:Script tag.

public function setMyTextBoxValue(text:String):void {
myTextBox.text = text;
}
public function getMyTextBoxValue():String {
return myTextBox.text;
}
  • Click on the MXML file on the navigation tree. Execute the MXML in order to generate the SWF file by selecting Run -> Run FlexBox (or whatever you named your project).


The SWF file is under <installation>\FlexBox\bin. This folder contains six files that are of interest to us. Below is their description:

FlexBox.swf: This is the compiled version of our FlexBox application.

AC_OETags.js: The FLEX Help defines the file as; " a file that provides methods for Flash Player version detection and embedding your Flex application. You call methods in this file from your wrapper"

History.js, history.swf, history.htm: These files are used to support the back button on the browser.

FlexBox.html: This HTML file is automatically generated and contains the wrapper so that the SWF file can run in client’s browser. Normally this file contains code to support Flash Player installation and different browsers. We separated some of these functionalities to two new JavaScript files (versionDetect.js and globalVars.js) to simplify the code in the JSP page.

This completes the development of the FLEX Input Box.

Development of the JDeveloper Workspace

  • Create a new ADF/JSF Application.

  • Copy the following files from the FLEX project’s bin folder to the public_html folder of the ViewController project in the JDeveloper workspace

    • versionDetect.js

    • globalVars.js

    • AC_OETags.js

    • history.js

    • history.swf

    • history.htm

    • playerProductInstall.swf

    • FlexBox.swf

  • Add a page to the workspace. Then add the following code to the page

<h:form id="jsfForm">
<h:panelGrid columns="3" cellpadding="0">
<af:outputText value="JSF Component"/>
<af:objectSpacer/>
<af:outputText value="FLEX Component"/>
<af:inputText id="jsfBox"/>
<h:panelGrid columns="1">
<af:commandButton text=">> From JSF to FLEX >>"
blocking="true"
onclick="setFlexComponentValue();"/>
<af:commandButton text="<< From FLEX to JSF <<"
blocking="true"
onclick="getFlexComponentValue();"/>
</h:panelGrid>
<h:panelGroup>
<!-- FlexBox -->
</h:panelGroup>
</h:panelGrid>
</h:form>
  • The command buttons have calls to getFlexComponentValue() and setFlexComponentValue() on their onclick event.
    The blocking attribute is set to true to avoid the submission of the HTML form when the buttons are clicked.
    Include the necessary JavaScript files under the <af:head> tag.

<afh:head title="flexBox">
<meta http-equiv="Content-Type"
content="text/html; charset=windows-1252"/>
<afh:script source="AC_OETags.js"/>
<afh:script source="globalVars.js"/>
</afh:head>
  • Place the HTML that runs the SWF File inside the tag, where it says <!-- Flex Box -->. Use the <f:verbatim>

<afh:script source="history.js"/>
<afh:script source="versionDetect.js"/>
<f:verbatim>
<noscript>
<object id="FlexBox" width="200" height="25"
classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
<param name="movie" value="FlexBox.swf"/>
<param name="quality" value="high"/>
<param name="bgcolor" value="#869ca7"/>
<param name="allowScriptAccess" value="sameDomain"/>
</object>
</noscript>
<iframe name="_history" src="history.htm" frameborder="0"
scrolling="no" width="22" height="0"/>
</f:verbatim>

Preparing the JavaScript code

  • Create a JavaScript file (myJScript.js) which will hold the code for getFlexComponentValue, setFlexComponentValue methods and a helper method called getMyApp(). The JavaScript file also contains an if statement to prevent the Internet Explorer from throwing an exception when the page is loaded.

if (navigator.appName.indexOf ("Microsoft") != -1) {
window.FlexBox = new Object();
}

function getMyApp(frmName, appName) {
if (navigator.appName.indexOf('Microsoft') != -1) {
var formName = window[frmName];
return formName[appName];
}
else {
return document[appName];
}
}

function setFlexComponentValue() {
var myApp = getMyApp('jsfForm', 'FlexBox');
var fieldValue =
document.getElementById('jsfForm:jsfBox').value;
var paramStr = '<invoke returntype="javascript"'
+ ' name="fromJsfToFlex"><arguments>'
+ '<string>' + fieldValue + '</string>'
+ '</arguments></invoke>';
myApp.CallFunction(paramStr);
}

function getFlexComponentValue() {
var myApp = getMyApp('jsfForm', 'FlexBox');
var paramStr = '<invoke returntype="javascript"'
+ ' name="fromFlexToJsf">';
var value = myApp.CallFunction(paramStr);
value = value.substring(1, value.length - 1);
document.getElementById('jsfForm:jsfBox').value = value;
}
  • Add the new JavaScript file inside the <afh:head> tag.

<afh:head title="flexBox">
<meta http-equiv="Content-Type"
content="text/html; charset=windows-1252"/>
<afh:script source="AC_OETags.js"/>
<afh:script source="globalVars.js"/>
<afh:script source="myJScript.js"/>
</afh:head>

This completes the development of the JDeveloper workspace.

We implemented this technique to replace the ADF Faces Shuttle Component with a FLEX Shuttle Component in one of our ADF Faces applications.

Links

Comments

Anonymous said…
Nice and very helpful, thanks! But how to do it without a command button, so that it will pass the parameters as example in onload event? Any ideas?

Or should I user FlashVars somehow?

Frank
Andreas said…
Thanks for the great article. I am planning to integrate flex with adf faces too.

Do you know if it might be simpler with Flex™ Ajax Bridge?

Popular posts from this blog

Monitoring Oracle Database with Zabbix

Powerful Free Webinar Network for Oracle Developers