Thoughts on business and business software

Archive for October, 2010

Adobe’s Rich Internet Application (RIA) framework product, LiveCycle Mosaic, allows developers to create applications that are made up of smaller micro-apps called Tiles. Tiles can be either Flex applications or HTML pages and there are very mature tools for development and testing of individual Tiles. Since one of Mosaic’s biggest features is that Tiles can communicate with each other on the client side (not requiring round trips to the server) its very useful to test Tiles running in the framework. In this post I’m going to describe a few tools and tips to make this a bit easier.

Mosaic Debug WAR

There is a special debug version of the Mosaic WAR file that is built specifically for developers. When you install/unzip Mosaic you fill find the debug version in the deploy/war/{logversion}/debug folder (logversion refers to either the log4j-logging or jdk-logging folder). This version of Mosaic is the same as the production version, except it includes hooks for QTP and the Mosaic plugin for Flash Builder (see below). If you want to create a debug environment, simply deploy this debug version to your application server.

Debug WAR in Standalone

Mosaic comes with a handy-dandy standalone version for development. It comes bundled with its own Tomcat so you can start building things without worrying about setting up a more complex production environment. As of the time of this post, the standalone version comes with the production version of Mosaic. The first thing I always do is to replace it with the debug version. Here’s how:

Stop the standalone Tomcat if its running

Go to the {mosaic home}/standalone/webapps folder

Delete the existing mosaic.war (don’t panic, you still have a copy in the deploy folder)

Delete the mosaic folder and everything in it – This will delete any deployed Mosaic apps

Copy the debug version from {mosaic home}/deploy/war/log4j-logging/debug/mosaic.war into the {mosaic home}/standalone/webapps folder

Start the standalone Tomcat and redeploy any apps

Debug Tools

Flash Player Debugger

If you are doing any Flash or Flex development you owe it to your self to get the Flash Player debug version (find it here). Get the ActiveX one if you are using IE and the Netscape one if you are using Firefox. This will allow you to connect to the Flash Builder tool and see exactly what’s going on in your apps.

Mosaic Flash Builder Plugin

The Mosaic team has put together a really useful plugin for the Flex Builder 4 IDE. The LiveCycle Mosaic ES2 Plugin for Flash Builder 4 (FB4) plugin helps with tile creation as well as debugging. Used in combination with the debug version of the mosaic.war file and the FlashPlayer debug version, you can do all of the standard debugging things that you could with FB4, but inside of the Mosaic framework. This includes breakpoints, expression watchers, step through, etc.

The tool will even build a temporary Catalog and Application file so you can test Tiles in the framework strait away. Having said that, however, I usually like to test with my own layouts and catalog setups. Fortunately I can do this by deploying my Catalog and Application descriptors as per normal (using an ANT script), then I change the Debug Configuration in FB4 to use my setup. By setting the Host Application and Catalog settings to point to my descriptors I can test the tiles as they would appear to the end user. For example, in the shot below I have an Application called SalesDashboard and a Catalog called SalesDashboardCatalog. This setup will launch the debugger using those descriptors:

You have 45 seconds to comply

If you are using Firefox as your web browser then you may have noticed that the Flash Player will crash after a short idle time.

This is especially annoying when you are debugging because the thing times out and crashes when you are in the middle of looking at variable properties. This is because of a “feature” in Firefox that crashes the Flash Player after 45 seconds of inactivity. Fortunately its fairly easy to override this by disabling the hang protection:

In Firefox type the following into the address bar (aka the “Location bar”) and hit enter: about:config

Click the “I’ll be careful…” button

In the resulting Filter box type: dom.ipc.plugins.timeoutSecs

In the resluting dialog box enter -1 and click OK

Now the Flash Player won’t time out while you are trying to debug your application.

LiveCycle Mosaic 9.5 has the concept of a service component. This is a data store that defines objects that are used by multiple tiles. This allows the exchange of custom data objects between tiles as well as pre-configuring data before a tile is loaded.

Why Services Matter

