Integrate Adobe Flex and JBOSS using BlazeDS – Part I

In this tutorial I will give you step by step instructions on how to integrate Adobe Flex and JBOSS using BlazeDS.
Although in this tutorial I am addressing BlazeDS, the steps in this tutorial should also apply to Adobe Flex LiveCycle Data Services. The only difference are the jars that you copy to your WEB-INF/lib directory. For those who want to integrate BlazeDS with Struts 2, the instructions in this tutorial should also be helpful.

In the Java Backend:

Step 1

Download blazeds.war from http://opensource.adobe.com/wiki/display/blazeds/Downloads

Step 2

Unzip blazeds.war. Copy the files in WEB-INF/lib and WEB-INF/flex to your web project under the same path in your web app.

Step 3

Edit web.xml and add the following lines:

    <!-- Http Flex Session attribute and binding listener support -->
    <listener>
        <listener-class>flex.messaging.HttpFlexSession</listener-class>
    </listener>

    <!-- MessageBroker Servlet -->
    <servlet>
        <servlet-name>MessageBrokerServlet</servlet-name>
        <display-name>MessageBrokerServlet</display-name>
        <servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>
        <init-param>
            <param-name>services.configuration.file</param-name>
            <param-value>/WEB-INF/flex/services-config.xml</param-value>
       </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>MessageBrokerServlet</servlet-name>
        <url-pattern>/messagebroker/*</url-pattern>
    </servlet-mapping>

Step 4

Create a simple java class with a simple method that we will invoke from Adobe Flex:

package uk.co.spltech.remote;

import java.util.ArrayList;
import java.util.List;

/**
 * This remote service is called using BlazeDS/LiveCycle DS from Flex
 * 
 * @author Armindo Cachada
 *
 */
public class RemoteService { 
 /**
  * I am not doing anything useful except to just show that I can be invoked remotely
  * from Adobe Flex using RemoteObject.
  * 
  */
 public List<String> callMe() {
  System.out.println("I am being invoked!");
  List<String> result = new ArrayList<String>();
  result.add("Michael Jackson");
  result.add("Beatles");
  result.add("Tina Turner");
  return result;
 }
}

Step 5

Create a new destination in remoting-config.xml:

<destination id="remoteService" >
   <properties>
        <source>uk.co.spltech.remote.RemoteService</source>
        <scope>application</scope>
   </properties>
</destination>

The source of the destination can be a fully qualified class name, a jndi reference or a spring bean. We will discuss that in a later post. For this example we just specify a class name.

The scope of the destination can be one of:

  • application – there is only one instance of the class for the entire application(i.e. global in atg, singleton in spring)
  • session – there is one instance per user session
  • request – for each http request a new instance of the class is created

In Adobe Flex:

Step 1

Create a new project in Adobe Flex. Please make sure that the Application Server type is set to none.
Why? Fair question to ask since most instructions say to do exactly the opposite. I found those instructions not really helpful in the case of JBOSS since they assume I can provide the directory containing the application after it is deployed to JBOSS. That works quite well for tomcat because it simply extracts the war file under webapps. The path is always the same. In the case of JBOSS the path to the application changes after each deployment…

Step 2

The only reason Adobe Flex asks you for the path to the root folder of your web application is so that it can provide two arguments to the flex compiler:

  • services – The path to the Adobe flex data services configuration file
  • context-root – The context root of your web application

After you create your web application add the following arguments to the flex compiler:

-services "/usr/java/eclipse/workspace/example6/resources/flex/services-config.xml" -context-root "/example6"

Step 3

Let’s create a very simple flex application that invokes the callMe() method in uk.co.spltech.remote.RemoteService. This method returns an ArrayList with a list of items:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" >
<mx:Script>
 <![CDATA[
  import mx.collections.ArrayCollection;
  import mx.controls.Alert;
  import mx.rpc.events.ResultEvent;
  import flash.utils.getQualifiedClassName;
  
  
  /**
   * Populates the data list using the results returned by callMe()
   */
  private function populateList(event:ResultEvent):void {
   var result:ArrayCollection= ArrayCollection(event.result);
   singerList.dataProvider= result;
  }
 ]]>
</mx:Script>
 <mx:RemoteObject id="myService" destination="remoteService" result="populateList(event)"/>
 <mx:List id="singerList" >
  
 </mx:List>
 <mx:Button click="myService.callMe();" label="Call Remote Function"  />
