Throw it onto the Internet, but will they come?

Despite the talk of the second tech bubble, new ideas still pour out. Sometimes people gravitate towards them. And sometimes they even make money. “Coding isn’t about making money or scratching some OCD itch. It’s about doing what you love and, yes, changing the world.” More in Bubble Boys from New York Magazine.

Changing default braces in Flash Builder

Those little curly punctuation marks can cause controversy. Some folks are entirely end-of-the-line adherents, others are stridently next-liners. The templates and code completion within Flash Builder follow the next-line model. For some end-of-line folks this can grate like fingernails on a chalkboard.

The default braces are changed within Flash Builder at two places, one for file templates and the other for code block templates. To change the file templates open the preferences for Flash Builder. Go to the Flash Builder->File Templates section and there is a list of all the file templates used in Flash Builder. To edit the code block templates, go to Flash Builder->Editor->Code Templates section.

Kern, Kern, Kern

Competitive kerning has been brought to the Internet: Kern Type, the kerning game. I predict an increase in kerning-related injuries.

Creating and manipulating XML within Process Management in LiveCycle ES 2

Using xPath and creating XML is interesting in process orchestrations. The primary way of manipulating variables within processes is to use the Set Value service. This uses as its “scripting” language xPath. As a scripting language xPath is limited. It is meant to be a query language and does that very well. For creating XML, however, it can be a blunt tool.

Within a process there are three basic ways to create and edit XML.

  1. Using xPath within a Set Value service
  2. Building the XML as text and then deserializing the text into XML. This, too, uses xPath within a Set Value activity. Instead of using xPath to manipulate the XML it is used to manipulate string variables.
  3. Editing an XML variable within an Execute Script service

Using xPath to Build XML Variables

XML may be created within the Set Value service using the xPath syntax if the XML has schema associated with it.

For example, it is possible to start with an empty XML variable that is associated with a schema and add nodes.

/process_data/node = "" // make sure the XML is empty
/process_data/node/resources/resource/@value = "value for first resource"
/process_data/node/resources/resource/@id = "id for first resource"

 
In this example, the variable, node, is now:

<resources>
     <resource id="itemOne" value="itemTwo"/>
</resources>

 
But what if there is more than one resource node? Let’s add code to set the value of a second resource node:

/process_data/node = "" // make sure the XML is empty
/process_data/node/resources/resource/@value = "value for first resource"
/process_data/node/resources/resource/@id = "id for first resource"
/process_data/node/resources/resource[number(2)]/@id = "id for second resource"
/process_data/node/resources/resource[number(2)]/@value = "value for second resource"

 
This, sadly, fails. To be able to set the value of a node that is referenced by index, the item must already exist.

It is possible to add items to list items using xPath syntax.

/process_data/stringList = empty-list()
/process_data/stringList = "item one"
/process_data/stringList = "item two"

 
Now, /process_data/stringList[number(1)] equals “item one” and process_data/stringList[number(2)] equals “item two”

Can we do the same with XML in the xPath syntax? Unfortunately, no. The Set Value service treats Java objects (such as the list) and XML completely different.

/process_data/node = "" // make sure the XML is empty
/process_data/node/resources/resource/@value = "value for first resource"
/process_data/node/resources/resource/@id = "id for first resource"
/process_data/node/resources/resource/@id = "id for second resource"
/process_data/node/resources/resource/@value = "value for second resource"

 
This replaces the value of a node with a new value. The value of XML is now:

<resources>
     <resource id="id for second resource" value="value for second resource"/>
</resources>

 

Building XML as text

We can build an XML value in a more cumbersome way by building the xml in text.

/process_data/@nodeId = "id for first resource"
/process_data/@nodeValue = "value for first resource"
/process_data/@stringVariable = "<resources>" // add the start tag to the string
/process_data/@stringVariable = concat(/process_data/@stringVariable,"<resource") // add the beginning of the resource tag
/process_data/@stringVariable = concat(/process_data/@stringVariable," id='",/process_data/@nodeId,"'") // add the id attribute
/process_data/@stringVariable = concat(/process_data/@stringVariable," value='",/process_data/@nodeValue,"'") // add the value attribute
/process_data/@stringVariable = concat(/process_data/@stringVariable,"/></resource>") // close tags
/process_data/node = deserialize(/process_data/@stringVariable)

 
Building XML with text may be more cumbersome for simple XML, but it does provide a way to add nodes that xPath does not provide. In addition, a schema is not required. To add another resource to the sample above:

/process_data/@nodeId = "id for second resource"
/process_data/@nodeValue = "value for second resource"
/process_data/@stringVariable = serialize(/process_data/node) // get existing node as a string
/process_data/@stringVariable = string-before(/process_data/@stringVariable,"</resources>") // returns everything but the closing resources tag
/process_data/@stringVariable = concat(/process_data/@stringVariable,"<resource") // add the beginning of the new resource tag
/process_data/@stringVariable = concat(/process_data/@stringVariable," id='",/process_data/@nodeId,"'") // add the id attribute
/process_data/@stringVariable = concat(/process_data/@stringVariable," value='",/process_data/@nodeValue,"'") // add the value attribute
/process_data/@stringVariable = concat(/process_data/@stringVariable,"/></resource>") // close tags
/process_data/node = deserialize(/process_data/@stringVariable) // turn string back into XML

 

Building XML using Java

Within orchestrations Java may be used within the Execute Script service. The Execute Script service within Process Management orchestrations uses BeanScript, a scriptable version of Java. Java is much more adapted to complex manipulation of XML data.

Process Management uses the Apache Xerces DOM parser to create and store XML variables within processes. Xerces is a Java implementation of W3C’s Document Object Model specification, http://www.w3.org/DOM/. The DOM specification is a standard way of manipulating XML that has been around since 1998. The Java implementation of Xerces, Xerces-J, supports DOM Level 2 version 1.0.

There is an extended explanation of how to manipulate XML within the Execute Script service within the article, Using the Execute Script Service in LiveCycle Workbench ES2 to build XML data.

A quick way to find an out-of-control thread within CRX

It happens. A process is out of control, consuming system resources on your server and bringing performance to its knees. And many times it is very hard to tell what is behaving badly. For CRX on the Experience Services platform there is a rudimentary profiler that comes in handy when trying to troubleshoot this sort of problem.

The URL for the profiler is at http://[your crx host]:[your crx port]/crx/diagnostic/prof.jsp. This profiler is started, then stopped. It shows the number of times threads ran while the profiler was collecting, sorted in the order of frequency. That’s not a lot of information, but for a quick test to see what is wreaking havoc the built-in profiler works. For more complete profiling use a third party profiling tool such as YourKit.

Optimize the CRX repository

The CRX repository stores its data in tar files. Data is not overwritten or deleted as it is changed. The changed data is added to the tar files and older data continues to exist in the tar files, unused. Doing this makes the repository much more efficient. But this means that even small changes, if there are enough of them, will cause the amount of data residing in the jar files to become quite large.

How can the amount of space taken up by the repository’s tar files be quickly reduced?

CRX has functionality that works like memory garbage collection except for tar files. The tar files can be optimized with this functionality and reduced in size. When this happens the unused data stored in the tar files will be removed and the amount of data stored in the tar files can become much less.  By default, this optimization occurs in the early morning hours. If the size of the repository tar files becomes too large the optimization can be run manually any time it is needed.

Running the CRX respository tar file optimization

After logging into the Experience Services console with an administrator account select the link, Repository Management, on the right. This will take you to the management screen for the CRX repository. Select the link, Tar Persistence Manager Optimization.

On this screen is a field, Delay after optimizing one transaction. Changing this to be a higher number will cause the optimization to take longer while using less of the processor on the server.

To optimize the tar files of the repository, press the button, Start Optimization. While this is running you will see two buttons, Refresh and Stop Optimization. To get updates of the progress of the optimization you will need to press the Refresh button. When completed, a message is displayed: Optimization successfully finished.

For more information see:
Documentation for CRX Persistence Managers

Specifying channel fallback for Flex applications using Data Services

Note: Edited 22 November 2001 to add symptoms that fallback to RTMPT can cause and how to disable RTMPT.

Data Services servers that have a high volume of messaging connections can have a problem in which all available sockets or threads are used. Another point of issue they can have, too, are large worker threads that seem to linger long after they are no longer being used. Sometimes the amount of memory consumed by these threads is great enough that the developer begins to suspect there is a memory leak. It is a particular problem if the number of client application that cannot connect to the server via the conventional RTMP port is large.

The most effective protocol to use for messaging within Data Services is RTMPS. Not all firewalls allow the passing of RTMPS traffic. Messaging between Data Services and Flex can use several protocols, including HTTP streaming. The process of the Flex client using alternative protocols when the preferred do not work is called fallback. Which protocols are preferred and in what order they are attempted during fallback can be configured.