Why would you go through the effort of putting together a service? What does it give you that you can’t do with “normal” tiles? One good reason is that you need to exchange custom objects between tiles.

If you have multiple tiles that use the same custom object. If you were to compile each of those tiles with the object inside it and then deploy it, you would run into a problem due to the way Mosaic isolates tiles.

For example:

Say you have a complex object called Dog. A dog has several fields: name, color, breed and a Boolean called hungry. Now say you have two tiles that make use of the dog object – AddDog and ShowDogs. The AddDog tile creates a message that sends out a Dog object. The ShowDogs tile watches for a message with the Dog message in it.

When you package your tiles, each one will contain a copy of the Dog object.

Since the Mosaic framework doesn’t know what a Dog object is and there are really two different Dog objects (one for each tile) you are going to get errors.

You could send each individual as a message (or an array of messages), but that gets cumbersome quickly. Also, if your custom object contains complex objects it becomes a problem.

Now let’s look at doing the same thing using Mosaic Services. This time you create an interface and service for the Dog object. The two tiles don’t include the Dog themselves, but they do refer to it.

Now the framework is aware of what a Dog object is. When the AddDog tile sends a message with a Dog in it, the ShowDogs tile will be able to receive the message.

Using Mosaic Services

To create and use Mosaic services you need to do the following:

Create an ActionScript interface library. This allows you to separate the definition of the custom object from its implementation.

Create the ActionScript service, an implementation of the interface class.

Use the services in your tiles. You will be accessing the custom objects using the interface.

Add the services, interfaces and tiles to the catalog

Add the service reference to the application

Deploy the catalog and application to your Mosaic server.

When the user logs in, Mosaic will use the designated service implementation for the custom object based on the references in the application and catalog information. For those of you that are familiar with the Java Spring framework this is similar to Spring’s dependency injection.

Now let’s look at how to build the above mentioned example using services.

The Interface Library

Using FlashBuilder create a new Flex Library Project to hold the interface file(s). Ensure that you are using Flex 3.4 or greater. The interface spells out the fields and functions that must be in the service implementation.

In this case I only have one interface, IDogData. It defines the name, color, breed and hungry fields as well as a toString function that is useful for debugging.

package com.adobe.etech

{

publicinterfaceIDogData

{

functionget name():String;

functionset name(nm:String):void;

functionget color():String;

functionset color(clr:String):void;

functionget breed():String;

functionset breed(brd:String):void;

functionget hungry():Boolean;

functionset hungry(hngy:Boolean):void;

function toString():String;

}

}

The interface library needs to be compiled into a SWF file so it can be deployed to Mosaic. The easiest way to do this is to modify the sample ant scripts that are shipped as part of the stockDataService that comes with Mosaic.

The Service Implementation Library

Now that we have defined what the custom object will do, we need to actually do it. Create another Flex Library Project to hold the service classes. You will need to add a reference to the interface library you just created as well as a reference to the Mosaic tile API swc.

Next create ActionScript implementation classes that implement your interface library classes. The service class will need to have corresponding functions for each of the ones mentioned in the interface. This is where you put the code that carries out the operations that you named in the interface.

In this example, I have only one service class (DogData) that implements the IDogData interface. The service class fleshes out each of the functions from the interface. I have also added a constructor function that allows me to initialize the service at start up. I’ll talk more on that when I discuss the catalog descriptor.

Much like the interface library, the service library must be compiled into a SWF. Again, the stockDataService includes an ANT script that serves as a good starting point for how to do this.

Services in Tiles

Now that you have an interface library and a service implementation of that interface; its time to look at how the service is used in your tiles.

Start by creating a new Flex project to hold your tile source code. This project will be like any other Mosaic tile project except that you will include a reference to the service implementation library that you created earlier. I won’t get into creating general Mosaic tiles here, as you can find that information in other Adobe documents.

In your tile code, you will refer to the interfaces and not the service implementations. This is because we want Mosaic to select the correct services to ensure that we are using ones common to all tiles. We don’t want a copy of the service embedded in our tile code.

