Archive for November, 2010

Service Interruptus

While working on a recent LiveCycle Mosaic demo, I discovered some interesting consequences of using Mosaic services with large amounts of data and memory heavy tiles.  Since the cause of the issues was not immediately apparent, and the solution is quite simple, I thought I’d share my findings.

The Conditions

The demo I was constructing consists of quite a few Mosaic tiles that rely on common data.  Basically each tile shows a different aspect of the data, so the user gets a graphical breakdown of a current situation.  Since much of the data is shared across several tiles, I figured it would be a good use of a common Mosaic service.  Then each tile can access the same service and the data only needs to be loaded once.  The service will read an XML file from the Mosaic catalog, process it and will have functions that will present aspects of the data to the Tiles.

arch2

In the service implementation class, I have a standard Flex HTTPService object that I use to load the data into an XML object.  After the data is loaded into the service there are several functions that can be called by the tiles.

The Symptoms

For early testing I created a simple XML file and a couple of quickie tiles. By watching the Flash Builder 4 console, I could see that the service was loading, then the tiles.  The tiles could access the data via the service with no problems. As I continued adding more complex tiles, and increasing the size of the XML file, strange things started happening.

Every once in a while a tile would give a null pointer error.  Upon further inspection, this happened only in tiles that called the service functions on creation complete.  It looked as if the service had not loaded the data, but when I put break points in my code I could see that the data was loaded.  To aggravate the issue, it wasn’t consistent as to when the problem would happen.  I could load the application a dozen times and it would work fine, then it would fail once or twice and then be fine again.

WTF???

Somebody tell Schrodinger his cat is dead

If all else fails, procrastinate. I ignored the problem and continued working on the rest of the demo – hey it worked most of the time.  As I continued to add additional tiles and functionality to the service things steadily got worse.  Eventually it got to a point where it would fail more often than it would not.  To be fair to myself (and who else will), it really was a good thing to delay looking for the root of the problem.  At least now I could take a serious look at what was going wrong and have a reasonable chance of looking at a failed case.

I’ll save you the tribulation of my debugging efforts, needless to say I learned a lot about working with a non-linear multi-faceted environment such as Mosaic.  Not the least of which was – just observe, don’t participate.  Trying to find intermittent problems with multiple tiles, services, asynchronous events and a black box framework takes a level of patience for which I am not well equipped.  I tried to be Zen about it but The Norse part of my genetics just wanted to smash it with a big axe and go burn a village (ah, simpler times…)

After stepping through the code multiple times, and adding more trace statements than I’d like to admit, I was able to figure out that there were actually two separate problems.  One was fairly obvious, the other not so much.

Problems and Solutions

The first problem was in the service itself.   The tiles depended on the data provided by the service.  The service implementation uses an HTTPService to read the data from an XML file.  Since the HTTPService load operation is asynchronous (waits for a ResultEvent), a tile may try to access the service before the data is loaded.  When the tile makes the call to the service, the XML data is empty and an exception is thrown when the service tries to perform an operation on the data object.  When there wasn’t much data it loaded quickly enough not to present a problem.  As the test data became larger it took more time to load and the problem started to show itself.

If this was a “normal” Flex app, I’d just have the service dispatch an event when the data was loaded.  Flex components that depended on that service would have event listeners that would wait for the service to say it is ready.  This won’t work in the Mosaic framework however, because of the decoupled nature of services and tiles.  The tile does not have direct knowledge of the service context and therefore cannot pickup events thrown by the service.  The solution is to have the service send a message to the Mosaic framework, and have the tiles listen to the framework for a message.  Unfortunately, Mosaic service implementations don’t directly inherit the Mosaic context.  Yes, I can import the IContext class, but there is no way to initialize it directly with the Mosaic framework’s information.

The solution was a bit of a cheat.  I can get the Mosaic context information from a tile, it’s a property of the inherited mosaicApp object.  So what I did was to add an IContext variable to the service, with a setter function.  Then I had one of the tiles pass its context to the service using the setter.  Now when the service decides that both the data and context are set, it can set a Mosaic attribute saying that its ready.  Tiles will check the attribute before attempting to access the service.  As a bonus, tiles can watch for the attribute to change which will tell them the data has been updated.

I implemented the fix, and tested it out.  Everything worked fine … for a while.

Every once and a while the tile that passed its context to the service would throw an exception.  The exception stated that the service itself was null.  From what I understood about the way Mosaic handled the services, this should not be possible.  Mosaic is supposed to load the services before the tiles, guaranteeing that they would exist. Another round of step through and trace statements ensued.  From what I was able to deduce, Mosaic was indeed loading the service before the tiles, however the tiles could be created before the reference to the service was injected.  In other words, because I was setting the context on the tile’s creationComplete event, the service implementation’s reference may not be fully realized – resulting in a null pointer error.