Fallback between Data Services and Flash is mostly programmed within Flash. The server.xml and messaging.xml configuration files define a contract between Flex and the server. Flex reads the configuration files at runtime and follows those specification when connecting to the Data Services server. The Data Services server uses the configuration file to know which endpoints it needs to make available for Flex to use.

Say a developer wants a fallback from RTMPS to the HTTP Streaming. And they need the fallback to be secure. Within the services-config.xml file the configuration for the secure HTTP streaming needs to be added. If the developer is sending XML back and forth they can use HTTP secure streaming. For passing AMF data the developer can use the AMF version of the HTTP secure streaming.

<channel-definition id="my-streaming-amf">
     <endpoint
         url="http://{server.name}:{server.port}/{context.root}/messagebroker/securestreamingamf"
         class="flex.messaging.endpoints.SecureStreamingAMFEndpoint"/>
     <server ref="secure-nio-streaming-amf-service"/>
</channel-definition>

 

The endpoint, secure-nio-streaming-amf-service, needs to be defined within the configuration like in the same way are for RTMPS.

The fallback order is specified in the messaging-config.xml. So the secure HTTP streaming endpoint needs to be added:

<channels>
     <channel ref="my-rtmps" />
     <channel ref="my-rtmp" />
     <channel ref="my-streaming-amf" />
</channels>

 

The configurations on the server make the fallback endpoints available and gives the Flex compiler a way of knowing the endpoints to use for fallback. Flex does not make a query to the server at run time for the preference order of endpoints. This information needs to be compiled into the client or handled within the ActionScript on the client layer. I am guessing this is done for security reasons. If a client obtained endpoint information at runtime it is possible for someone to point the client to their own servers and hijack your traffic.

One last step must be completed to keep RTMPT from being used. There is a setting to disable it: block-rtmpt-polling-clients. Adding this property to the RTMP channel will disable it.

<channel-definition id="serverRtmp" class="mx.messaging.channels.RTMPChannel">
    <endpoint uri="rtmp://localhost:2037/rtmp" class="flex.messaging.endpoints.RTMPEndpoint"/>
    <server ref="nioserver"/>
    <properties>
        <block-rtmpt-polling-clients>true</block-rtmpt-polling-clients>
    </properties>
</channel-definition>

 

How to Set Fallback on the Client

There’s more than one way to set up fallback within your client. Your Consumer class instances have a channelSet property that contains the list of channels to use in order of preference. This information needs to populated within your client. This can be done with just configuration. You can also use MXML and ActionScript to set the fallback.

Specifying Fallback Through Configuration Only

There is a compiler tag, -services, that can be used with the MXML compiler of the Flex SDK. The tag -services should be set to the path of your services-config.xml. When you do this, your MXML will be compiled with the server-specific information. When a new instance of Consumer is created it will have its values already populated with the values you specified in your configuration. If you are compiling an ActionScript-only application or component this value will not be pre-set. I am supposing you at least have a top-level MXML application file.

Specifying Fallback Through MXML

A Consumer instance can be created using MXML.

<Consumer id="msging" destination="messagingDestination">
     <mx:channelSet>
          <mx:ChannelSet>
               <mx:channels>
                    <mx:SecureStreamingAMFChannel
                         id="secureStreaming"
                         uri="http://myserver:2000/myapp/messagebroker/secureAMF"/>
               </mx:channels>
          </mx:ChannelSet>
       </mx:channelSet>
</Consumer>

 

Specifying Fallback Within ActionScript

The following example shows ActionScript code that is equivalent to the MXML code in the previous example:

private function run():void
{
    consumer = new Consumer();
    var cs:ChannelSet = new ChannelSet();
    cs.addChannel(
            new SecureStreamingAMFChannel (
            "secureStreaming",
            "http://myserver:2000/eqa/messagebroker/secureAMF")
    );
    consumer.destination = "secureStreamingAMF";
    consumer.channelSet = cs;
}

 

Detecting the Type of Channel Being Used By a Consumer

The same channelSet property of a Consumer instance that can be used to set the fallback channels can be used to detect the current channel type. ChannelSet has a the property, currentChannel. Each type of channel has its own class. Those classes can be found in the documentation for the … package. Each channel also has a protocol property. If the channel is RTMP or RTMPS, the value of protocol will be the string, “rtmp.” If the channel is RTMPT, the protocol will be “rtmpt.” For all non-secure HTTP channels the protocol is “http.” For all secure HTTP channels the protocol is “https.”

Documentation

Real-Time Messaging with LiveCycle Data Services ES
http://blogs.adobe.com/flexdoc/2007/07/realtime_messaging_with_livecy_1.html