</mx:Application>

Step 4

Compile the flex app and copy all the generated swf/html/js to your jboss web app.

Step 5

Deploy the war file to JBOSS and test it under http://localhost:8080/example6

If you click in the “Call Remote Function” button you should see a list of results returned by the method callMe().

Download source code for JBOSS+Adobe Flex+BlazeDS project

Note that, in order to make the zip smaller, I didn’t include the BlazeDS jar files. You need to manually copy them to the lib directory before generating the war file.

Click here to read Part II

Adobe Flex with Struts 2 using HttpService

Using HttpService is the easiest way in which you can integrate Adobe Flex and Struts 2. As an example I will show you how you can create a registration form in Adobe Flex which calls a struts 2 action to create new users. Note that this example is very simple and for demonstration purposes. I am not adding any validation in flex and not even creating the users in a database. All I show you is how you can pass data between flex and struts.

First let me show you the steps you need to perform in Adobe Flex:

Step 1

Create the registration form in mxml:

<mx:Form label="Registration Form">
 <mx:FormHeading label="Registration Form">
 </mx:FormHeading>
 <mx:FormItem label="First Name">
  <mx:TextInput id="firstName">
  </mx:TextInput>
 </mx:FormItem>
 <mx:FormItem label="Last Name">
  <mx:TextInput id="lastName">
  </mx:TextInput>
 </mx:FormItem>
 <mx:FormItem label="Email">
   <mx:TextInput id="email">
  </mx:TextInput>
 </mx:FormItem>
 <mx:FormItem label="Username">
  <mx:TextInput id="username">
  </mx:TextInput>
 </mx:FormItem>
 <mx:FormItem label="Password">
  <mx:TextInput id="password" displayAsPassword="true">
  </mx:TextInput>
 </mx:FormItem>
 <mx:FormItem>
  <mx:Button label="Register" click="registerUser()"/>
 </mx:FormItem>
</mx:Form>

Step 2

Create the HttpService object:

<mx:HTTPService id="registerService" showBusyCursor="true" useProxy="false" url="register.action" resultFormat="e4x" method="POST" result="registerConfirmation(event)" fault="registerFailed(event)"/>
  • register.action is the Struts 2 action that registers the user
  • registerConfirmation(event) is the function that is called if the http service call is successful.
  • registerFailed(event) is the function that is called if an error occurs. For example if the server is down. The event object gives you access to any xml/html that might be returned upon the call of the action.
  • resultFormat specifies in which format you want to view the results. It can be text, xml or an object. There are 5 possible values for this field:
    • object – An XML object is returned and is parsed as a tree of ActionScript objects
    • xml – Returns literal XML in an XMLNode object
    • e4x – Returns literal XML that can be accessed using ECMAScript for XML(E4X) expressions.
    • flashvars – The result is text in flashvars format, value pairs separated by ampersands. Flex returns this result in an actionscript object
    • array – The result is XML that is returned in an Array even if there is only one top level node.

Step 3

Write the actionscript call to submit the form:

public function registerUser():void {
      var params:Object = { 'user.firstName': firstName.text,'user.lastName': lastName.text, 'user.email':email.text, 'user.password':password.text }; 
      this.registerService.send(params);
}

Step 4

Create registerConfirmation(). This method checks whether the registration was successful. We can know that by inspecting the XML that is returned.

private function registerConfirmation(event:ResultEvent):void {
        var xml:XML=XML(event.result); 
 if (xml != null && xml.item == true) {
  mx.controls.Alert.show("Registration Successful!");
 }
 else {
  mx.controls.Alert.show("The registration was not successful.");
 }
 }}

Step 5

If we can’t call the action on the server because of some networking issue we also should give some feedback to the user.

   
/**
 * Display a message to the user explaining what went wrong
 */
private function registerFailed(event:FaultEvent):void {
 mx.controls.Alert.show(event.fault.message);
}

Now let’s create our Struts 2 Action:

Step 1

Create RegisterAction.java

package uk.co.spltech.web.actions;

import uk.co.spltech.beans.User;

import com.opensymphony.xwork2.ActionSupport;

/**
 * Creates a new user
 * 
 * @author Armindo Cachada
 *
 */
public class RegisterAction extends ActionSupport {

 private User user;
 
 private Boolean success;
 
 public Boolean getSuccess() {
  return success;
 }