The solution to this problem was less pleasant.  The only way I could figure to make sure the service reference was complete was to put a timer into the tile that set the service context.  Basically I check to see if the service object is null.  If it is then I set a timer’s event listener and start the timer.  The event listener checks again to see if the service is null.  If it is then it resets the timer.  If it is not then I set the context object and we move on.

I’m not a fan of these kind of timed wait loops. However; without being able to get an event from the service, I can’t see any other way of doing it.  The problem is that I can’t get an event without the context being set and I can’t set the context until I know the service is not null.

I also added a check in the other tiles to not only look for the service’s data loaded attribute, but they also check to see that the service object is not null.  Belt and suspenders programming at its best.

Conclusion

Here is the short version of what happened:

Issue 1

  1. Services that perform asynchronous operations need to tell their dependent tiles when these operations are complete
  2. Service have no direct way of notifying tiles as they don’t have access to the Mosaic context
  3. A tile can pass that context to the service if the service exposes a context object setter function

Issue 2

  1. Service load before tiles, however tiles can reach creation complete before the service injection has happened.  This means that the tile’s service object may be null.
  2. The only thing to do is to have the tile wait (using a timer loop) for the injection to be complete.

Creating an Organized Mosaic Project Structure

Lately, I’ve been working a lot with people that are new to LiveCycle ES2 Mosaic.  One thing always seems to come up is the question of the best way to organize Mosaic projects.    There aren’t any hard and fast rules (with the exception of the Catalog folder layout), but I’ve seen enough similarities in unrelated projects to suggest that there are some unofficial conventions that are forming.  I won’t go as far as to call the following “best practices”, rather consider them suggestions based on experience.  When combined with standard Flex best practices, these suggestions may make developing your Mosaic applications a bit easier.

Folder Structure

Organization will set you free – Alton Brown

Mosaic applications consist of quite a few moving parts.  There are the application descriptors, tile code, services and interfaces, authentication policies, shell skins, etc.  Keeping these sorted out will definitely make your life easier, especially when it comes to deploying and debugging.  Whenever possible, I prefer to keep all of the files/folders for a single Mosaic undertaking under a single folder.  That may mean having more than one application in the same folder, but at least the related code will be close by.

Under that parent folder I usually create one folder for each major Mosaic component.  The folder names are in lower case to differentiate them from the Catalog’s folders (more on that later).  For example:  I have a project called the Sales Dashboard, which will contain an application, catalog, several tiles, a service, a custom style sheet, etc.  To keep from going insane, I created the following folder structure:

topLevel

  • applications – this folder contains the application descriptor xml file(s)
  • catalogs – this folder contains the deployable contents for the project’s catalog.  If I was to have multiple catalogs, then they would each go in a separate subfolder.  A catalog’s structure is one of the few things that must have a specific structure.  This is because the catalog folder gets zipped and then deployed to the Mosaic server.  For more on the catalog folder’s structure, see the section below.
  • interfaces – this project uses a Mosaic Service component that is used by several tiles.  Each service component consists of two parts – the interface library and the service class.  This folder contains sub folders for each of the interface library projects.  Those subfolders contain a Flex Builder project that includes the source code for the interface.  In this example I have a single interface library called the “SalesDashboardInterfaceLibrary”, so the interface folder has a single subfolder with that name.  In the subfolder is a Flex Builder project for the interface:
    interfaces
  • policies – if you are using the Mosaic fine grained authorization, then this folder contains the XACML files that provide authorization information for the elements.
  • services – this folder is related to the interfaces folder.  It contains subfolders for each of the service class files.  Inside those subfolders is a Flex Builder project used to develop the service code.  For example, this application includes a “SalesDashboardService”. That subfolder contains a Flex Builder project for that service library:
    service
  • stylesheets – this project contains a custom skin for the Mosaic application.  The Flex Builder project for this skin is in a subfolder under the stylesheets folder.  If I had more than one skin, then each would get its own subfolder.  For example, my skin project is called “GlobalCorpSkins”:
    stylesheet
  • tiles – this folder contains sub folders for each of the Flex Builder tile projects.  Usually I try to keep related tiles in the same Flex Builder project (it makes debugging a bit easier), so a single sub folder may contain many tiles.  There are some cases, however, where a particular tile needs  its own project.  For example, if it uses a different Flex SDK or comes from a legacy application.  How fine grained you want to make the tile projects is really up to you, but keeping them all under this one tiles folder will make them easier to find.  In this example I have two tile projects – Flex 4 tiles (which contains several tiles) and Map (which contains a single, very complex tile):
    tiles

Catalog Structure

As I said earlier, the catalog structure is the one thing that must be in a specific format.  The catalog contains the deploy objects (compiled code, resources, etc.) and it will be zipped, then sent to the Mosaic server.  The server is expecting specific things to be in specific folders.  And yes, those folders are case sensitive.

