<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Enterprise...I Think</title>
	<atom:link href="http://blogs.adobe.com/steampowered/feed" rel="self" type="application/rss+xml" />
	<link>http://blogs.adobe.com/steampowered</link>
	<description>Thoughts on business and business software</description>
	<lastBuildDate>Thu, 20 Oct 2011 20:24:17 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Why HTML forms are [still] important</title>
		<link>http://blogs.adobe.com/steampowered/2011/10/why-html-forms-are-still-important.html</link>
		<comments>http://blogs.adobe.com/steampowered/2011/10/why-html-forms-are-still-important.html#comments</comments>
		<pubDate>Thu, 20 Oct 2011 20:24:12 +0000</pubDate>
		<dc:creator>Mike Hodgson</dc:creator>
				<category><![CDATA[Opinion and Rants]]></category>
		<category><![CDATA[HTML Forms]]></category>
		<category><![CDATA[Web Data Capture]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/steampowered/?p=138</guid>
		<description><![CDATA[Web designers have access to countless rich media tools and social applications, why should they still care about the humble form? How customers interact with you Think about the last dozen web sites you visited. How many asked you for &#8230; <a href="http://blogs.adobe.com/steampowered/2011/10/why-html-forms-are-still-important.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Web designers have access to countless rich media tools and social applications, why should they still care about the humble form?<br />
<h2>How customers interact with you</h2>
<p>Think about the last dozen web sites you visited. How many asked you for information? Whether it’s an account registration, a comment on a blog post, a web forum or a survey, chances are there was a form to gather your information.
<p>HTML forms are important components of modern websites. It’s how your customers tell you who they are, sign up for services and purchase your products. They are the major way your users communicate with you.
<p>If you are truly interacting with your web site’s users you will need to gather some information about them at some point and most of the time this is done through a form.<br />
<h2>But people hate forms</h2>
<p>So why haven’t HTML forms gotten the attention they deserve? I blame much of it on crappy design and inappropriate use. There are some of nice tools out there that make creating HTML forms easy, unfortunately the forms created with these tools is often not well thought out.
<p>Badly designed or badly placed forms can cause user frustration, taking them out of the web sites experience. One of the worst examples of this is the popup survey. If I’m reading your site trying to find a recipe for the ten pounds of zucchini that are in my garden, I don’t want to fill in a survey about your new credit card cross promotion.
<p>Regardless of your form there are some basic things that you should consider:
<ul>
<li><b>Context</b> – ask for the right information at the right time. Sure you need the customer’s shipping address, but ask for it at the right time (and pre-fill it if it’s a returning customer).
<li><b>Functionality</b> – the form should work as users are expecting it to. I know it sounds silly, but there is no easier way to lose audience than to fill in a form and not have the submit button work (or worse have it reset the form).<br />This also means you should follow the standard conventions for forms. For example; if you are providing an exclusive choice, use a radio button and not a check box. When users see a check box they assume that they can choose multiple items.
<li><b>Security </b>– Your gathering, potentially sensitive, customer information. It is extremely important to ensure that that data is handled appropriately.
<li><b>Design</b> – This is far too broad a subject for this one post, but needless to say you should give the same consideration to form design as you would any other aspect of the site.</li>
</ul>
<h2>Think small</h2>
<p>The vast majority of web based forms are simple, with only a handful of fields. By no means are these insignificant, the data gathered here drives the customer experience for many web sites.
<p>In fact, I would argue that these are more important as data gathering devices than the large complex forms, at least it terms of web design:
<ul>
<li>They are completed more often. People are more inclined to fill out a four field form than a four page one.
<li>They are easier to build and update. Less complex forms are easier to put together and deploy, meaning that there is a better chance that they will see the light of day
<li>The total amount of information gathered is several times that of complex forms. Think of all of the little bits of information you are asked for in the course of a day.</li>
</ul>
<h2></h2>
<h2>Your Thoughts</h2>
<p>What are your thoughts?&nbsp; Do you feel that HTML forms have a place in the modern web design toolkit?&nbsp; Is your organization using HTML forms to interact with your audience?&nbsp;
<p>&nbsp;
<p>Completely unrelated side note:
<p>A few of you may have noticed that I have changed the name of this blog from “Steampowered” to “Enterprise…I Think”.&nbsp; There are a couple of reasons for this:&nbsp; 1 &#8211; To avoid confusion with another web site. 2 &#8211; My role at Adobe has recently changed and the change in the blog’s focus will reflect that change.&nbsp;&nbsp; Cheers,&nbsp; Mike.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/steampowered/2011/10/why-html-forms-are-still-important.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dispatching Events from an ActionScript Class</title>
		<link>http://blogs.adobe.com/steampowered/2011/05/dispatching-events-from-an-actionscript-class.html</link>
		<comments>http://blogs.adobe.com/steampowered/2011/05/dispatching-events-from-an-actionscript-class.html#comments</comments>
		<pubDate>Mon, 30 May 2011 17:16:09 +0000</pubDate>
		<dc:creator>Mike Hodgson</dc:creator>
				<category><![CDATA[Developing and Coding]]></category>
		<category><![CDATA[General Knowledge]]></category>
		<category><![CDATA[ActionScript Custom Event]]></category>
		<category><![CDATA[ActionScript Event Dispatch]]></category>
		<category><![CDATA[Pure ActionScript Event]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/steampowered/?p=130</guid>
		<description><![CDATA[A little while ago I was working on a project that required data from an external source.  In trying to follow good development practices, I divided the interface code for the external source into a separate ActionScript class.  No problems &#8230; <a href="http://blogs.adobe.com/steampowered/2011/05/dispatching-events-from-an-actionscript-class.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>A little while ago I was working on a project that required data from an external source.  In trying to follow good development practices, I divided the interface code for the external source into a separate ActionScript class.  No problems there, but the external source may not respond to a request immediately.   This means that my ActionScript class is asynchronous, and will need to tell the calling object when the data is ready.</p>
<p>I’ve used Flex long enough to know that when I see anything asynchronous, I will be dealing with the event model.   “No problem.”, says I,  “I’ve used events in MXML components before.  Add a meta-data tag, dispatch the event using <em>dispatchEvent, </em>and add a listener in the calling object.  Bob’s your uncle, its done.  I can even create a small custom event to be really fancy.  <a href="http://livedocs.adobe.com/flex/3/html/help.html?content=createevents_3.html">The syntax is all in the help files.</a> “</p>
<p>Alas, it was not so easy.   When using MXML components, the <em>dispatchEvent</em> function is a property of the <em>mx.core.UIComponent</em> object, but pure ActionScript classes aren’t derived from the UIComponent and therefore don’t have access to the <em>dispatchEvent</em> function.  So how do I dispatch the event form an ActionScript class?</p>
<p>It took me quite a while to find the answer to this simple question.  If you search the internet, there are tons of examples of using the event dispatcher in MXML components.  There are not that many when it comes to using pure ActionScript classes.  The problem isn’t that its difficult to do, its just hard to find how to do it amongst the thousands of results returned in a search.</p>
<p>So in the interest of spreading the knowledge, here is how to dispatch a custom event from a pure ActionScript class.</p>
<p><a href="http://blogs.adobe.com/steampowered/files/2011/05/CustomDispatcherExample.zip">Source code can be found here.</a></p>
<p>&nbsp;</p>
<h2>The parts list:</h2>
<p>The solution consists for three parts:</p>
<ul>
<li>The ActionScript class.  This is a pure ActionScript object (no MXML) that will perform an asynchronous task.  In this case it will make an external call to get data.</li>
<li>The custom event.  This is a custom build event object that will be thrown by the ActionScript class when the asynchronous task is complete.</li>
<li>The calling object (aka parent).  This is the MXML, class, etc.  that will use the ActionScript class to get data.</li>
</ul>
<p>The order of operations is quite simple as well:</p>
<ol>
<li>The parent object will add an event listener to watch for the custom event</li>
<li>The parent object will then call a function in the ActionScript class</li>
<li>The ActionScript class’ function will perform an asynchronous task.   This may require the addition of its own event listener to know when the task is complete.</li>
<li>The ActionScript class will dispatch a custom event that includes data from the asynchronous task.</li>
<li>The parent object will get the data from the custom event and do something with it.</li>
</ol>
<p>Here’s a simple diagram that shows what happens:</p>
<p><a href="http://blogs.adobe.com/steampowered/files/2011/05/eventModel.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border-width: 0px;" src="http://blogs.adobe.com/steampowered/files/2011/05/eventModel_thumb.png" border="0" alt="eventModel" width="349" height="336" /></a></p>
<p>&nbsp;</p>
<h2>The code:</h2>
<p>To keep from having to jump around, lets start looking from the bottom up:</p>
<h3>The Custom Event</h3>
<p>I could have easily used the existing Event object, but a custom event allows me a bit more freedom.  I can create my own event types as well as having my own data objects passed back in the event.</p>
<ul>
<li>The class is fairly simple, it extends the <em>flash.events.Event</em> object</li>
<li>There are three types of event that can be returned:
<ul>
<li>EXTERNALDATA_DATAREADY – everything is good and the data is ready to go</li>
<li>EXTERNALDATA_NODATAFOUND – there is no data found</li>
<li>EXTERNALDATA_ERROR – something went wrong</li>
</ul>
</li>
<li>There is an attribute that holds the data called <em>externalData</em>, which uses the ActionScript convention around getters and setters.</li>
<li>The constructor has been modified to include the event type and the data itself.</li>
</ul>
<p>Here is the source code:</p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><strong><span><span style="color: #9900cc;"><span>package</span></span></span></strong><span><span> events</span></span></span><span> </span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span>{</span></span></span><span> </span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">import</span></span></strong></span><span><span> flash.events.Event;</span></span></span><span> </span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span><span> </span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">public</span></span></strong><span> </span><strong><span><span style="color: #9900cc;">class</span></span></strong><span> ExternalDataEvent </span><strong><span><span style="color: #0033ff;">extends</span></span></strong></span><span><span> Event<span> </span>{</span></span></span><span> </span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span><span> </span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">public</span></span></strong><span> </span><strong><span><span style="color: #0033ff;">static</span></span></strong><span> </span><strong><span><span style="color: #0033ff;">const</span></span></strong><span> EXTERNALDATA_DATAREADY:String <span> </span>= </span><strong><span><span style="color: #990000;">&#8216;ExternalDataReady&#8217;</span></span></strong></span><span><span>;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">public</span></span></strong><span> </span><strong><span><span style="color: #0033ff;">static</span></span></strong><span> </span><strong><span><span style="color: #0033ff;">const</span></span></strong><span> EXTERNALDATA_NODATAFOUND:String <span> </span>= </span><strong><span><span style="color: #990000;">&#8216;ExternalDataNoDataFound&#8217;</span></span></strong></span><span><span>;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">public</span></span></strong><span> </span><strong><span><span style="color: #0033ff;">static</span></span></strong><span> </span><strong><span><span style="color: #0033ff;">const</span></span></strong><span> EXTERNALDATA_ERROR:String <span> </span>= </span><strong><span><span style="color: #990000;">&#8216;ExternalDataError&#8217;</span></span></strong></span><span><span>;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">private</span></span></strong><span> </span><strong><span><span style="color: #6699cc;">var</span></span></strong></span><span><span> _externalData:XML;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">public</span></span></strong><span> </span><strong><span><span style="color: #339966;">function</span></span></strong><span> ExternalDataEvent(type:String, exData:XML, bubbles:Boolean=</span><strong><span><span style="color: #0033ff;">false</span></span></strong><span>, cancelable:Boolean=</span><strong><span><span style="color: #0033ff;">false</span></span></strong></span><span><span>)<span> </span>{</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">super</span></span></strong></span><span><span>(type, bubbles, cancelable);</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">this</span></span></strong></span><span><span>.externalData = exData;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>}</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span> </span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">public</span></span></strong><span> </span><strong><span><span style="color: #339966;">function</span></span></strong><span> </span><strong><span><span style="color: #0033ff;">get</span></span></strong></span><span><span> externalData():XML<span> </span>{</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">return</span></span></strong></span><span><span> _externalData;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>}</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span> </span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">public</span></span></strong><span> </span><strong><span><span style="color: #339966;">function</span></span></strong><span> </span><strong><span><span style="color: #0033ff;">set</span></span></strong><span> externalData(value:XML):</span><strong><span><span style="color: #0033ff;">void</span></span></strong></span><span><span><span> </span>{</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>_externalData = value;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>}</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span> </span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>}</span></span></span></p>
<p class="MsoNormal" style="line-height: 13pt; margin: 0in 0in 10pt;"><span style="line-height: 12pt;"><span style="font-family: Courier New;"><span>}</span></span></span></p>
<h3>The ActionScript Class</h3>
<p>The ActionScript class serves as the model for this project.  It is called by the parent object, performs an asynchronous call, and returns the result in an <em>ExternalDataEvent</em> event.</p>
<p>In this case I’m just making a simple HTTP request to load an external XML file, but this could just as easily been an SQL call to a database, a web service request, a LiveCycle Data Services call or any other asynchronous request.</p>
<ul>
<li>The class extends<em> flash.events.EventDispatcher. </em>This is very important.   Because the ActionScript class is not an MXML object, it does not have access to the <em>mx.core.UIComponent</em> object.  By extending the EventDispatcher class we can now dispatch our custom event using the <em>dispatchEvent</em> function.</li>
<li>The class has one public method <em>readData</em></li>
<li>Since the data is loaded from an <em>HTTPService</em> (an asynchronous event), we need a listener for the returned data.  This is done by the <em>loadData</em> function.</li>
<li>The <em>loadData</em> function fires our custom event.  Which event depends on the data.  During the call the type and data are set into the event itself</li>
<li>There is also an error function, <em>fault</em>, as a basic error trap.</li>
</ul>
<p>Here is the source code:</p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><strong><span><span style="color: #9900cc;"><span>package</span></span></span></strong><span><span> model</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span>{</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">import</span></span></strong></span><span><span> events.ExternalDataEvent;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">import</span></span></strong></span><span><span> flash.events.EventDispatcher;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">import</span></span></strong></span><span><span> flash.events.Event;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">import</span></span></strong></span><span><span> mx.rpc.events.FaultEvent;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">import</span></span></strong></span><span><span> mx.rpc.events.ResultEvent;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">import</span></span></strong></span><span><span> mx.rpc.http.mxml.HTTPService;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">public</span></span></strong><span> </span><strong><span><span style="color: #9900cc;">class</span></span></strong><span> ExternalData<span> </span></span><strong><span><span style="color: #0033ff;">extends</span></span></strong></span><span><span> EventDispatcher<span> </span>{</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">private</span></span></strong><span> </span><strong><span><span style="color: #6699cc;">var</span></span></strong><span> HttpService:HTTPService = </span><strong><span><span style="color: #0033ff;">new</span></span></strong></span><span><span> HTTPService();</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">private</span></span></strong><span> </span><strong><span><span style="color: #6699cc;">var</span></span></strong><span> xmlURL:String = </span><strong><span><span style="color: #0033ff;">new</span></span></strong></span><span><span> String();</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">public</span></span></strong><span> </span><strong><span><span style="color: #339966;">function</span></span></strong><span> readData(dataUrl:String):</span><strong><span><span style="color: #0033ff;">void</span></span></strong></span><span><span>{</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">this</span></span></strong></span><span><span>.load(dataUrl);</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>}</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">private</span></span></strong><span> </span><strong><span><span style="color: #339966;">function</span></span></strong><span> load(dataUrl:String):</span><strong><span><span style="color: #0033ff;">void</span></span></strong></span><span><span>{</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>xmlURL = dataUrl;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span><span>HttpService.resultFormat = </span></span><span><strong><span><span style="color: #990000;">&#8220;e4x&#8221;</span></span></strong></span><span><span>;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>HttpService.addEventListener(ResultEvent.RESULT,loadData);</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>HttpService.addEventListener(FaultEvent.FAULT,fault);</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>HttpService.url = xmlURL;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>HttpService.send();</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>}</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">private</span></span></strong><span> </span><strong><span><span style="color: #339966;">function</span></span></strong><span> loadData(event:ResultEvent):</span><strong><span><span style="color: #0033ff;">void</span></span></strong></span><span><span>{</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">if</span></span></strong><span> (event.result !=<span> </span></span><strong><span><span style="color: #0033ff;">null</span></span></strong></span><span><span>){</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span><span>dispatchEvent (</span></span><span><strong><span><span style="color: #0033ff;">new</span></span></strong><span> ExternalDataEvent (ExternalDataEvent.EXTERNALDATA_DATAREADY,event.result </span><strong><span><span style="color: #0033ff;">as</span></span></strong></span><span><span> XML));</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span><span>}</span></span><span><strong><span><span style="color: #0033ff;">else</span></span></strong></span><span><span> {</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span><span>dispatchEvent (</span></span><span><strong><span><span style="color: #0033ff;">new</span></span></strong><span> ExternalDataEvent (ExternalDataEvent.EXTERNALDATA_NODATAFOUND,</span><strong><span><span style="color: #0033ff;">null</span></span></strong></span><span><span>));</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>}</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>}</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">private</span></span></strong><span> </span><strong><span><span style="color: #339966;">function</span></span></strong><span> fault(event:FaultEvent):</span><strong><span><span style="color: #0033ff;">void</span></span></strong></span><span><span>{</span><span><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #cc6666;">trace</span></span></strong><span> (</span><strong><span><span style="color: #990000;">&#8220;ERROR: Problem loading XML data.<span> </span>Stack Trace follows:&#8221;</span></span></strong></span><span><span>);</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #cc6666;">trace</span></span></strong></span><span><span>(event.message);</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span><span>dispatchEvent (</span></span><span><strong><span><span style="color: #0033ff;">new</span></span></strong><span> ExternalDataEvent (ExternalDataEvent.EXTERNALDATA_ERROR,</span><strong><span><span style="color: #0033ff;">null</span></span></strong></span><span><span>));</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>}</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>}</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: 13pt; margin: 0in 0in 10pt;"><span style="line-height: 12pt;"><span style="font-family: Courier New;"><span>}</span></span></span></p>
<p>&nbsp;</p>
<h3>The Parent Object</h3>
<p>Finally we have the parent object.  In this case I built a simple MXML application that will call the ActionScript class and get the returned data from the custom event.</p>
<ul>
<li>The application consists of a button and a text area.  When the button is clicked a click handler function is fired and the retrieved data is displayed in the text area.</li>
<li>The click handler adds three listeners.  One for each type of event that can come from the custom event object.</li>
<li>The click handler also sets some data and calls the public method in our ActionScript class.</li>
<li>The event listeners will be triggered by the ActionScript when it dispatches the custom event (with data).</li>
<li>The event listeners set the text of the text area field</li>
</ul>
<p>Here is the source code:</p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span>&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;utf-8&#8243;?&gt;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span style="color: #0000ff;"><span>&lt;s:Application</span></span></span><span><span> xmlns:fx=&#8221;</span><span><span style="color: #990000;">http://ns.adobe.com/mxml/2009</span></span></span><span><span>&#8221; </span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span><span><span> </span>xmlns:s=&#8221;</span></span><span><span><span style="color: #990000;">library://ns.adobe.com/flex/spark</span></span></span><span><span>&#8221; </span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span><span><span> </span>xmlns:mx=&#8221;</span></span><span><span><span style="color: #990000;">library://ns.adobe.com/flex/mx</span></span><span>&#8221; minWidth=&#8221;</span><span><span style="color: #990000;">955</span></span><span>&#8221; minHeight=&#8221;</span><span><span style="color: #990000;">600</span></span><span>&#8221; xmlns:model=&#8221;</span><span><span style="color: #990000;">model.*</span></span><span>&#8220;</span></span><span><span style="color: #006633;">&gt;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><span style="color: #006633;">&lt;fx:Declarations&gt;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><span><span style="color: #0000ff;">&lt;model:ExternalData</span></span><span> id=&#8221;</span><span><span style="color: #990000;">externalData</span></span><span>&#8220;</span></span><span><span style="color: #0000ff;">/&gt;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><span style="color: #006633;">&lt;/fx:Declarations&gt;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span> </span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><span style="color: #006633;">&lt;fx:Script&gt;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>&lt;![CDATA[</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">import</span></span></strong></span><span><span> events.ExternalDataEvent;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">import</span></span></strong></span><span><span> model.ExternalData;</span><span><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span style="text-decoration: underline;"><span><span style="color: #0000fe;">protected</span></span></span></strong><span> </span><strong><span><span style="color: #339966;">function</span></span></strong><span> getDataBtn_clickHandler(event:MouseEvent):</span><strong><span><span style="color: #0033ff;">void</span></span></strong></span><span><span><span> </span>{<span> </span></span><span><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span><span> </span>externalData.addEventListener(ExternalDataEvent.EXTERNALDATA_DATAREADY,dataReady);</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span><span> </span>externalData.addEventListener(ExternalDataEvent.EXTERNALDATA_NODATAFOUND,noDataFound);</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span><span> </span>externalData.addEventListener(ExternalDataEvent.EXTERNALDATA_ERROR,fault);</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #6699cc;">var</span></span></strong><span> dataURL:String = </span><strong><span><span style="color: #990000;">"\\assets\\testData.xml"</span></span></strong></span><span><span>;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>externalData.readData(dataURL);</span><span><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>}</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">private</span></span></strong><span> </span><strong><span><span style="color: #339966;">function</span></span></strong><span> dataReady(event:ExternalDataEvent):</span><strong><span><span style="color: #0033ff;">void</span></span></strong></span><span><span>{</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>dataResults.text = event.externalData.toXMLString();</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>}</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">private</span></span></strong><span> </span><strong><span><span style="color: #339966;">function</span></span></strong><span> noDataFound(event:ExternalDataEvent):</span><strong><span><span style="color: #0033ff;">void</span></span></strong></span><span><span>{</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span><span>dataResults.text = </span></span><span><strong><span><span style="color: #990000;">"No Data Found"</span></span></strong></span><span><span>;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>}</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><strong><span><span style="color: #0033ff;">private</span></span></strong><span> </span><strong><span><span style="color: #339966;">function</span></span></strong><span> fault(event:ExternalDataEvent):</span><strong><span><span style="color: #0033ff;">void</span></span></strong></span><span><span>{</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span><span>dataResults.text = </span></span><span><strong><span><span style="color: #990000;">"Data Fault"</span></span></strong></span><span><span>;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>}</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span><span> </span></span><span>]]&gt;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><span style="color: #006633;">&lt;/fx:Script&gt;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><span><span style="color: #0000ff;">&lt;s:Button</span></span><span> id=&#8221;</span><span><span style="color: #990000;">getDataBtn</span></span><span>&#8221; x=&#8221;</span><span><span style="color: #990000;">31</span></span><span>&#8221; y=&#8221;</span><span><span style="color: #990000;">40</span></span><span>&#8221; label=&#8221;</span><span><span style="color: #990000;">Get Data</span></span><span>&#8221; click=&#8221;getDataBtn_clickHandler(event)&#8221;</span></span><span><span style="color: #0000ff;">/&gt;</span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span style="font-family: Courier New;"><span><span><span> </span></span></span><span><span><span style="color: #0000ff;">&lt;s:TextArea</span></span><span> id=&#8221;</span><span><span style="color: #990000;">dataResults</span></span><span>&#8221; x=&#8221;</span><span><span style="color: #990000;">88</span></span><span>&#8221; y=&#8221;</span><span><span style="color: #990000;">86</span></span><span>&#8220;</span></span><span><span style="color: #0000ff;">/&gt;</span></span></span><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span><span style="font-family: Courier New;"><span> </span></span></span></span></p>
<p class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"><span><span style="font-family: Courier New;"><span style="color: #0000ff;">&lt;/s:Application&gt;</span></span></span></p>
<h2>Results</h2>
<p>When the user clicks on the Get Data button the ActionScript class is called.  Data is loaded and the custom event is dispatched.  The parent application is watching for the custom event and it populates the text area with the data from that event.</p>
<p>If all goes well, here’s what you should see once you click on the button:</p>
<p><a href="http://blogs.adobe.com/steampowered/files/2011/05/image.png"><img style="margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; border: 0px;" src="http://blogs.adobe.com/steampowered/files/2011/05/image_thumb.png" border="0" alt="image" width="230" height="244" /></a></p>
<p>&nbsp;</p>
<p>Like I said earlier, its not terribly difficult.  At least its no more difficult than doing custom events using MXML components.   There just doesn’t seem to be too many sample using pure ActionScript classes rather than visual based components.</p>
<p><a href="http://blogs.adobe.com/steampowered/files/2011/05/CustomDispatcherExample.zip">Source code can be found here.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/steampowered/2011/05/dispatching-events-from-an-actionscript-class.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mosaic 9.5 Content Authorization</title>
		<link>http://blogs.adobe.com/steampowered/2011/04/mosaic-9-5-content-authorization.html</link>
		<comments>http://blogs.adobe.com/steampowered/2011/04/mosaic-9-5-content-authorization.html#comments</comments>
		<pubDate>Thu, 21 Apr 2011 15:25:28 +0000</pubDate>
		<dc:creator>Mike Hodgson</dc:creator>
				<category><![CDATA[Developing and Coding]]></category>
		<category><![CDATA[Product Information]]></category>
		<category><![CDATA[Authorization]]></category>
		<category><![CDATA[Mosaic]]></category>
		<category><![CDATA[Mosaic 9.5]]></category>
		<category><![CDATA[Permissions]]></category>
		<category><![CDATA[Roles]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/steampowered/?p=119</guid>
		<description><![CDATA[Mosaic 9.5 has allows control of content based on authorization rules stored in a policy file.  This means we can control access to an application, catalog, tile or other resource by setting permissions in the policy file.  We can also &#8230; <a href="http://blogs.adobe.com/steampowered/2011/04/mosaic-9-5-content-authorization.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Mosaic 9.5 has allows control of content based on authorization rules stored in a policy file.  This means we can control access to an application, catalog, tile or other resource by setting permissions in the policy file.  We can also combine the permissions in different ways to control the user experience.</p>
<p>This is a very powerful feature that allows the developer or administrator to control resource access at a very fine grained level.  It also can be an incredibly maddening feature when it is not configured properly.  In this post I’ll try to demystify some of the magic behind authorization.  Hopefully this will make your configuration a bit less stressful.</p>
<p>The rules for the authorization of Mosaic content is stored in a <em>policy file</em> which is deployed to Mosaic as you would other resources.  The application and catalog descriptors will have a Policy Reference  that indicates what policy file(s) contain the rules for the resource.  The policy reference is optional, and if it is absent it means that there are no specific rules for that resource. There may be more than one policy file deployed to your server.</p>
<p>The policy file uses the <a href="http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xacml">OASIS eXtensible Access Control Markup Language (XACML)</a> notation to define the authorization rules for each resource.  This allows you to set up some incredibly complex rules for authorization, but it also allows you to get a little too creative with the rules.  Its like juggling chainsaws.  Its really cool when it works, but if something goes wrong there will be a big mess to clean up.</p>
<h2>The rules of authorization:</h2>
<p>These are some general rules of thumb that will help you keep the authorization functionality from driving you crazy:</p>
<ol>
<li><strong>Mosaic evaluates the authorization at runtime.</strong><br />
When a user accesses an application, Mosaic reads the application descriptor and assembles the application before sending it to the client.  While this allows you to update rules with out recompiling code, it also means that large, complex policy files can cause performance issues.</li>
<li><strong>The evaluation of permissions for each resource is <em>independent </em>of that for other resources.</strong><br />
When Mosaic determines that a resource is needed, it checks the policy file to see if the user has access (assuming there is a policy reference).  Then the next resource is similarly checked.  Mosaic  does not maintain state information between the calls, so  each resource  request is judged on its own merits.  For example, say a tile is used by two different applications. The tile  rules are evaluated separately from the evaluation of the applications.  In other words; If you can read a tile, you can read that tile regardless of what application it is in.</li>
<li><strong>If a resource is inside of another resource, you need access to the parent resource as well.</strong><br />
Although each resource is evaluated on its own, for practical purposes, there is a evaluation order.  You can consider the evaluation order as application, catalog, view template, panel template and tile (or other catalog resource) and that these can be treated as an AND operation.<br />
What that means is that if you have access to the tiles and not access to the app, you won’t see anything.  Although the tile rules may say you have read access, the tiles have no container into which they can be put.<br />
For example; to see a tile the user must have access to the application AND the catalog AND the tile (1&amp;1&amp;1=1).  If any of these are denied, you will not see the tile.</li>
</ol>
<p>In addition, there are two corollaries to the rules:</p>
<ol>
<li>What happens if there is no policy?<br />
This can happen if the resource (application, catalog, tile, etc.) has no policy file reference.  Since there is no rule, Mosaic assumes access is granted.</li>
<li>What happens if there is a policy, but no rule applies?<br />
This can happen if there is no specific rule in the policy that applies to the resource for that user.  According to the XACML standard, this results in an <em>indeterminate</em> result.  In this case Mosaic falls back to the overall Mosaic authorization setting (also known as the base setting). This is set in the <em>mosaic-context.xml</em> file using the <em>denyWhenIndeterminate</em> property.  If the value is set to <em>true</em> then any indeterminate requests will be denied.<br />
One thing to watch for is an error in your XACML policy file.  If there is a mistake or typo that is still legal XACML, an indeterminate state can be returned.  For example, if you make a mistake in an attribute entry then the rule may not execute and an indeterminate result will be returned.  If the <em>denyWhenIndeterminate</em> property is set then no user will be able to access the resource.<br />
For these reasons I recommend adding a “catch all” rule that will apply when no others do.  It will make debugging your policy file much easier.</li>
</ol>
<h2>An Example</h2>
<p>Lets take a look at a simple sample to see how this works. <a href="http://blogs.adobe.com/steampowered/files/2011/04/MosaicAuthorization.zip"> The source for this example can be downloaded here</a>.</p>
<p>The test consists of the following:</p>
<p class="MsoListParagraphCxSpFirst" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>Two user roles were added to Mosaic.<span> </span>Each role has one unique user:</p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 1in;"><span><span><span style="font-family: Courier New;">o</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>&lt;security:user name=&#8221;r1&#8243; password=&#8221;password&#8221; authorities=&#8221;ROLE_MOSAIC_R1&#8243;/&gt;</p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 1in;"><span><span><span style="font-family: Courier New;">o</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span><span> </span>&lt;security:user name=&#8221;r2&#8243; password=&#8221;password&#8221; authorities=&#8221;ROLE_MOSAIC_R2&#8243;/&gt;</p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>Two applications – App1 and App2</p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>One catalog – AppCatalog</p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>Two tiles – Tile1 and Tile2</p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>AppCatalog has entries for Tile1 and Tile2</p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>App1 uses Tile1 and Tile2 from the AppCatalog</p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>App2 uses Tile1 and Tile2 from the AppCatalog</p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>There is one policy file – <span style="line-height: 12pt;"><span style="font-family: Arial;">ControlPolicy</span></span></p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span><span style="line-height: 12pt;"><span style="font-family: Arial;"><span>App1 and App2 contain a reference to </span><span><span>ControlPolicy</span></span></span></span></p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span><span style="line-height: 12pt;"><span style="font-family: Arial;"><span>AppCatalog contains a reference to <span>ControlPolicy</span> at its root</span></span></span></p>
<p class="MsoListParagraphCxSpLast" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 10pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span><span style="line-height: 12pt;"><span style="font-family: Arial;"><span>The Tile1 and Tile2 entries in the AppCatalog each contain a reference to </span><span><span>ControlPolicy</span></span></span></span></p>
<p class="MsoNormal" style="line-height: 13pt; margin: 0in 0in 10pt;">When the applications are accessed using the owner’s account (a super user with all access granted) they look like the following:</p>
<p>App1 with no authorization rules:</p>
<p><a href="http://blogs.adobe.com/steampowered/files/2011/04/image.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border: 0px;" src="http://blogs.adobe.com/steampowered/files/2011/04/image_thumb.png" border="0" alt="image" width="409" height="183" /></a></p>
<p>&nbsp;</p>
<p>App2 with no authorization rules:</p>
<p><a href="http://blogs.adobe.com/steampowered/files/2011/04/image1.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border: 0px;" src="http://blogs.adobe.com/steampowered/files/2011/04/image_thumb1.png" border="0" alt="image" width="405" height="181" /></a></p>
<p>&nbsp;</p>
<h3>Policy Rules:</h3>
<p class="MsoNormal" style="line-height: 13pt; margin: 0in 0in 10pt;">Rules for R1:</p>
<p class="MsoListParagraphCxSpFirst" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>Read access for App1</p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>Read access for AppCatalog</p>
<p class="MsoListParagraphCxSpLast" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 10pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>Read access for Tile1</p>
<p class="MsoNormal" style="line-height: 13pt; margin: 0in 0in 10pt;">Rules for R2:</p>
<p class="MsoListParagraphCxSpFirst" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>Read access for App2</p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>Read access for AppCatalog</p>
<p class="MsoListParagraphCxSpLast" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 10pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>Read access for Tile2</p>
<p class="MsoNormal" style="line-height: 13pt; margin: 0in 0in 10pt;">Rules for resource owner:</p>
<p class="MsoListParagraph" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 10pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>All actions to all resources</p>
<p class="MsoNormal" style="line-height: 13pt; margin: 0in 0in 10pt;">In addition there is a “catch all” rule to catch anything that does not apply to the above.<span> </span>This rule is set to deny.<span> </span></p>
<h3>Results</h3>
<p class="MsoNormal" style="line-height: 13pt; margin: 0in 0in 10pt;">The following are the results when the two users attempt to access the two applications with the above listed rules:</p>
<p class="MsoNormal" style="line-height: 13pt; margin: 0in 0in 10pt;">For user R1:</p>
<p class="MsoListParagraphCxSpFirst" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>When accessing App1, user R1 sees the app and Tile1.<span> </span>He does not see Tile2</p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 1in;"><span><span><span style="font-family: Courier New;">o</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>The user has access to the app, the catalog and Tile1 (1&amp;1&amp;1=1) so he sees Tile1</p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 1in;"><span><span><span style="font-family: Courier New;">o</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>The user has no access to Tile2 (1&amp;1&amp;0=0) so he does not see Tile2</p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 1in;"><a href="http://blogs.adobe.com/steampowered/files/2011/04/image2.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border: 0px;" src="http://blogs.adobe.com/steampowered/files/2011/04/image_thumb2.png" border="0" alt="image" width="422" height="189" /></a></p>
<p class="MsoListParagraphCxSpMiddle" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>When accessing App2, user R1 is denied access.</p>
<p class="MsoListParagraphCxSpLast" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 10pt 1in;"><span><span><span style="font-family: Courier New;">o</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>The user has no access to the app, but does have access to the catalog and Tile1.<span> </span>Since he can’t see the app, access to the catalog and tile are not relevant (0&amp;1&amp;0=0)</p>
<p class="MsoListParagraphCxSpLast" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 10pt 1in;"><a href="http://blogs.adobe.com/steampowered/files/2011/04/image3.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border: 0px;" src="http://blogs.adobe.com/steampowered/files/2011/04/image_thumb3.png" border="0" alt="image" width="443" height="198" /></a></p>
<p>For user R2:</p>
<p class="MsoListParagraphCxSpFirst" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>When accessing App1, user R1 is denied access</p>
<p class="MsoListParagraphCxSpFirst" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 0pt 0.5in;"><a href="http://blogs.adobe.com/steampowered/files/2011/04/image4.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border: 0px;" src="http://blogs.adobe.com/steampowered/files/2011/04/image_thumb4.png" border="0" alt="image" width="484" height="216" /></a></p>
<p class="MsoListParagraphCxSpLast" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 10pt 0.5in;"><span><span><span style="font-family: Symbol;">·</span><span style="line-height: normal;"><span style="font-family: Times New Roman;"><span> </span></span></span></span></span>When accessing App2, user R2 sees only Tile2.<span> </span>He does not see Tile1</p>
<p class="MsoListParagraphCxSpLast" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 10pt 0.5in;"><a href="http://blogs.adobe.com/steampowered/files/2011/04/image5.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border: 0px;" src="http://blogs.adobe.com/steampowered/files/2011/04/image_thumb5.png" border="0" alt="image" width="477" height="213" /></a></p>
<p class="MsoListParagraphCxSpLast" style="line-height: 13pt; text-indent: -0.25in; margin: 0in 0in 10pt 0.5in;">&nbsp;</p>
<h2>Compound Rules</h2>
<p>What happens if you want to do more complex rules on combinations of resources?  As I said earlier, Mosaic requests authorization on individual resources and does not pass the state information during the request.  If you want a combo – say only show Tile 2 if Tile 1 is present – can you do it?  You can, but you need to be a bit creative.</p>
<p>You need to find a way to combine the two tiles into a single resource on which Mosaic can check the authorization.  Fortunately, this can be easily done using view and panel templates.   In the catalog you can combine the tiles you need into a single view/panel.  The application will reference the view/panel template and not the tiles individually.  The policy file will include a resource entry for the view/panel as well as the tiles, catalog and application.</p>
<p>Of course the rules must be setup so the user has access to the tiles as well as the view/panel.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/steampowered/2011/04/mosaic-9-5-content-authorization.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Updating Mosaic 9.5 Tooling</title>
		<link>http://blogs.adobe.com/steampowered/2011/04/updating-mosaic-9-5-tooling.html</link>
		<comments>http://blogs.adobe.com/steampowered/2011/04/updating-mosaic-9-5-tooling.html#comments</comments>
		<pubDate>Wed, 13 Apr 2011 18:27:04 +0000</pubDate>
		<dc:creator>Mike Hodgson</dc:creator>
				<category><![CDATA[Developing and Coding]]></category>
		<category><![CDATA[Product Information]]></category>
		<category><![CDATA[LCM Plugin]]></category>
		<category><![CDATA[Mosaic 9.5]]></category>
		<category><![CDATA[Tooling]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/steampowered/?p=104</guid>
		<description><![CDATA[If you are developing Mosaic applications or tiles then you have probably looked at the LCM plugin for Flash Builder 4*.&#160; This plugin was developed for use with Mosaic 9.0, but what if you are developing on Mosaic 9.5.0.1 or &#8230; <a href="http://blogs.adobe.com/steampowered/2011/04/updating-mosaic-9-5-tooling.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>If you are developing Mosaic applications or tiles then you have probably looked at the <a href="http://labs.adobe.com/technologies/lcmplugin/">LCM plugin for Flash Builder 4</a>*.&nbsp; This plugin was developed for use with Mosaic 9.0, but what if you are developing on Mosaic 9.5.0.1 or 9.5.0.2?&nbsp;&nbsp; You need to update a coupe of things in the tooling so the SDK and the deployment client are compatible with later versions of Mosaic.&nbsp; </p>
<p>In this discussion the following conventions are used:</p>
<p><i>{fb_install}</i> – refers to the installation location of your FlashBuilder 4.&nbsp; For example:&nbsp; C:\Program Files (x86)\Adobe\Adobe Flash Builder 4</p>
<p><i>{Mosaic_install}</i>&nbsp; &#8211; refers to the installation location of your Mosaic server.&nbsp; For example: C:\Adobe\Mosaic 9.5.0.2</p>
<p><em>{plugin SDK}</em> – refers to the location of the plug in’s version of the Mosaic SDK files.&nbsp; In my case it is:&nbsp; C:\Adobe\Mosaic\Mosaic 9.5.0.1\sdk\com.adobe.livecyle.ria.mosaic\9.5-gm.</p>
<blockquote><p>To&nbsp; Find what the plugin is using for an SDK folder:</p>
</blockquote>
<ul>
<ul>
<li>Launch FlashBuilder 4</li>
<li>Choose Window –&gt; Preferences</li>
<li>Choose General -&gt; Workspace -&gt; Linked Resources</li>
<li>Look for the MOSAIC_9_5_GM_SDK entry</li>
</ul>
</ul>
<p>&nbsp;</p>
<p><strong>I strongly advise you to backup any files you will change.</strong></p>
<p>1.&nbsp; Update the deployment client:</p>
<ul>
<li>If FlashBuilder 4 is running, stop it.</li>
<li>Locate the deployment client that comes with the plugin and rename it so it will no longer be referenced:</li>
<ul>
<li>Go to:&nbsp; <i>{fb_install}</i> \configuration\org.eclipse.osgi\bundles\116\1\.cp\lib</li>
<li>Find the mosaic-ant-tasks.jar file</li>
<li>Rename it to mosaic-ant-tasks.jar.dontUseMe</li>
</ul>
<li>Find the updated deployment client and copy it to the plugin folder:</li>
<ul>
<li>Copy <i>{Mosaic_install}</i> \bin\mosaicTasks.jar to <i>{fb_install}</i> \configuration\org.eclipse.osgi\bundles\116\1\.cp\lib</li>
<li>Rename the mosaicTasks.jar file to mosaic-ant-tasks.jar</li>
</ul>
</ul>
<p>2.&nbsp; Update the plugin SDK:</p>
<ul>
<li>Back up the plugin SDK:</li>
<ul>
<li>Go to<i> {plugin SDK}</i></li>
<li>Move the css, flex and javascript folders to somewhere safe.&nbsp; Leave the sdkinstall.properties file alone</li>
</ul>
<li>Update the plugin SDK</li>
<ul>
<li>Copy the <i>{Mosaic_install}</i> \sdk\css folder to<i> {plugin SDK}</i></li>
<li>Copy the <i>{Mosaic_install}</i> \sdk\flex folder to <i>{plugin SDK}</i></li>
<li>Copy the <i>{Mosaic_install}</i> \sdk\javascript folder to <i>{plugin SDK}</i></li>
</ul>
<li>Start FlashBuilder 4</li>
<li>Recompile any projects that were created with the old Mosaic SDK:</li>
<ul>
<li>Choose Project –&gt; Clean</li>
<li>Choose Clean all projects</li>
<li>Click OK.&nbsp; Wait while the swfs are regenerated.</li>
</ul>
</ul>
<p>&nbsp;</p>
<p>* Please note:&nbsp; The LCM plugin was developed is provided as unsupported software.&nbsp; Adobe hopes that you find it useful, but as the terms of use state: …PROVIDED BY ADOBE UNDER THESE ADOBE LABS TERMS OF USE &#8220;AS IS&#8221; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,…</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/steampowered/2011/04/updating-mosaic-9-5-tooling.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>View Master</title>
		<link>http://blogs.adobe.com/steampowered/2011/02/view-master.html</link>
		<comments>http://blogs.adobe.com/steampowered/2011/02/view-master.html#comments</comments>
		<pubDate>Thu, 24 Feb 2011 21:35:59 +0000</pubDate>
		<dc:creator>Mike Hodgson</dc:creator>
				<category><![CDATA[Developing and Coding]]></category>
		<category><![CDATA[Product Information]]></category>
		<category><![CDATA[Mosaic]]></category>
		<category><![CDATA[View]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/steampowered/?p=102</guid>
		<description><![CDATA[LiveCycle Mosaic ES2.5 has some very useful features for allowing users to customize their environment.&#160; Some of the most useful revolve around the view object and its related view context.&#160; With a bit of creative programming we can take advantage &#8230; <a href="http://blogs.adobe.com/steampowered/2011/02/view-master.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>LiveCycle Mosaic ES2.5 has some very useful features for allowing users to customize their environment.&nbsp; Some of the most useful revolve around the view object and its related view context.&nbsp; With a bit of creative programming we can take advantage of the view object and allow users to create their own, customized design.
<p>In this post I’ll look at a fairly common request for a customizable Mosaic app and see how it can be done while using many of the view features.
<p><a href="http://blogs.adobe.com/steampowered/files/2011/02/MosaicViewDemos-9.5.zip">The source code used in this post can be found here.</a></p>
<h2>Scenario</h2>
<p>I’ll start with a short description of what we want from the app:</p>
<ol>
<li>An IT Request application with four tiles to begin (more may be added later):
<ul>
<li>Request List – has a list of currently active requests
<li>Request Details – contains details about a single request
<li>Customer Details – contains details about the customer to which the request applies
<li>Customer History – contains information about a customer’s previous requests</li>
</ul>
<li>When a user selects an item from the request list the other tiles will update with relevant request/customer information
<li>User’s can customize their app to include any or all of the tiles.
<li>User’s can open multiple copies of the work space to work on different requests.&nbsp;
<li>User’s can save their customized work space
<li>If a user has a customized work space, then it should come up when they login.
<li>If a user does not have a customized work space then a default will be presented.&nbsp; The default will include the Request List and the Request Details.
<li>When a user’s customized work space is opened then the last request they were working on should be selected</li>
</ol>
<p>Okay, that should do for now. </p>
<h2>The Tiles</h2>
<p>First we need to build the four tiles that make up the bulk of the application.&nbsp; I won’t go too much into the general tile development, but instead I’ll concentrate on the “special” things I need to do to make the other requirements work.</p>
<p>Basically these are small Flex apps that happen to use the Mosaic API.&nbsp; In my case I built them as ModuleTile files since they are all built on the same version of the Flex SDK.&nbsp;&nbsp; Since this is a sample, I’m just going to read the data from a couple of local XML files using an HTTP Service.&nbsp; No need to get too fancy here.</p>
<ul>
<li>The Request List (RequestList.mxml) will be a simple data grid that shows the list of requests from the XML file.&nbsp;
<li>The Request Details (RequestDetails.mxml) is a screen that shows details about a single request.&nbsp; Its pretty much a form.
<li>The Customer Details (CustomerDetails.mxml) is a simple display screen that shows information about a single customer.
<li>The Customer History (CustomerHistory.mxml) is a list of a single customer’s previous requests.</li>
</ul>
<p>The construction of these tiles is pretty strait forward MXML development.</p>
<h2></h2>
<h2>Inter-tile Communication</h2>
<blockquote><p>Requirement: <em>When a user selects an item from the request list the other tiles will update with relevant request/customer information.</em> </p>
</blockquote>
<p>Mosaic has several methods to exchange data between tiles (<a href="http://tv.adobe.com/watch/working-with-adobe-livecycle-es2/livecycle-mosaic-95-inter-tile-communications/">see video for more</a>), but there are a few requirements that lend themselves to using the <em>view context</em> for inter-tile communication: </p>
<ul>
<li><em>User’s can open multiple copies of the work space to work on different requests.</em>&nbsp; -&nbsp; This means that tiles in the same work space need to share data, but they shouldn’t interfere with tiles in another work space.&nbsp; We can equate a work space with a Mosaic view. Then we can read that as the data needs to be exchanged between tiles in the same view and not tiles in another view.&nbsp; Coincidentally, this is exactly how view attribute data works.
<li><em>When a user’s customized work space is opened then the last request they were working on should be selected.</em> – This means that the data the user is looking at needs to be saved and reloaded when the view is opened.&nbsp; Fortunately the view context data is saved when the view is saved.&nbsp; The tile just needs to be built to make use of that data. The one restriction is that the view data must be a primitive type – complex data types cannot be saved. </li>
</ul>
<p>Let’s look at how the use of the view context data attributes are coded to meet these requirements.</p>
<h3>Sending Data</h3>
<p>The Request List tile will be broadcasting data to the other tiles.&nbsp; When a user clicks on an item from the data grid (<font face="Courier New">id=”grid”)</font> two data attributes will be set – the <font face="Courier New">caseNumber</font> and the <font face="Courier New">customerName</font>.&nbsp; These will be picked up by the other tiles.&nbsp; </p>
<p>To send view data to the other tiles in the current view you would use the <font face="Courier New">parentView.context.setAttribute</font> method.&nbsp; The first parameter is the attribute name, the second is its value.&nbsp; Here is the code from the Request List tile:</p>
<blockquote><p><font face="Courier New">private function selectRecord():void{<br />&nbsp;&nbsp;&nbsp; var caseNumber:String = grid.selectedItem.caseNumber;<br />&nbsp;&nbsp;&nbsp; var customerName:String = grid.selectedItem.customer;<br />&nbsp;&nbsp;&nbsp; parentView.context.setAttribute(&#8220;caseNumber&#8221;,caseNumber);<br />&nbsp;&nbsp;&nbsp; parentView.context.setAttribute(&#8220;customerName&#8221;,customerName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />}</font></p>
</blockquote>
<h3>Receiving Data</h3>
<p>The other three tiles need to receive the data and then do something with it.&nbsp; In this case they will get related XML data and put it on the screen. </p>
<p>To meet the requirements the tile must check for the data when it loads (thus meeting the requirement to open the last request).&nbsp; It must also watch for changes to the data so the tile is updated when the user selects a different request.</p>
<p>To get the value of a view data attribute I will use the <font face="Courier New">parentView.context.getAttribute</font> method.&nbsp; The only parameter is the attribute name and the result is the contents of the data.</p>
<p>Mosaic also has a listener that can watch for changes in a view context attribute. The&nbsp; <font face="Courier New">parentView.context.addAttributeWatcher</font> function works using the standard Flex event model in that it will fire a function when the attribute data changes.&nbsp; You can then use the <font face="Courier New">getAttribute</font> function to get the data.
<p>The following code is from the Request Details tile, but the other two tiles use similar techniques for getting the view context data.&nbsp; The <font face="Courier New">init</font> function is called on the <font face="Courier New">creationComplete</font> event of the tile:<br />
<blockquote>
<p><font face="Courier New">import mx.rpc.events.FaultEvent;<br />import mx.rpc.events.ResultEvent;<br />import mx.events.PropertyChangeEvent;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />[Bindable] private var currentRequest:XML;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />[Bindable] private var caseNum:String;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br /> 
<p>private function init():void{&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; parentView.context.addAttributeWatcher(&#8220;caseNumber&#8221;,onChange);&nbsp; //watch for changes to the data<br />&nbsp;&nbsp;&nbsp; onChange();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //check for data on load<br />}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />private function onChange(event:PropertyChangeEvent=null):void{<br />&nbsp;&nbsp;&nbsp; caseNum = parentView.context.getAttribute(&#8220;caseNumber&#8221;);&nbsp;&nbsp; //get the data<br />&nbsp;&nbsp;&nbsp; if (caseNum != null)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //if there is data, then do something with it<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpService.send();<br />}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
</blockquote>
<h2>Adding Tiles to a View</h2>
<blockquote><p>Requirements: <em>User’s can customize their app to include any or all of the tiles<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; User’s can open multiple copies of the work space to work on different requests. </em></p>
</blockquote>
<p>This requirement implies that the application needs a way to allow the user to create a new view and to add available tile to that view as they want.&nbsp; Creating a new view is easy, as Mosaic has a built in button on the view skin to add a new view (the “+” button in the default skin).&nbsp;
<p>Adding tiles to the view takes a bit more effort.&nbsp; Mosaic 9.5 doesn’t have an out of the box way to do this, but it does provide the APIs so it can be coded.&nbsp; I need somewhere to put this code and the user controls.&nbsp; It doesn’t make much sense to put it in any of the four tiles, as the user may not have add that tile to their view.&nbsp; For this example I’ll add another tile called Header (<font face="Courier New">Header.mxml</font>).
<p>I’ll need something to hold a list of the available tiles.&nbsp; To be more flexible, I will also add the catalog name to that list as well.&nbsp; That will allow me to add tiles from other catalogs into the view later on.&nbsp;&nbsp;&nbsp; I created a simple class <font face="Courier New">TileInfo</font> to hold the tile and catalog name for each tile.&nbsp; Then I created an array collection of the <font face="Courier New">TileInfo</font> objects and I populate that array collection when the Header tile is initialized (creation complete):<br />
<blockquote>
<p><font face="Courier New">private function init():void{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; //set the list of tiles (and their catalogs) that a user can add<br />&nbsp;&nbsp;&nbsp; tileCollection.addItem(new TileInfo(&#8220;RequestList&#8221;,&#8221;ViewDemo_Catalog&#8221;));<br />&nbsp;&nbsp;&nbsp; tileMenuCollection.addItem(&#8220;Request List&#8221;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; tileCollection.addItem(new TileInfo(&#8220;RequestDetails&#8221;,&#8221;ViewDemo_Catalog&#8221;));<br />&nbsp;&nbsp;&nbsp; tileMenuCollection.addItem(&#8220;Request Details&#8221; );<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; tileCollection.addItem(new TileInfo(&#8220;CustomerDetails&#8221;,&#8221;ViewDemo_Catalog&#8221;));<br />&nbsp;&nbsp;&nbsp; tileMenuCollection.addItem(&#8220;Customer Details&#8221;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; tileCollection.addItem(new TileInfo( &#8220;CustomerHistory&#8221;,&#8221;ViewDemo_Catalog&#8221;));<br />&nbsp;&nbsp;&nbsp; tileMenuCollection.addItem(&#8220;Customer History&#8221;)</font></p>
<p><font face="Courier New">}</font>&nbsp;&nbsp;&nbsp; </p>
</blockquote>
<p>One of Header’s jobs will be to have a control that a user can use to add tiles.&nbsp; I used a simple drop down (bound to the array collection) with the tile names and a button for the user to add the selected tile.
<p><a href="http://blogs.adobe.com/steampowered/files/2011/02/headerControls.png"><img style="border-right-width: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px;border-bottom-width: 0px;border-left-width: 0px;padding-top: 0px" border="0" alt="headerControls" src="http://blogs.adobe.com/steampowered/files/2011/02/headerControls_thumb.png" width="244" height="54"></a>
<p>When the user clicks on the <em>Add Tile</em> button a function executes that will add the tile.&nbsp; When the function fires the code must first do the following:
<ol>
<li>Locate the proper catalog
<li>Locate the proper tile in the catalog
<li>Find the view and panel that the user is looking at
<li>Add the tile to the view</li>
</ol>
<p>As part of step 3 we should make sure that there is both a view and panel into which we can put the tile.&nbsp; If either of these are missing, we can pull a pre-configured one out of the catalog.&nbsp; By creating a pre-configured view and panel template, the layout can be defined ahead of time.&nbsp; This will save a bit of coding.&nbsp; In this case I created a view template called addView and a panel template called addPanel in the catalog. </p>
<p>The button handler in the Header tile looks like:<br />
<blockquote>
<p><font face="Courier New">protected function addTile_clickHandler(event:MouseEvent):void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (tileDropDown.selectedIndex != -1){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var tileInfo:TileInfo = tileCollection.getItemAt(tileDropDown.selectedIndex) as TileInfo ;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //get the tile<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var cat:ICatalog = mosaicApp.getCatalog(tileInfo.catalogNm);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var tileToAdd:ITile = cat.getTile(tileInfo.tileNm);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var view:IView = this.currentView();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var panel:IPanel = this.currentPanel(view);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; panel.addTile(tileToAdd);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></p>
</blockquote>
<p>This calls two functions to find (or add) the current view (<font face="Courier New">currentView</font>) and panel (<font face="Courier New">currentPanel</font>).&nbsp; To determine if a view or panel is the one that the user is using, I check each view/panel for the <font face="Courier New">displayed</font> flag (true means that it is the current one).
<p>The following is the function for determining the current view.&nbsp; The panel function is similar (you can see it in the source code).<br />
<blockquote>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * find the current view.&nbsp; If not found, then load one from the catalog<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; **/ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected function currentView():IView{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var currentView:IView;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //find the current view by looking at the displayed flag in each view<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var viewArray:Array = mosaicApp.views;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for each (var searchView:IView in viewArray){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (searchView.displayed){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //found view<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentView = searchView;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //not found, so go into the catalog and get a default view<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (currentView == null){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var catalog:ICatalog = mosaicApp.getCatalog(&#8220;ViewDemo_Catalog&#8221;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentView = catalog.getView(&#8220;addView&#8221;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mosaicApp.addView(currentView);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentView.display();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return currentView;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
</blockquote>
<h2>Saving and Loading Views</h2>
<blockquote><p>Requirements:&nbsp;&nbsp; <em>User’s can save their customized work space <br /></em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>If a user has a customized work space, then it should come up when they login.</em>&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>If a user does not have a customized work space then a default will be presented.&nbsp; The default will include the Request List and the Request Details.</em> </p>
</blockquote>
<p>The view skin has a control that allows users to save a view at any time:&nbsp; <a href="http://blogs.adobe.com/steampowered/files/2011/02/clip_image002.gif"><img style="border-right-width: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px;border-bottom-width: 0px;border-left-width: 0px;padding-top: 0px" border="0" alt="clip_image002" src="http://blogs.adobe.com/steampowered/files/2011/02/clip_image002_thumb.gif" width="43" height="36"></a>. Views can also be saved using the IView.save API.&nbsp; Views are saved on the server and are tagged to the user’s account.&nbsp; In this case I’ll let the user save the view using the built in controls.
<p>Views can be loaded into an application either by using the organizer (added to the application’s xml file using the <a href="http://help.adobe.com/en_US/LiveCycleMosaic/9.0/xmlschema/view_xsd~e~Organizer.html">organizer element</a>), or by using the API.&nbsp; The organizer is an element added to the application’s xml definition.&nbsp; It shows a list of the user’s saved Views and allows a user to add the view to the application at any time.
<p>The requirement, however, state that the app should load the user’s view and if that does not exist, load the default view.&nbsp;&nbsp; This will require loading the correct view using the API.&nbsp; To add a view using the API you first have to find the view in the <font face="Courier New">mosaicApp.userViews</font> array, then add it to the application using the <font face="Courier New">mosaicApp.addView</font> method.&nbsp;&nbsp; I could put the default view, with its panels and tiles, directly into the application’s XML file.&nbsp; The problem with that is the default view will <i>always</i> load because Mosaic loads the application contents when the user accesses the app.&nbsp;&nbsp;&nbsp; There will be no way to intercept it and show the user’s saved view.&nbsp; In this case its better to open the view (default or saved) using the API.&nbsp;
<p>This means that the application’s XML file will not have any of the four tiles.&nbsp; It will have the <strong>Header</strong> tile, which will contain the API calls to load the proper view.&nbsp;
<p>The application xml file looks like:<br />
<blockquote>
<p><font face="Courier New">&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;UTF-8&#8243;?&gt;<br />&lt;app:Application name=&#8221;ITRequests&#8221; label=&#8221;IT Requests&#8221; <br />xmlns:view=&#8221;http://ns.adobe.com/Mosaic/View/1.0/&#8221; <br />xmlns:catalog=&#8221;http://ns.adobe.com/Mosaic/Catalog/1.0/&#8221; <br />xmlns:tile=&#8221;http://ns.adobe.com/Mosaic/Tile/1.0/&#8221; <br />xmlns:crx=&#8221;http://ns.adobe.com/Mosaic/CRXTypes/1.0/&#8221; <br />xmlns:app=&#8221;http://ns.adobe.com/Mosaic/Application/1.0/&#8221; <br />xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221; <br />xsi:schemaLocation=&#8221;http://ns.adobe.com/Mosaic/Application/1.0/ file:///C:/Adobe/Mosaic/Mosaic%209.5.0.1/docs/schemas/application.xsd&#8221;&gt;</font>
<p><font face="Courier New">&nbsp;&nbsp;&nbsp; &lt;crx:Metadata&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;crx:Description&gt;ITRequests&lt;/crx:Description&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/crx:Metadata&gt;<br />&nbsp;&nbsp;&nbsp; &lt;app:Shell name=&#8221;ITRequests&#8221; label=&#8221;IT Requests&#8221;&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;catalog:CatalogReference name=&#8221;cat&#8221; uri=&#8221;ViewDemo_Catalog&#8221;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;view:Organizer visible=&#8221;false&#8221;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tile:TileReference catalog=&#8221;cat&#8221; name=&#8221;Header&#8221; label=&#8221;Header&#8221; width=&#8221;100%&#8221; height=&#8221;80&#8243;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;view:ViewManager width=&#8221;100%&#8221; height=&#8221;100%&#8221;&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/view:ViewManager&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/app:Shell&gt;<br />&lt;/app:Application&gt;</font></p>
</blockquote>
<p>Notice that I did add a <font face="Courier New">ViewManager</font>, this is necessary because Mosaic needs something to control the views that I will add later.
<p>Now I need to add some code to the Header tile so it can load the proper view.&nbsp; I’ll need to check to see if there are any saved views for the user.&nbsp; If there are, then I add them to the application.&nbsp; If not; then I’ll call another function to load the default view.&nbsp;&nbsp;
<p><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * check to see if the user has any saved views.&nbsp; If so <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * bring them up.&nbsp; If not, bring up the default <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected function getUserViews():void{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var userViews:Array = mosaicApp.userViews;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for each (var view:IView in userViews ){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mosaicApp.addView(view);&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; showDefaultBtn.visible = true;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (userViews.length == 0){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; showDefaultView();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; show the default view<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected function showDefaultView():void{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var catalog:ICatalog = mosaicApp.getCatalog(&#8220;ViewDemo_Catalog&#8221;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var defaultView:IView = catalog.getView(&#8220;defaultView&#8221;);&nbsp;&nbsp; //load a view template called defaultView from the catalog<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mosaicApp.addView(defaultView);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; showDefaultBtn.visible = false;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font>
<p>To make sure this happens when the app first gets loaded, I’ll add a call to the <font face="Courier New">getUserViews</font>(); function to the Header’s <font face="Courier New">init</font> function.
<p>I could have easily done this in one function, but I wanted user’s that have a saved view to “reload” the default one.&nbsp; To do that I added a button (<font face="Courier New">showDefaultBtn</font>) that will fire the <font face="Courier New">showDefaultView</font> function.&nbsp; If the default view is there, I want the button to be invisible.<br />
<h2>Conclusion</h2>
<p>By taking advantage of the Mosaic view features – inter-tile communication, view layout saving, view data saving and view related APIs – you can build a highly customizable application.&nbsp; This will allow your users to have the freedom to set the system up the way they want.
<p><a href="http://blogs.adobe.com/steampowered/files/2011/02/MosaicViewDemos-9.5.zip">The source code used in this post can be found here.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/steampowered/2011/02/view-master.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Server Side PDF Flattening*</title>
		<link>http://blogs.adobe.com/steampowered/2011/01/server-side-pdf-flattening.html</link>
		<comments>http://blogs.adobe.com/steampowered/2011/01/server-side-pdf-flattening.html#comments</comments>
		<pubDate>Thu, 20 Jan 2011 15:05:21 +0000</pubDate>
		<dc:creator>Mike Hodgson</dc:creator>
				<category><![CDATA[Developing and Coding]]></category>
		<category><![CDATA[General Knowledge]]></category>
		<category><![CDATA[Product Information]]></category>
		<category><![CDATA[DDX]]></category>
		<category><![CDATA[Flatten PDF]]></category>
		<category><![CDATA[LiveCycle]]></category>
		<category><![CDATA[LiveCycle Assembler]]></category>
		<category><![CDATA[LiveCycle Output]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/steampowered/?p=95</guid>
		<description><![CDATA[This blog entry is based on an internal document I wrote some time ago.&#160; I’ve updated it for the current release of LiveCycle ES2.5 and cleaned it up a bit so it is more accessible to an external audience. *Please &#8230; <a href="http://blogs.adobe.com/steampowered/2011/01/server-side-pdf-flattening.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><em><font size="2">This blog entry is based on an internal document I wrote some time ago.&nbsp; I’ve updated it for the current release of LiveCycle ES2.5 and cleaned it up a bit so it is more accessible to an external audience.</font></em></p>
<p><font size="2">*<em>Please note that the title contains a purposeful anachronism. Although the term “Flattening” has entered the vernacular, most PDFs are not really transformed into a flat PDF. Except in limited special cases, the Form is <b>re-rendered</b> as a flat PDF.</em></font></p>
<p>&nbsp;
<p>There has been much confusion around the ability of LiveCycle ES/ES2/ES2.5 to create flat PDFs from various types of interactive PDF forms. This has been exacerbated by functions added to LiveCycle ES Assembler which includes the ability to remove XFA (NoXFA) and form (NoForm) capabilities from a PDF. Specifically, there have been many questions, rumors and theories as to how flat PDFs can be created with and without LiveCycle ES Output.
<p>Despite the ability of various LC components to create flat documents in certain cases, the most comprehensive application for creating flat PDFs is LiveCycle ES Output. As you will see there are certain circumstances where Output is not required to create a flat PDF.&nbsp; However; these are specific circumstances.&nbsp; The decision to propose a non LC Output solution must be taken carefully with understanding of the limitations that will be imposed being understood by the development team and customer. This will avoid the trap of what worked in a simple proof is not working when the customer proceeds with the actual application.
<p>This post lays out these limitations and provides some guidance as to when Output is required.<br />
<h2>Common Definitions</h2>
<p>The following terms are used throughout this document. You shouldn’t consider these to be tremendously technically accurate, but they will work for the purposes of this discussion.&nbsp; </p>
<p><b>Interactive Form</b> – A form that can be filled in and potentially signed with a definition of the form in XFA and the data stream in XML.
<p><b>Non-interactive Form</b> – This is an interactive form with fields locked. It still has all of the XFA and XML in it, but the fields are all locked to be read-only.
<p><b>Flat PDF</b> – A PDF with no XFA stream and no non-signature elements. Basically there are no fields in the document.&nbsp; It is important to note that a “Flat” PDF may still have some layers, such as the comment layer.&nbsp; In this case the flatness refers to the lack of data fields.
<p><b>Static PDF</b> – A PDF which contains an XFA stream and the form layout does not change. Static forms may be interactive (a user can still fill in fields). If a dynamic XDP is rendered with LiveCycle Forms with the Render At Client option set to “No” then the resulting PDF is no longer dynamic – it is now static and behaves like any other static PDF.
<p><b>Dynamic PDF</b> – Dynamic PDFs allow the layout of the form to be altered either through user interaction or through script. An example is a form that adds subforms based on a user input. If a static XDP is rendered with LiveCycle Forms with the Render At Client option set to “Yes” then the resulting PDF is no longer static – it is now dynamic and behaves like any other dynamic PDF.
<p><b>Acroform</b> – A non-XFA based PDF form, usually created directly in Adobe Acrobat (as opposed to using LiveCycle Designer).
<p><b>Artwork or XFAF</b> – A PDF form created with from a flat PDF document using the “Create an Interactive Form with Fixed Pages” option in designer. For the purpose of this document Artwork PDFs operate the same as static PDFs.<br />
<h2>Different Methods</h2>
<p>There are a variety of ways to create a non-interactive form out of an interactive form using Adobe LiveCycle ES/ES2/ES2.5. The use of these different methods depends on the customer process:
<ul>
<li><b>Assembler</b> – Assembler can invoke a DDX operation that can have either a noXFA or noForms tag. The result of both of these operations is to turn an interactive PDF into a flat PDF</li>
<li><b>DocConverter</b> – DocConverter includes a feature (Convert to PDF/A) that will convert PDFs to a PDF/A format. PDF/A documents are flat PDFs with additional archival restrictions</li>
<li><b>Output</b> – LiveCycle Output includes a transformPDF feature that, amongst other things, can create flat PDFs.</li>
</ul>
<h2>What works and what doesn’t</h2>
<p>The following matrix lists what works (Y) and what does not work (N) when you try to convert interactive PDF documents to flat PDFs.
<p><a href="http://blogs.adobe.com/steampowered/files/2011/01/whatWorks.png"><img style="border-bottom: 0px;border-left: 0px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px" border="0" alt="whatWorks" src="http://blogs.adobe.com/steampowered/files/2011/01/whatWorks_thumb.png" width="442" height="345"></a>
<p>Notes:
<ul>
<li>[2] With LiveCycle ES, if a PDF (XFA or Acroform based) is merged with data using LiveCycle Forms (or Form Data Integration), the resulting document is not fully rendered. If the resulting PDF is processed with Assembler and the NoXFA or NoForms tags are used then the resulting PDF will have no data. The reason the PDF is not re-rendered is to increase server performance. The solution is to use LiveCycle Output to render the flat PDF directly instead of using a combination of Forms and Assembler.&nbsp; I understand that this was changed with LiveCycle ES2, so it should not be a problem if you are using a more recent version of the product.</li>
<li>Artwork based PDFs work in the same way as other static PDFs. </li>
<li>Some developers have attempted to use the toPS operation to convert an interactive PDF into a PostScript file with the intention of converting the PS file back to a flat PDF using LiveCycle Generator. This will not work as toPS only works with flat PDFs.</li>
</ul>
<h2>Explanation</h2>
<p>Dynamic PDFs require regeneration of the layout because they contain dynamic XFA. Only LiveCycle Output ES and LiveCycle Forms ES (Forms can only generate interactive PDFs so is not applicable in this case) include the XFAForm.exe application.&nbsp; XFAForm.exe is called behind the scenes through the use of the LiveCycle services and is used in the layout creation. So any scenario that requires rendering XFA, such as merging data or displaying dynamic XFA, will ultimately require Output to do the rendering. Static XFA is already rendered, so unless there is new data being merged, Output is not required.
<p>AcroForms can be rendered by the Gibson libraries (within the limitations of the Assembler and PDF Generator implementations), and therefore do not require Output.
<p>The key message is that, in general, LiveCycle Output ES is the product for documents of record (flat PDF) from XFA and forms. </p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/steampowered/2011/01/server-side-pdf-flattening.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Customer Experience Management for the Pragmatist</title>
		<link>http://blogs.adobe.com/steampowered/2011/01/customer-experience-management-for-the-pragmatist.html</link>
		<comments>http://blogs.adobe.com/steampowered/2011/01/customer-experience-management-for-the-pragmatist.html#comments</comments>
		<pubDate>Thu, 06 Jan 2011 18:10:45 +0000</pubDate>
		<dc:creator>Mike Hodgson</dc:creator>
				<category><![CDATA[Opinion and Rants]]></category>
		<category><![CDATA[CEM]]></category>
		<category><![CDATA[Customer Experience Management]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/steampowered/?p=79</guid>
		<description><![CDATA[As you may be aware, the term Customer Experience Management (CEM) has become one of the latest buzzwords in the enterprise software industry.  Many large companies have formed CEM groups and a few have even created “C” level positions that are dedicated to improving the customer experience.  Adobe has embraced CEM in a big way (you can see the Experience Delivers blog  or Steven Webster’s blog for just a couple of examples), so I felt I needed to understand more about it.    <a href="http://blogs.adobe.com/steampowered/2011/01/customer-experience-management-for-the-pragmatist.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>As you may be aware, the term Customer Experience Management (CEM) has become one of the latest buzzwords in the enterprise software industry.  Many large companies have formed CEM groups and a few have even created “C” level positions that are dedicated to improving the customer experience.  Adobe has embraced CEM in a big way (you can see the <a href="http://blogs.adobe.com/experiencedelivers/">Experience Delivers</a> blog  or <a href="http://blogs.adobe.com/swebster/">Steven Webster’s blog</a> for just a couple of examples), so I felt I needed to understand more about it.</p>
<p>In my search for answers I came across tons of white papers, research notes, videos and other content on CEM and its related topics (such as Rich Internet Applications (RIA), User Experience (UX), Experience Oriented Architecture (XOA), etc.).  There were web pages that call out “bad” design and praise “good” design.  Some sites had some best practices (although these were mostly based on specific examples).  I found a plethora of other phrases that seemed to float around the subject – customer oriented design, put the customer first, contextual design, etc.</p>
<p>I also spoke with some of Adobe’s CEM proponents.  Unfortunately these conversations tended to bend towards rather philosophical discussions.  One time someone actually said “the Medium is the Message”.    At this point my the part of my brain that performs cognitive reasoning ran down the hallway and hid in a quiet corner.  I can’t help it; <a href="http://en.wikipedia.org/wiki/Marshall_McLuhan">McLuhan</a> has that effect on me.</p>
<p>Nothing really hit home with me.  I might be able to recognize a CEM application if I saw one, but I still couldn’t describe to you why it was CEM.</p>
<p>It started to feel like when I played baseball as a kid.  Both my little league coach and my dad kept telling me to “keep your eye on the ball”.  Repeating the phrase over and over made it essentially meaningless.  One day someone (probably a frustrated first baseman) said something like &#8211; “look, just watch the ball as it leaves my hand.  Keep watching it as it goes through the air and then put your glove in front of it.”  All of a sudden it made sense.  I still suck at baseball, but at least I don’t get beaned as often.</p>
<p>One day, while searching for cheap vacation flights, things started to congeal.  Navigating through several sites that essentially did the same thing, I started to understand what was meant by customer experience.  More importantly I started to get why it was so important.</p>
<p>When you get right down to it, what does CEM mean in a practical sense?  Its simple really – build software that <em>helps</em> the user accomplish their goal.  At the very least it should not actively make the user mad.</p>
<p>Like so many simple statements, that has some rather complex consequences.  For one thing, as a designer/developer you really need to understand what the user is trying to do as well as how they feel confortable doing it.  This includes not only understanding the direct path to the goal, but how to assist them.  Also allow people to get back when they go down a different path.</p>
<p>If I look at my own recent experience with online ticket retailers, there were precious few who designed their applications in this way.  For the most part the sites were designed for people to book flights; but I, for one, wasn’t using it that way.  I was shopping for flights &#8211; changing dates/times, departure location (I’m Canadian, so it sometimes pays to drive to a US airport), airlines, etc.  One site made me re-enter all of the information each time I changed one thing.  Others would only give me one flight choice and would not suggest others.  Some would require me to know things that are industry specific (such as airport codes).  The sites I really appreciated, and therefor spent more time on, made my life easier.</p>
<p>Here are some general things that I observed:</p>
<ul>
<li>Cut down on the clicking
<ul>
<li>If you’re going to require me to read something then just show it to me.  Don’t make me click on a button that brings it up.  If its that important than gimme it.  This really goes to presenting the right information at the right time.</li>
</ul>
</li>
<li>Get on with it! (or where’s the <a href="mailto:“f@*ck">“f@*ck</a> off” button)
<ul>
<li>Of course the flip side is presenting too much information.  If I don’t need it right now, get rid of it.</li>
</ul>
</li>
<li>Just do what I tell you to do
<ul>
<li>Software is a tool.  As developers we often think that the software itself is the most important thing.  We must keep in mind that the user is trying to get something done (like shop for a flight) and the software is just a means to an end.</li>
</ul>
</li>
<li>I don’t care about your process
<ul>
<li>Remember that the user is not concerned with what is going on behind the scenes.  Your product codes, industry regulations, inter-departmental routing, etc. does not matter to the user.  While you do want to tell the user what is going on, they don’t need to know what’s going on in the sausage factory.</li>
</ul>
</li>
<li>Customize when necessary, but but not necessarily customize
<ul>
<li>There is a trend to allow the user to customize every aspect an application.  In some circumstances this is a really nice thing (iGoogle is a prime example), but it has a dark side.  I’ve used too many applications that require lengthy configuration to provide a personalized experience.  I know they theory is that by customizing the interface the user takes ownership, but Its not always necessary or even wanted.  Sometimes I just want to do a quick search and get on with my life (google.com is a prime example).</li>
</ul>
</li>
</ul>
<p>As I said, it all boils down to designing software that helps the user do something.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/steampowered/2011/01/customer-experience-management-for-the-pragmatist.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Mosaic and LiveCycle Data Services</title>
		<link>http://blogs.adobe.com/steampowered/2010/12/mosaic-and-livecycle-data-services.html</link>
		<comments>http://blogs.adobe.com/steampowered/2010/12/mosaic-and-livecycle-data-services.html#comments</comments>
		<pubDate>Tue, 21 Dec 2010 15:15:33 +0000</pubDate>
		<dc:creator>Mike Hodgson</dc:creator>
				<category><![CDATA[Developing and Coding]]></category>
		<category><![CDATA[Product Information]]></category>
		<category><![CDATA[Data Service]]></category>
		<category><![CDATA[LCDS]]></category>
		<category><![CDATA[LiveCycle]]></category>
		<category><![CDATA[Mosaic]]></category>
		<category><![CDATA[Tiles]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/steampowered/?p=73</guid>
		<description><![CDATA[Adobe’s two RIA products – LiveCycle Mosaic and LiveCycle Data Services (LCDS) – go together like peanut butter and jelly.  One provides a framework for intuitive, user focused applications, the other provides efficient access to real time back end data.  Between the two of them they can provide up-to-date data in an engaging user experience. 

There are a couple of different ways to combine the two products, however.  What one you will choose will depend on your particular setup and how your back end data is organized.  So, do you prefer your jelly on top, or on the bottom? <a href="http://blogs.adobe.com/steampowered/2010/12/mosaic-and-livecycle-data-services.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Adobe’s two RIA products – LiveCycle Mosaic and LiveCycle Data Services (LCDS) – go together like peanut butter and jelly.  One provides a framework for intuitive, user focused applications, the other provides efficient access to real time back end data.  Between the two of them they can provide up-to-date data in an engaging user experience.</p>
<p>There are a couple of different ways to combine the two products, however.  What one you will choose will depend on your particular setup and how your back end data is organized.  So, do you prefer your jelly on top, or on the bottom?</p>
<p>In this post I’ll present both methods of Mosaic/LCDS integration using an overly simple example.  Hopefully this will give you some ideas for your projects.</p>
<p>In the end I built a simple Mosaic application that demonstrated both methods.</p>
<p><a href="http://blogs.adobe.com/steampowered/files/2010/12/image.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border-width: 0px;" src="http://blogs.adobe.com/steampowered/files/2010/12/image_thumb.png" border="0" alt="image" width="467" height="290" /></a></p>
<h2>A Simple Service</h2>
<p>For this example, I’m going to create a very simple LCDS RPC service that accesses a Java object.  This is based on the Adobe documentation that can be found at: <a title="http://livedocs.adobe.com/livecycle/8.2/programLC/programmer/lcds/help.html?content=lcoverview_4.html" href="http://livedocs.adobe.com/livecycle/8.2/programLC/programmer/lcds/help.html?content=lcoverview_4.html">http://livedocs.adobe.com/livecycle/8.2/programLC/programmer/lcds/help.html?content=lcoverview_4.html</a></p>
<p>First I created a trivially simple POJO that echoes back a single String:</p>
<pre><span style="color: #4bacc6;">package remoting;
public class EchoService
{
    public String echo(String text) {
        return "Server says: I received '" + text + "' from you";
    }
}</span>
</pre>
<p>Once that was compiled I moved the class file to the  WEB-INF/classes/remoting directory.  Then I added the following entry into the WEB-INF/flex/remoting-config.xml file:</p>
<pre><span style="color: #4bacc6;">&lt;destination id="echoServiceDestination" <strong>channels="my-amf</strong>"&gt;
    &lt;properties&gt;
        <strong>&lt;source&gt;remoting.EchoService&lt;/source&gt;</strong>
    &lt;/properties&gt;
&lt;/destination&gt;</span>
</pre>
<p>The source entry points to my Java class and it uses the existing my-amf channel.</p>
<p>The last thing that I needed to do was to add a crossdomain.xml file to my LCDS server.  This is because my Mosaic server is running on a different box.</p>
<h2>Jelly on top; Calling LCDS directly from a tile</h2>
<p>The first method I’ll show is also the most direct.  This involves making a direct call from the Mosaic tile to the LCDS service. This is a useful method when there is a direct relationship between the tile’s visual elements and the data. What it has in simplicity, it lacks in power.  This method does not lend itself to decoupling the data from the tile.</p>
<p><span style="color: #4bacc6;"><span style="font-family: Courier New;">&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;utf-8&#8243;?&gt;<br />
&lt;mc:Tile xmlns:fx=&#8221;</span><span style="font-family: Courier New;">http://ns.adobe.com/mxml/2009&#8243;</span></span><span style="font-family: Courier New; color: #4bacc6;"><br />
xmlns:s=&#8221;library://ns.adobe.com/flex/spark&#8221;<br />
xmlns:mx=&#8221;library://ns.adobe.com/flex/mx&#8221;<br />
xmlns:mc=&#8221;com.adobe.mosaic.core.*&#8221;<br />
layout=&#8221;absolute&#8221; width=&#8221;100%&#8221; height=&#8221;100%&#8221;<br />
creationComplete=&#8221;init()&#8221;&gt;</span></p>
<p>&lt;fx:Declarations&gt;<br />
&lt;mx:RemoteObject id=&#8221;remoteObject&#8221;<br />
destination=&#8221;echoServiceDestination&#8221;<br />
result=&#8221;resultHandler(event);&#8221;<br />
fault=&#8221;faultHandler(event);&#8221;/&gt;<br />
&lt;/fx:Declarations&gt;<br />
&lt;fx:Script&gt;<br />
&lt;![CDATA[<br />
import mx.collections.ArrayCollection;<br />
import mx.collections.ArrayList;<br />
import mx.messaging.Channel;<br />
import mx.messaging.ChannelSet;<br />
import mx.messaging.channels.AMFChannel;<br />
import mx.messaging.config.ConfigMap;<br />
import mx.messaging.events.*;<br />
import mx.messaging.messages.*;<br />
import mx.rpc.events.FaultEvent;<br />
import mx.rpc.events.ResultEvent;<br />
import mx.utils.ObjectProxy;</p>
<p><span style="color: #4bacc6;"><span style="font-family: Courier New;"><br />
private function init():void{<br />
register();<br />
var cs:ChannelSet = new ChannelSet();<br />
var customChannel:Channel = new AMFChannel("my-amf","</span><span style="font-family: Courier New;">http://myserver/lcds/messagebroker/amf");</span><br />
</span><span style="font-family: Courier New; color: #cccccc;"><span style="color: #4bacc6;"> cs.addChannel(customChannel);<br />
remoteObject.channelSet = cs;<br />
}</span></span></p>
<p>private function register():void{<br />
registerClassAlias("flex.messaging.messages.CommandMessage",CommandMessage);<br />
registerClassAlias("flex.messaging.messages.RemotingMessage",RemotingMessage);<br />
registerClassAlias("flex.messaging.messages.AcknowledgeMessage", AcknowledgeMessage);<br />
registerClassAlias("flex.messaging.messages.ErrorMessage",ErrorMessage);<br />
registerClassAlias("DSC", CommandMessageExt);<br />
registerClassAlias("DSK", AcknowledgeMessageExt);<br />
registerClassAlias("flex.messaging.io.ArrayList", ArrayList);<br />
registerClassAlias("flex.messaging.config.ConfigMap",ConfigMap);<br />
registerClassAlias("flex.messaging.io.ArrayCollection",ArrayCollection);<br />
registerClassAlias("flex.messaging.io.ObjectProxy",ObjectProxy);<br />
registerClassAlias("flex.messaging.messages.HTTPMessage",HTTPRequestMessage);<br />
registerClassAlias("flex.messaging.messages.SOAPMessage",SOAPMessage);<br />
registerClassAlias("flex.messaging.messages.AsyncMessage",AsyncMessage);<br />
registerClassAlias("DSA", AsyncMessageExt);<br />
registerClassAlias("flex.messaging.messages.MessagePerformanceInfo", MessagePerformanceInfo);<br />
}</p>
<p>// Send the message in response to a Button click.<br />
private function echo():void {<br />
var text:String = ti.text;<br />
remoteObject.echo(text);<br />
}</p>
<p>// Handle the recevied message.<br />
private function resultHandler(event:ResultEvent):void {<br />
ta.text += "Server responded: "+ event.result + "\n";<br />
}</p>
<p>// Handle a message fault.<br />
private function faultHandler(event:FaultEvent):void {<br />
ta.text += "Received fault: " + event.fault + "\n";<br />
}<br />
]]&gt;<br />
&lt;/fx:Script&gt;</p>
<p>&lt;s:Label x=&#8221;11&#8243; y=&#8221;5&#8243; text=&#8221;Direct LCDS Call&#8221;/&gt;<br />
&lt;s:TextInput x=&#8221;11&#8243; y=&#8221;24&#8243; id=&#8221;ti&#8221; text=&#8221;Hello World!&#8221;/&gt;<br />
&lt;s:Button x=&#8221;147&#8243; y=&#8221;25&#8243; label=&#8221;Send&#8221; click=&#8221;echo();&#8221;/&gt;<br />
&lt;s:TextArea id=&#8221;ta&#8221; width=&#8221;100%&#8221; height=&#8221;628&#8243; y=&#8221;68&#8243;/&gt;<br />
&lt;/mc:Tile&gt;</p>
<p>Again this is based on the <a href="http://livedocs.adobe.com/livecycle/8.2/programLC/programmer/lcds/help.html?content=lcoverview_4.html">LCDS documentation</a>.  There are some concessions to the Mosaic framework however.  First, an AMF channel needs to be setup, also several classes need to be registered.  I know I’ve registered more than I need, but I will probably expand this tile later on.</p>
<p>As you can see, when the user clicks on the Send button, a function is called that makes use of the remote object.  The remote object then uses the AMF channel to make a LCDS call to the POJO.  The results are then shown on the screen.</p>
<h2>Jelly on bottom; Using a Mosaic service to make the LCDS call</h2>
<p>Another way to make an LCDS call from a Mosaic tile would be to use a Mosaic service as an intermediary.  In this case the tile wouldn’t be aware of the LCDS service at all, any interactions would be made through the Mosaic service.  This is very useful if multiple tiles need to access the same LCDS service as it only needs to be accessed once.  It also allows easy decoupling of the tiles and the data as the Mosaic service can be changed without affecting the inner workings of the tiles.  The draw back is that it does require a bit more coding and more for thought when planning out the Mosaic service.  For more info on creating Mosaic services, see my <a href="https://blogs.adobe.com/steampowered/2010/10/lip-service.html">earlier blog entry</a></p>
<h3>The interface</h3>
<p>Let’s look at the code to do something similar to the simple example.  First the Interface object:</p>
<p><span style="font-family: Courier New; color: #4bacc6;">package com.adobe.etech{</span></p>
<p>public interface IHelloWorld    {<br />
function setEcho(msg:String):void;<br />
function getEcho():String;<br />
function echoReady():Boolean;<br />
function setLoaderURL(url:String):void;<br />
}<br />
}</p>
<p>Since the LCDS call is asynchronous, I needed a getter and setter function to make the request and get the response. I also need a method to determine when the asynchronous call is complete (so I can go get the data). The echoReady function is a bit of a cheat to allow this.  As I mentioned in an <a href="https://blogs.adobe.com/steampowered/2010/11/service-interruptus.html">earlier post</a>, there is no easy way to send a message from the Mosaic service to the tile because the service is not context aware.  You can push the context into the service, but for this example it would be overkill.  So I built a cheap and cheesy Boolean function that I can ping from the tile.</p>
<p>The final function <em>setLoaderURL</em> is very important to the application and requires a bit of explanation.  When I was working on this project, I set everything up as I did with the direct LCDS call.    I kept getting an error that the URL was null.  I knew I had set the URI for the amf channel, so what was the URL it needed?  After discussing it with several of my colleagues I was able to narrow it down to  the fact that the LoaderConfig.mx_internal::_url  object needs to have a URL to a MXML element.  Passing the tile’s loaderInfo.url value to the Mosaic service seems to do the trick.</p>
<h3>The Mosaic Service</h3>
<p>The service implementation is below:</p>
<p><span style="font-family: Courier New; color: #4bacc6;">package com.adobe.etech.impl<br />
{<br />
import com.adobe.etech.IHelloWorld;</span></p>
<p>import flash.display.Sprite;<br />
import flash.net.registerClassAlias;</p>
<p>import mx.collections.ArrayCollection;<br />
import mx.collections.ArrayList;<br />
import mx.core.mx_internal;<br />
import mx.logging.targets.TraceTarget;<br />
import mx.messaging.Channel;<br />
import mx.messaging.ChannelSet;<br />
import mx.messaging.channels.AMFChannel;<br />
import mx.messaging.config.ConfigMap;<br />
import mx.messaging.config.LoaderConfig;<br />
import mx.messaging.events.*;<br />
import mx.messaging.messages.*;<br />
import mx.rpc.events.FaultEvent;<br />
import mx.rpc.events.ResultEvent;<br />
import mx.rpc.remoting.RemoteObject;<br />
import mx.utils.ObjectProxy;</p>
<p><span style="font-family: Courier New; color: #4bacc6;"><br />
public class HelloWorldLCDSService implements IHelloWorld<br />
{</span><span style="color: #4bacc6;"><span style="font-family: Courier New;"><br />
private var remoteObject:RemoteObject;<br />
private var _echoMsg:String = &#8220;&#8221;;<br />
private var _echoComplete:Boolean = false;</span></span></p>
<p>public function HelloWorldLCDSService()    {<br />
register();</p>
<p>var amfChannel:AMFChannel  = new AMFChannel(&#8220;my-amf&#8221;,<span style="font-family: Courier New;"><a href="http://server/lcds/messagebroker/amf">http://server/lcds/messagebroker/amf</a>);</span><br />
<span style="font-family: Courier New; color: #4bacc6;"> amfChannel.requestTimeout = 3;<br />
amfChannel.connectTimeout = 3;<br />
var channelSet:ChannelSet = new ChannelSet();<br />
channelSet.addChannel( amfChannel );</span></p>
<p><span style="font-family: Courier New; color: #4bacc6;"> amfChannel.addEventListener(ChannelFaultEvent.FAULT, handleChannelFault);<br />
amfChannel.addEventListener(ChannelEvent.CONNECT, handleChannelConnect);<br />
amfChannel.addEventListener(ChannelEvent.DISCONNECT, handleChannelDisconnect);</span></p>
<p>remoteObject = new RemoteObject();<br />
remoteObject.destination =&#8221;echoServiceDestination&#8221;;<br />
remoteObject.channelSet = channelSet;</p>
<p>remoteObject.addEventListener(ResultEvent.RESULT,resultHandler);<br />
remoteObject.addEventListener(FaultEvent.FAULT,faultHandler);<br />
}</p>
<p>private function handleChannelFault(e:ChannelFaultEvent):void {<br />
_echoComplete = true;<br />
_echoMsg +=&#8221;Channel Fault&#8221; + &#8220;\n&#8221;<br />
trace(&#8220;Channel Fault&#8221;);<br />
trace(e);<br />
}</p>
<p>private function handleChannelConnect(e:ChannelEvent):void {<br />
_echoComplete = true;<br />
_echoMsg +=&#8221;Channel Connect&#8221; + &#8220;\n&#8221;<br />
trace(&#8220;Channel Connect&#8221;);<br />
trace(e);<br />
}</p>
<p>private function handleChannelDisconnect(e:ChannelEvent):void {<br />
_echoComplete = true;<br />
_echoMsg +=&#8221;Channel Disconnect&#8221; + &#8220;\n&#8221;<br />
trace(&#8220;Channel Disconnect&#8221;);<br />
trace(e);<br />
}</p>
<p><span style="font-family: Courier New; color: #4bacc6;"><br />
public function setEcho(msg:String):void    {<br />
_echoComplete = false;<br />
remoteObject.echo(msg);<br />
}</span></p>
<p>public function getEcho():String{<br />
return _echoMsg;<br />
}</p>
<p>public function echoReady():Boolean{<br />
return _echoComplete;<br />
}</p>
<p>private function register():void{<span style="font-family: Courier New; color: #4bacc6;"><br />
registerClassAlias(&#8220;flex.messaging.messages.CommandMessage&#8221;,CommandMessage);<br />
registerClassAlias(&#8220;flex.messaging.messages.RemotingMessage&#8221;,RemotingMessage);<br />
registerClassAlias(&#8220;flex.messaging.messages.AcknowledgeMessage&#8221;, AcknowledgeMessage);<br />
registerClassAlias(&#8220;flex.messaging.messages.ErrorMessage&#8221;,ErrorMessage);<br />
registerClassAlias(&#8220;DSC&#8221;, CommandMessageExt);<br />
registerClassAlias(&#8220;DSK&#8221;, AcknowledgeMessageExt);<br />
registerClassAlias(&#8220;flex.messaging.io.ArrayList&#8221;, ArrayList);<br />
registerClassAlias(&#8220;flex.messaging.config.ConfigMap&#8221;,ConfigMap);<br />
registerClassAlias(&#8220;flex.messaging.io.ArrayCollection&#8221;,ArrayCollection);<br />
registerClassAlias(&#8220;flex.messaging.io.ObjectProxy&#8221;,ObjectProxy);<br />
registerClassAlias(&#8220;flex.messaging.messages.HTTPMessage&#8221;,HTTPRequestMessage);<br />
registerClassAlias(&#8220;flex.messaging.messages.SOAPMessage&#8221;,SOAPMessage);<br />
registerClassAlias(&#8220;flex.messaging.messages.AsyncMessage&#8221;,AsyncMessage);<br />
registerClassAlias(&#8220;DSA&#8221;, AsyncMessageExt);<br />
registerClassAlias(&#8220;flex.messaging.messages.MessagePerformanceInfo&#8221;, MessagePerformanceInfo);</span></p>
<p><span style="font-family: Courier New;"><span style="color: #4bacc6;"> }</span></span></p>
<p>public function setLoaderURL(<a href="void"><span style="color: #4bacc6;">url:String):void</span></a><span style="color: #4bacc6;">{<br />
LoaderConfig.mx_internal::_url = url;</span></p>
<p><span style="font-family: Courier New; color: #4bacc6;"> }</span></p>
<p>// Handle the recevied message.<br />
private function resultHandler(event:ResultEvent):void {<br />
_echoComplete = true;<br />
_echoMsg += &#8220;Server responded: &#8220;+ event.result + &#8220;\n&#8221;;<br />
}</p>
<p>// Handle a message fault.<br />
private function faultHandler(event:FaultEvent):void {<br />
_echoComplete = true;<br />
_echoMsg += &#8220;Received fault: &#8221; + event.fault + &#8220;\n&#8221;;<br />
}<br />
}<br />
}</p>
<p>This is very similar to the direct LCDS call, except it has getters/setters so the calling tile can go and get the resulting data.   The amf channel listeners are there as a result of me trying to debug the <em>setLoaderURL</em> issue mentioned above.</p>
<h3>The Tile</h3>
<p>The tile that uses the service is quite simple. It uses the IHelloWorld interface to make the call and relies on Mosaic to inject the service instance at runtime (see my <a href="https://blogs.adobe.com/steampowered/2010/10/lip-service.html">previous entry</a> for more on how this works):</p>
<p><span style="color: #4bacc6;"><span style="font-family: Courier New;">&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;utf-8&#8243;?&gt;<br />
&lt;mc:Tile xmlns:fx=&#8221;</span><span style="font-family: Courier New;">http://ns.adobe.com/mxml/2009&#8243;</span></span><span style="font-family: Courier New; color: #4bacc6;"><br />
xmlns:s=&#8221;library://ns.adobe.com/flex/spark&#8221;<br />
xmlns:mx=&#8221;library://ns.adobe.com/flex/mx&#8221;<br />
xmlns:mc=&#8221;com.adobe.mosaic.core.*&#8221;<br />
layout=&#8221;absolute&#8221; width=&#8221;100%&#8221; height=&#8221;100%&#8221;&gt;<br />
&lt;fx:Declarations&gt;<br />
&lt;!&#8211; Place non-visual elements (e.g., services, value objects) here &#8211;&gt;<br />
&lt;/fx:Declarations&gt;</span></p>
<p>&lt;fx:Script&gt;<br />
&lt;![CDATA[<br />
import com.adobe.etech.IHelloWorld;</p>
<p>[Bindable] public var helloService:IHelloWorld;<br />
private var myTimer:Timer = new Timer(1000,1);  //1 second<br />
private var timeoutID:uint;</p>
<p>// Send the message in response to a Button click.<br />
private function echo():void {<br />
var text:String = ti.text;<br />
//remoteObject.echo(text);<br />
helloService.setLoaderURL(this.loaderInfo.url);<br />
helloService.setEcho(text);<br />
if (helloService.echoReady()){<br />
this.getEcho();<br />
}else{<br />
myTimer.addEventListener(TimerEvent.TIMER,checkEcho);<br />
myTimer.start();<br />
}<br />
}</p>
<p>private function checkEcho(event:TimerEvent):void{<br />
if (helloService.echoReady()){<br />
myTimer.stop();<br />
myTimer.removeEventListener(TimerEvent.TIMER,checkEcho);<br />
this.getEcho();<br />
} else{<br />
//try again<br />
myTimer.reset();<br />
myTimer.start();<br />
}<br />
}</p>
<p>private function getEcho():void{<br />
ta.text = helloService.getEcho();<br />
}</p>
<p>]]&gt;<br />
&lt;/fx:Script&gt;</p>
<p>&lt;s:Label x=&#8221;11&#8243; y=&#8221;5&#8243; text=&#8221;LCDS Using Service&#8221; width=&#8221;195&#8243;/&gt;<br />
&lt;s:TextInput x=&#8221;11&#8243; y=&#8221;24&#8243; id=&#8221;ti&#8221; text=&#8221;Hello World!&#8221;/&gt;<br />
&lt;s:Button x=&#8221;147&#8243; y=&#8221;25&#8243; label=&#8221;Send&#8221; click=&#8221;echo();&#8221;/&gt;<br />
&lt;s:TextArea id=&#8221;ta&#8221; width=&#8221;100%&#8221; height=&#8221;628&#8243; y=&#8221;68&#8243;/&gt;<br />
&lt;/mc:Tile&gt;</p>
<p>You may notice that I have a timer that checks to see if the data is returned.  This is because the service has no built in way of sending a message to the tile. The timer was a bit of a cheat and I wouldn’t recommend using this method in production code. Instead I would recommend passing the tile context to the service so it can send a proper Mosaic message (<a href="https://blogs.adobe.com/steampowered/2010/11/service-interruptus.html">see this post for more info</a>)</p>
<h2>Conclusion</h2>
<p>As you can see from this simple example, there are a couple of different options for combining LCDS and Mosaic.  Each has its advantages and weaknesses and it will depend on your situation as to which one to use:</p>
<p>Direct LCDS Call:</p>
<blockquote><p>Pros:</p></blockquote>
<blockquote>
<ul>
<li>Simple to code</li>
<li>Direct tie from data to visual elements</li>
</ul>
<p>Cons:</p>
<ul>
<li>visual elements not decoupled from tile</li>
<li>each tile makes its own connection – no connection sharing</li>
</ul>
</blockquote>
<p>Mosaic Service LCDS Call:</p>
<blockquote><p>Pros:</p>
<ul>
<li>LCDS call abstracted from tile</li>
<li>multiple tiles use same call</li>
</ul>
<p>Cons:</p>
<ul>
<li>more complex code</li>
<li>need to implement your own checker for returned data, or pass the tile context to the service</li>
</ul>
</blockquote>
<p>Special thanks to <a href="http://www.linkedin.com/in/leoschuman">Leo Schuman</a> and <a href="http://blogs.adobe.com/mtg/">Marcel Boucher</a> for their assistance and patience with LCDS. If you are interested, the <a href="http://blogs.adobe.com/steampowered/files/2010/12/LCDSTests.zip">source code can be found here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/steampowered/2010/12/mosaic-and-livecycle-data-services.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Service Interruptus</title>
		<link>http://blogs.adobe.com/steampowered/2010/11/service-interruptus.html</link>
		<comments>http://blogs.adobe.com/steampowered/2010/11/service-interruptus.html#comments</comments>
		<pubDate>Mon, 22 Nov 2010 15:46:11 +0000</pubDate>
		<dc:creator>Mike Hodgson</dc:creator>
				<category><![CDATA[Developing and Coding]]></category>
		<category><![CDATA[Product Information]]></category>
		<category><![CDATA[LiveCycle]]></category>
		<category><![CDATA[Mosaic]]></category>
		<category><![CDATA[Service]]></category>
		<category><![CDATA[Tile]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/steampowered/?p=66</guid>
		<description><![CDATA[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. <a href="http://blogs.adobe.com/steampowered/2010/11/service-interruptus.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>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.</p>
<h2>The Conditions</h2>
<p>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.</p>
<p><a href="http://blogs.adobe.com/steampowered/files/2010/11/arch2.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border-width: 0px;" src="http://blogs.adobe.com/steampowered/files/2010/11/arch2_thumb.png" border="0" alt="arch2" width="240" height="196" /></a></p>
<p>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.</p>
<h2>The Symptoms</h2>
<p>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.</p>
<p>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.</p>
<p>WTF???</p>
<h2>Somebody tell Schrodinger his cat is dead</h2>
<p>If all else fails, procrastinate. I ignored the problem and continued working on the rest of the demo – hey it worked <em>most</em> 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.</p>
<p>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…)</p>
<p>After stepping through the code multiple times, and adding more <em>trace</em> 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.</p>
<h2>Problems and Solutions</h2>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>I implemented the fix, and tested it out.  Everything worked fine … for a while.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<h2>Conclusion</h2>
<p>Here is the short version of what happened:</p>
<p>Issue 1</p>
<ol>
<li>Services that perform asynchronous operations need to tell their dependent tiles when these operations are complete</li>
<li>Service have no direct way of notifying tiles as they don’t have access to the Mosaic context</li>
<li>A tile can pass that context to the service if the service exposes a context object setter function</li>
</ol>
<p>Issue 2</p>
<ol>
<li>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.</li>
<li>The only thing to do is to have the tile wait (using a timer loop) for the injection to be complete.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/steampowered/2010/11/service-interruptus.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Creating an Organized Mosaic Project Structure</title>
		<link>http://blogs.adobe.com/steampowered/2010/11/creating-an-organized-mosaic-project-structure.html</link>
		<comments>http://blogs.adobe.com/steampowered/2010/11/creating-an-organized-mosaic-project-structure.html#comments</comments>
		<pubDate>Fri, 12 Nov 2010 17:30:21 +0000</pubDate>
		<dc:creator>Mike Hodgson</dc:creator>
				<category><![CDATA[General Knowledge]]></category>
		<category><![CDATA[Opinion and Rants]]></category>
		<category><![CDATA[Flex Builder]]></category>
		<category><![CDATA[LiveCycle ES2]]></category>
		<category><![CDATA[Mosaic]]></category>
		<category><![CDATA[Mosaic Project]]></category>
		<category><![CDATA[Mosaic SDK]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/steampowered/?p=62</guid>
		<description><![CDATA[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.  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.  <a href="http://blogs.adobe.com/steampowered/2010/11/creating-an-organized-mosaic-project-structure.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>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 <a href="http://www.adobe.com/devnet/flex/articles/best_practices_pt1.html">Flex best practices</a>, these suggestions may make developing your Mosaic applications a bit easier.</p>
<h2>Folder Structure</h2>
<p><em><span style="font-size: x-small;">Organization will set you free – Alton Brown</span></em></p>
<p>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 <a href="http://blogs.adobe.com/steampowered/2010/10/debugging-in-mosaic.html">debugging</a>.  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.</p>
<p>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:</p>
<p><a href="http://blogs.adobe.com/steampowered/files/2010/11/topLevel.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border: 0px;" src="http://blogs.adobe.com/steampowered/files/2010/11/topLevel_thumb.png" border="0" alt="topLevel" width="164" height="173" /></a></p>
<ul>
<li>applications – this folder contains the application descriptor xml file(s)</li>
<li>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 <strong>must</strong> 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.</li>
<li>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:<br />
<a href="http://blogs.adobe.com/steampowered/files/2010/11/interfaces.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border: 0px;" src="http://blogs.adobe.com/steampowered/files/2010/11/interfaces_thumb.png" border="0" alt="interfaces" width="244" height="146" /></a></li>
<li>policies – if you are using the Mosaic fine grained authorization, then this folder contains the XACML files that provide authorization information for the elements.</li>
<li>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:<br />
<a href="http://blogs.adobe.com/steampowered/files/2010/11/service.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border: 0px;" src="http://blogs.adobe.com/steampowered/files/2010/11/service_thumb.png" border="0" alt="service" width="231" height="159" /></a></li>
</ul>
<ul>
<li>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”:<br />
<a href="http://blogs.adobe.com/steampowered/files/2010/11/stylesheet.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border: 0px;" src="http://blogs.adobe.com/steampowered/files/2010/11/stylesheet_thumb.png" border="0" alt="stylesheet" width="168" height="180" /></a></li>
<li>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):<br />
<a href="http://blogs.adobe.com/steampowered/files/2010/11/tiles.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border: 0px;" src="http://blogs.adobe.com/steampowered/files/2010/11/tiles_thumb.png" border="0" alt="tiles" width="168" height="244" /></a></li>
</ul>
<h2>Catalog Structure</h2>
<p>As I said earlier, the catalog structure is the one thing that <strong>must</strong> 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.</p>
<p><a href="http://blogs.adobe.com/steampowered/files/2010/11/catalog.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border: 0px;" src="http://blogs.adobe.com/steampowered/files/2010/11/catalog_thumb.png" border="0" alt="catalog" width="151" height="300" /></a></p>
<ul>
<li>descriptor.xml – this is the catalog’s definition file.  It <strong>must</strong> be named descriptor.xml and it must be at the root of the catalog zip file</li>
<li>Interfaces – contains the compiled swf for the interface libraries.</li>
<li>Resources – this is where the miscellaneous stuff needed for tiles and services is stored.  Things like images, XML files, videos, etc. are put here.</li>
<li>Services – contains the compiled swf for the service classes</li>
<li>Stylesheets – contains the skin classes complied into a swf</li>
<li>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.</li>
</ul>
<h2>Flex Builder Linked Resources</h2>
<p>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.</p>
<p>To set up a linked resource to the Mosaic SDK:</p>
<ul>
<li>Open Flex Builder</li>
<li>Choose Window –&gt; Preferences</li>
<li>Choose General –&gt; Workspace –&gt; Linked Resources</li>
<li>Click the New button</li>
<li>Give it a name of <strong>MOSAIC_SDK</strong></li>
<li>Click the Folder button and browse to your Mosaic SDK folder.  Don’t go any lower than the “sdk” folder.</li>
<li>Click OK to close the dialogs</li>
</ul>
<p>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).</p>
<h2>ANT Scripts</h2>
<p>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?</p>
<p>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.</p>
<p>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.</p>
<p>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:</p>
<p><a href="http://blogs.adobe.com/steampowered/files/2010/11/folderStructure.png"><img style="padding-left: 0px; padding-right: 0px; padding-top: 0px; border: 0px;" src="http://blogs.adobe.com/steampowered/files/2010/11/folderStructure_thumb.png" border="0" alt="folderStructure" width="152" height="359" /></a></p>
<h2>Request for Comments</h2>
<p>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.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/steampowered/2010/11/creating-an-organized-mosaic-project-structure.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