This is very good documentation about messaging and includes information about fallback. A lot of this may be too basic for you, but there is enough here that there may be some details that will help you out.

About channels and endpoints

http://help.adobe.com/en_US/LiveCycleDataServicesES/3.1/Developing/WSc3ff6d0ea77859461172e0811f00f6e876-7fecUpdate.html

 

How to respond to close and open events for tiles within the Composite Application Framework (Mosaic)

Within the Composite Application Framework, responding to the closing of tiles can be problematic. A tile can detect its own closing. Problems arise if the tile attempts to notify other parts of the program that it is closing through calls to shared services or changing global values. Before the tile can dispatch Mosaic events to other tiles it is closed.

Underlying Mosaic is the Client Component Framework (Gravity). Gravity is an OSGi-inspired framework that allows for plugins or modules to be added and removed to Flash applications. When a tile closes, the Gravity BundleEvent.BUNDLE_UNINSTALLED event is dispatched.

Here is an example snippet passed to me that shows how to listen for Gravity-oriented events:

BundleContext.currentContext.addEventListener(BundleEvent.BUNDLE_INSTALLED, bundleChange);
BundleContext.currentContext.addEventListener(BundleEvent.BUNDLE_RESOLVED, bundleChange)
BundleContext.currentContext.addEventListener(BundleEvent.BUNDLE_RESOLVING, bundleChange);
BundleContext.currentContext.addEventListener(BundleEvent.BUNDLE_STARTED, bundleChange);
BundleContext.currentContext.addEventListener(BundleEvent.BUNDLE_STARTING, bundleChange);
BundleContext.currentContext.addEventListener(BundleEvent.BUNDLE_STOPPED, bundleChange);
BundleContext.currentContext.addEventListener(BundleEvent.BUNDLE_STOPPING, bundleChange);
BundleContext.currentContext.addEventListener(BundleEvent.BUNDLE_UNINSTALLED, bundleChange);
BundleContext.currentContext.addEventListener(BundleEvent.BUNDLE_UNINSTALLING, bundleChange);
BundleContext.currentContext.addEventListener(BundleEvent.BUNDLE_UPDATED, bundleChange);
BundleContext.currentContext.addEventListener(BundleEvent.BUNDLE_UPDATING, bundleChange);

BundleContext.currentContext.addEventListener(ServiceEvent.SERVICE_MODIFIED, bundleChange);
BundleContext.currentContext.addEventListener(ServiceEvent.SERVICE_REGISTERED, bundleChange);
BundleContext.currentContext.addEventListener(ServiceEvent.SERVICE_UNREGISTERING, bundleChange);

 

How to iterate through an XML collection within LiveCycle/Document Services Process Management

The Set Value activity within Process Management orchestrations uses xPath for  building expressions. And xPath has some quirks features that can frustrate developers who are not used to it.

One thing that can be confusing is how to iterate through XML collections. The problem is caused by the fact that xPath interprets all variables as strings unless they are coerce to some other type. And this coercion can happen automatically in some circumstances.

In this case, the variable @i is treated as a number because it is being added to another number:

/process_data/@i = /process_data/@i + 1
// this performs addition and increments @i by 1

 

But when used as an xPath reference variables are treated as strings:

/process_data/@i = 1
/process_data/myXML/topElement/childElement[/process_data/@i]
// this will return the first item
/process_data/@i = 20
/process_data/myXML/topElement/childElement[/process_data/@i]
// this returns the first item, too!

 

When used a reference, always coerce variables to be a Number:

/process_data/@i = 20
/process_data/myXML/topElement/childElement[Number(/process_data/@i)]
// this returns the 20th item

 

Deconstructing Experience Services: the Composite Application Framework (Mosaic)

The Experience Services contains the Composite Application Framework (Mosaic). The framework has both a server component and a Flex component. Adding the ADEP tooling plugins will, among other things, provide Mosaic capabilities to Flash Builder.

Mosaic builds on the OSGi-inspired Gravity framework. It provides a Flex sdk and tools for creating Mosaic applications, functionality within Flash Builder to create catalogs and deploy applications to a server, and the Mosaic server to present the applications over the Internet.

Content, both Flash-based and HTML, can be brought to together into an application as individual tiles. The tiles can be existing content recompiled with Mosaic tags or it can be new content. The tiles do not all have to have been compiled with the same Flex SDK. The tiles can be developed independently of each other by separate team or at different times. And the tiles can be reused in other applications.