catalog

  • descriptor.xml – this is the catalog’s definition file.  It must be named descriptor.xml and it must be at the root of the catalog zip file
  • Interfaces – contains the compiled swf for the interface libraries.
  • Resources – this is where the miscellaneous stuff needed for tiles and services is stored.  Things like images, XML files, videos, etc. are put here.
  • Services – contains the compiled swf for the service classes
  • Stylesheets – contains the skin classes complied into a swf
  • Tiles – contains subfolders for each of the tiles in the catalog.  The subfolder names is the same name as the tile, and they contain the tile swf files.

Flex Builder Linked Resources

Since tiles, services and skin projects rely on the Mosaic SDK, you’ll need to include the appropriate SDK swc in each of your projects.  Rather than hard coding the path, it is a good idea to create a pointer to the SDK folder and let Flash Builder sort out the location.  This makes your code more portable, if you give it to someone else, they don’t have to have the SDK in exactly the same location as you do.

To set up a linked resource to the Mosaic SDK:

  • Open Flex Builder
  • Choose Window –> Preferences
  • Choose General –> Workspace –> Linked Resources
  • Click the New button
  • Give it a name of MOSAIC_SDK
  • Click the Folder button and browse to your Mosaic SDK folder.  Don’t go any lower than the “sdk” folder.
  • Click OK to close the dialogs

When you create a new Mosaic project you can use the linked resource in your Flex Build Path.  Then if someone else opens your project and has the SDK in a different location, Flash Builder will sort out the reference (assuming they have a MOSAIC_SDK resource).

ANT Scripts

It may seem that I’ve gone a little berserk with the organization of the project.  I mean, how anal retentive can you get?  Why not just lump everything together in one or two folders and be done with it?

The answer lies in the application deployment through ANT scripts.  Having a highly organized structure like this allow you to build the deployment code as a few, small ANT files.  These can be combined together to quickly deploy code changes in an efficient manner.  There are few things more annoying than testing against the wrong code.

For example; At the root of the project I have an ANT script that deploys the catalog, application and policies.  Before that section executes, it calls ANT scripts in the sub folders that re-compile the interface, service, style sheet and tile classes, and move them to the appropriate location in the catalog structure.  Using this, I can make changes to a tile, run the root ANT script and ensure that everything is the current version.

True, it takes a bit more effort to set up, but the time and frustration savings are well worth it.  Here’s what my final folder structure looks like:

folderStructure

Request for Comments

For what its worth, most of the above is my opinion based on my own experiences.  If you have any additional suggestions, I’d love to hear them.

LiveCycle Process Management ES2 Task Access Control List

Recently, I had an interesting discussion with a customer representative regarding the nature of LiveCycle Process Management ES2 and the use of shared queues.  Specifically, the issue came down to a misunderstanding of how the Assign Task Operation’s Task Access Control List (ACL) parameters effected who could see items in a user’s shared queue.

With the help of Chantal Richard and Jasmin Charbonneau, I learned a lot more about what these parameters do.    I though it would be a good idea to share the information in case others are as confused as I was.

Say we have a task that is assigned to a user.  The particular user is decided at runtime based on some process data.  The Task Access Control List (ACL) provides restrictions on what that user can do with the task.  It does not say who the task can be shared/consult/forward (etc.) with.  The “Add ACL for shared queue”  only states whether the task can be viewed in a shared queue, not who gets access to that shared queue.   You can use the “Reassignment Restrictions” to specify which group(s) a user can share with/forward to /consult with.

For example, consider the following setup for a task assignment (see image):

clip_image001

A task is assigned to a user based on the XPath expression – let’s say, based on form and process information,  it gets assigned to Sarah Rose.  The system then checks to see if Sarah is in the Task Access Control List (ACL).  In this case she is, and her options say she can share the task.  The Task Access Control List (ACL) does not say with whom she can share.  The other users in this list (John Jacobs and Kara Bowman) are in the list in case they get assigned the task and the system needs to decide what they can do.  The Reassignment Restrictions section tells us that this task can only be shared with the “All principals in Default Domain” group.

Since the “Add ACL for shared queue” is checked, the task will show up in Sarah’s shared queue (if it was not on then it would not show up in her shared queue).  This means that if Sarah shares her queue with another user they will see that task in her queue.  An important note – the “Add ACL for shared queue” option is not affected by the “Reassignment Restrictions”.  In this example; if Sarah shares here queue with Bob Jones who is not in the “All principals in Default Domain” group, then when Bob looks in Sarah’s queue he will see the task.

If we now look at the entry for John Jacobs in the Task Access Control List (ACL) list, we will see that he is not allowed to Share or Consult the task.

image

This means that if the task was assigned to John, he would not be allowed to share the task or use Workspace to consult with others.  He has different permissions than Sarah.