Flex and ApEx: exchanging data

Following my post Flex and Oracle, I wanted to investigate how difficult it would be to exchange data between flex and ApEx. After some trial and error I’m pleased to say that it isn’t that hard to exchange data between both technologies.

I started by looking for a way to get a simple string from a flex application to an ApEx application. I came across the ActionScript API “ExternalInterface“. The Adobe documentation for the api:


The ExternalInterface class is the External API, an application programming interface that enables straightforward communication between ActionScript and the Flash Player container or a desktop application with Flash Player embedded.

ExternalInterface has a method “call” where you can specify the name of the external function you want to call, the second parameters are the parameters you want to pass to that function.

In your html page make a function called “setDept” with the necessary parameters and let the fill the Apex Items. Make a clickhandler in your flex application and call your function, you will see that it works perfect.

Now we have send data from flex to ApEx, it’s time to send something back from ApEx to flex. To start we need to be sure we have a JavaScript function that allows us to speak with the swf file. After some searching, trial and error, I came across the next function that works in both Mozilla and IE:

Now we need to create a javascript function that will pass a String to our flex application using the thisMovie function. Once this is done the only thing we need to create an ActionScript function that can registers an ActionScript method as callable from the container. We can use the method “callBack” from the “ExternalInterface” class for this.
Your Actionscript could look something like this:

Test the JavaScript function on your html page and you will see that you send data from your ApEx application to your flex application.

<!–You can find a working example here.–>

Integrating Flex and Data Management Services with a Bpel process – What about Typed Collections?

As you can remember we’re working out a flex application using Data Management Services and Flex for the client-side and Bpel at server side.

During development I ran into a blocking issue regarding using typed collections in my ActionScript objects.

Why would I use Typed Arguments, Typed Collections or Typed Arrays ?
My bpel process is using a Global Business Object (GBO), an XML Schema Definition, that defines the entire structure of the business objects I will need in the dossier management lifecycle. The bpel process will be cut pu into different sub processes which will define the needed process lifecycle for the dossier management system we’re building.

Of course this kind of business functionality will be handling master-detail data, e.g. a dossier has dossier_members and dossier_members have address_information.

If we create a web service proxy client for our bpel process, the different objects used in this process will be defined as Java Objects. The hierarchical structure of the dossier-element or – object will be defined in the following manner:

public class Dossier implements java.io.Serializable {
protected int id;
protected be.ws.proxy.types.DossierMembersCollection dosMembersCollection;

public class DossierMembersCollection implements java.io.Serializable
{
protected be.kg.ws.proxy.types.DossierMembers[] dossierMember;

The ActionScript Objects I defined for these server side objects :

[Managed]
[RemoteClass(alias="be.kg.ws.proxy.types.Dossier")]
public
class Dossier
{
public var id:int;
public var dosMembersCollection:DossierMembersCollection;

[Managed]
[RemoteClass(alias="be.kg.ws.proxy.types.DossierMembersCollection")]
public class DossierMembersCollection
{
public var dossierMembers:ArrayCollection;
}

The exception I run into :

ArgumentError: Error #2004: One of the parameters is invalid. at
flash.net::NetConnection/flash.net:NetConnection::invokeWithArgsArray()

What does this mean?
In order for this to work, you need to serialize, you’d need to override both the readExternal and writeExternal methods on both the client and server to take of the serialization of the typed collections yourself.

Practical Approach:

  • Implement the Externalizable Interface at Client- and Server-side
  • Overwrite the readExternal()- and writeExternal()-method in both your client and server classes which match (i.e. the read methods exactly match the write methods on both client and server). You need to serialize your fields as well as the source field of the ArrayCollection (it is an Array).

Take care of serialization and deserialization at server-side, use Externalizable Interface:

public class DossierMembersCollection implements java.io.Serializable ,
Externalizable { protected be.kg.ws.proxy.types.DossierMembers[] dossierMembers;

public DossierMembersCollection() { }

/*** Deserializes the client state of an instance of dossierMembers. */ public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
System.out.println(“Receiving array ———————–”);
Object[] obj2 = (Object[]) in.readObject();
System.out.println(“Read input array obj2 ———————–”);

if (obj2 != null) {
DossierMembers[] dossierMembers = new DossierMembers[obj2.length];
System.out.println(“Initialized dossierMembers———————–”);
loop over the object array and cast the Object-classes to your custom class.
System.out.println(“Looping over array ———————–”); dossierMembers[i] = (DossierMembers) obj2[i];

System.out.println(“DossierMembers: ” + dossierMembers[i].toString());
}}

System.out.println(“Receiving array DONE ————————”); }

/*** Serializes the server state of an instance of dossierMembers. */

public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(dossierMembers); }

Take care of serialization and deserialization at client-side:

[Managed]

[RemoteClass alias="be.kg.ws.proxy.types.DossierMembersCollection")]

public class DossierMembersCollection implements IExternalizable {

public var dossierMembers:ArrayCollection;

public function readExternal(input:IDataInput):void {
trace(“***********Reading dossierMembers”);
var array:Array = input.readObject() as Array;
if (array!=null) {
trace(“****Array received”);
dossierMembers = new ArrayCollection();
Loop over the array and add the arrayElements as typed objects to your collection in the following way:

dossierMembers.addItem(array.pop() as DossierMembers);

trace(“**Number of dossierMembers : ” + dossierMembers.length); }

public function writeExternal(output:IDataOutput):void {

trace(“Write ArrayCollection dossierMembers to array”);

var array:Array = new Array();

loop over object-array and add array-items to the collection: {

array.push(dossierMembers.getItemAt(i));

trace(dossierMembers.getItemAt(i).toString()); }

output.writeObject(array); trace(“Done”); } }

If you get random errors there will propbably be a mismatch between server- and client-side objects. The two approaches you can use are: print statements or stopping in your read/write external methods in the debugger. Step through actionscript classes and Java classes using Flex Debugging mode, so you can ensure that you are reading exactly what you are writing.

Hopefully this will help a lot of people facing the same issues regarding typed objects in an Adobe Flex Environment.

FLEX SQLAssembler

Recently I have been working with Adobe Flex and Adobe LiveCycle Data Services for building a dossier-management system.

I came around some strange behavior which I couldn’t understand regarding displaying referential/static data in a flex user interface.

The requirement I need to implement in my flex application is to display static, referential data in the different forms being filled in by the user.

This data needs to be looked-up and displayed in for example dropdown-lists and can be adjusted by administrator, so no CRUD-operations are needed in the entry-module of the application.

What I wanted to do is fill some ArrayCollections with data stored in an Oracle 10G database. I don’t want to convert my data to actionscript or java objects, no transfer objects or value objects because I just want to display them so I won’t use any adapters. I made a new destination in my data-management-config and added a fill:

<fill>
<name>dossier_types</name>
<sql>SELECT cd as “cd”,
omschrijving as “omschrijving”
FROM dossier_types</sql>
</fill>

You might notice that I used an alias in my query, initially I didn’t know this but without the alias I can’t display any data. For me this seemed the right solution to retrieve my data but when I tried it I didn’t retrieve anything. I couldn’t see the data in the console of my tomcat server either; my ArrayCollection always had length 0.

Not sure for what reason but I put in a JavaAdapter :

<adapter ref=”java-dao” />

Referencing to:

<adapter-definition id=”java-dao”
class=”flex.data.adapters.JavaAdapter” />

Out of the blue the ArrayCollection was populated with the wright data. Note that I did not specify any java class in my destination. I also tried to use the actionscript adapter but then I couldn’t receive any data.

I’m not sure this is the behavior I must expect but for now it works and I don’t need to define any transfer-objects in the form of actionscript or java objects, which is what I wanted to accomplish.