 public void setSuccess(Boolean success) {
  this.success = success;
 }

 public User getUser() {
  return user;
 }

 public void setUser(User user) {
  this.user = user;
 }

 /**
  * Registers a user
  * 
  * @return
  */
 public String register() {
  System.out.println("Checking user");
  if ( this.getUser()!= null) {
   User u = this.getUser();
   if (u.getEmail()!= null && !u.getEmail().equals("") && u.getPassword()!= null 
     && !u.getPassword().equals("") ) {
    System.out.println("Successfully registered user with email=" + u.getEmail());
    this.success=true;
   }
   else {
    this.success=false;
    System.out.println("Error registering user");
   }
  }
  else {
   this.success=false;
   System.out.println("Error registering user");
  }
  
  return SUCCESS;

 }
 
}

Step 2

Add action name=’register’ to struts.xml

<package name="user" extends="struts-default">
        <action name="register" method="register" class="uk.co.spltech.web.actions.RegisterAction">
           <result type="xslt">   <param name="exposedValue">{success}</param></result>
        </action>
</package>

Source for “Adobe Flex with Struts 2 using HttpService” Example


To compile this example you will need to copy the following libraries to the lib folder:

commons-fileupload-1.2.1.jar
commons-io-1.3.2.jar
commons-logging.jar
freemarker-2.3.13.jar
ognl-2.6.11.jar
struts2-core-2.1.6.jar
xwork-2.1.2.jar
struts2-convention-plugin-2.1.6.jar

Uploading a file with Struts 2

Uploading a file with Struts 2 is really simple with the help of the FileUploadInterceptor. The steps required to upload a file using Struts 2 are:

Step 1

Create the Struts 2 Action class. In our example we have called it FileUploadAction.java

An example of an action to upload a file:

package uk.co.spltech.web.actions;

import com.opensymphony.xwork2.Action;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;


/**
 * Uploads a file using Struts 2
 * 
 * @author Armindo Cachada
 */
public class FileUploadAction extends ActionSupport {
     private static final long serialVersionUID = 12323232L;
     private File file;
     private String fileFileName;
     private String fileContentType;
    
    
 public String execute() {

  return Action.SUCCESS;
 }
   
 public File getFile() {
        return this.file;
     }
 
  public void setFile(File file) {
         this.file = file;
      }

  public void setUpload(File file) {
      this.file = file;
   }
 /**
       * This method is called by the action.
       * Here you can do whatever you want with the uploaded file
       */
 public String upload() throws IOException  {
        File uploadedFile =this.getFile();
        // you can do whatever you want with the file
        return Action.SUCCESS;
 }


 public String getFileFileName() {
  return fileFileName;
 }

 public void setFileFileName(String fileFileName) {
  this.fileFileName = fileFileName;
 }

 public String getFileContentType() {
  return fileContentType;
 }

 public void setFileContentType(String fileContentType) {
  this.fileContentType = fileContentType;
 }

 public String getFileUrl() {
  return fileUrl;
 }

 public void setFileUrl(String fileUrl) {
  this.fileUrl = fileUrl;
 }
}

Step 2

Create the action in struts.xml

<action name="fileUpload" class="uk.co.spltech.web.actions.FileUploadAction" method="upload">
 <result>/success.jsp </result>
 <result type="error">/upload.jsp</result>   
</action>

Step 3

Create the jsp. For example:

Please select the file you want to upload:

 <s:form action="fileUpload" method="post" enctype="multipart/form-data" theme="simple">  
  <s:actionerror cssClass="errorMessage"/>
  <s:fielderror cssClass="error"/>
      <s:file name="upload" label="File"/>
     <s:submit/>   
 </s:form>

Step 3

The default maximum file size that struts 2 allows you to upload is only 2 megabytes. You can increase this size by specifying in struts.properties the struts.multipart.maxSize. This value is in bytes.
For example:

struts.multipart.maxSize=20480

Finally you can download the code for this example here.

Note that I didn’t include the required struts2 library files with the example.
The files you need are:

commons-fileupload-1.2.1.jar
commons-io-1.3.2.jar
commons-logging.jar
freemarker-2.3.13.jar
ognl-2.6.11.jar
struts2-core-2.1.6.jar
xwork-2.1.2.jar
struts2-convention-plugin-2.1.6.jar


Click here to learn how to upload a file with Adobe Flex