For example: I have a very simple tile called AddDogs. I want it to share the dog object, specified in the IDogData interface, that is loaded into the application. This will allow me to send IDogData objects as part of Mosaic messages. My Tile code looks like this:

Adding Services to the Catalog

I mentioned earlier that the two tiles use the object interface and not any particular implementation of that interface. This is because we only want one implementation loaded, and that should not be in any particular tile. When the tile code runs, however; it will need an instantiated version of the object on which to work.

The Mosaic catalog is used to resolve this issue. In the catalog we will add the service implementation. In the tile descriptions we will create a reference to that service implementation. Mosaic will resolve the references so the running code has access to the instantiated object.

On the file system, in the catalogs folder, we need to add an Interfaces directory and Service directory. Into these we put the compiled interface and service SWF files (or you can have the ANT script do that for you).

The Interface Library Entry

In the catalog’s descriptor.xml file, there needs to be an entry for the interface library. The library has a name that will serve as a reference to other entries.

My advice is that you name the library the same as the interface library’s Flex project and SWF file name. There will be a lot of references in the catalog after we’re done and keeping the names strait will be messy enough.

For example, my IDogData interface is in a Flex project called MyDataInterfaceLibrary, so the interface library entry in the catalog looks like this:

<tile:InterfaceLibraryList>

<tile:InterfaceLibrary name=”MyDataInterfaceLibrary“>

<crx:Metadata>

<crx:Description>Dog Data Interfaces</crx:Description>

</crx:Metadata>

<tile:InterfaceList>

<tile:Interface interfaceName=”com.adobe.etech.IDogData“/>

</tile:InterfaceList>

</tile:InterfaceLibrary>

</tile:InterfaceLibraryList>

The Service Library Entry

The service implementation class needs an entry in the catalog as well. The service entry refers to the Interface Library Entry.

It also allows us to set some data when the service instance is first created. When I created the DogData class, I added a constructor that took four parameters. In the Service Library entry in the catalog, I use the ConstructorArgs tag to load some initial data into the instantiated object. That way I’ll have some dog data when the tiles first go to use the object.

One other important thing to note is the scope attribute. By setting its value to singleton, I’m telling Mosaic to create only one instance of that object. All tiles will share that one instance. If anything changes it, it will be changed for ALL tiles.

The Tile Entries

The tile class entries need to be modified to tell Mosaic how to map the interface library types to variables in the tile. This is done by adding a Depends and Property element to the TileClass element.

The Depends clause tells us that this tile uses interfaces from the specified interface library. The Property element tells us that the interface maps to a specific variable in the tile. If you look at the tile’s MXML code you will see a variable that corresponds to the name attribute. In this case there is the line:[Bindable]publicvar dogData:IDogData;

So this maps the interface library to the content of the tile, note that it does not mention the service library. This is done in the application’s descriptor.

Putting it all Together with the Application Descriptor

The final step is to use the application descriptor to identify the exact service that will carry out the work of the interface. A properties element will be added to each tile reference that uses the service. This will map the service to the property. When combined with the catalog entry for the tile, this will inject the service into the tile’s variable.

This entry tells Mosaic to map the SampleDogData service to the dogData property in the AddDogs tile. If you look at the catalog entry for that tile you can see that the dogData parameter is an IDogData object. You can also see that the SampleDogData service is a DogData class with some pre-named values supplied to the constructor.

What’s it look like

Assuming all of the code, packaging and mapping was done right; the application should be deployable now. Once that’s done you should be able to run it by going to the application’s URL. In the example the application is called SimpleService. It should look like the following:

You can see that there are two tiles: the AddDog on the left and the ShowDogs on the right. One thing to note is that the ShowDogs tile has data to start. This is because the initial data was listed in the catalog along with the service entry.

If I make changes to the dog’s data using the AddDog tile and hit the Add button then the data in the ShowDogs tile will change as well.

This is because the Add button click handler sets a Mosaic attribute that includes the IDogData object. The ShowDogs tile on the other hand is watching for a message that includes an IDogData object. If I loaded a new tile that used the same service I would see the new data, this is because service was marked as a singleton.