|
Using composite application annotations (Tile, Application, ContextBind, Expose, Consume, SecurityManager)Composite application tiles and services can communicate
data and call interfaces to other tiles and services. You start
communication by adding annotations to tiles and services. You insert
these annotations as metadata tags into your MXML and ActionScript
files to provide information to the Adobe Flex compiler, Experience
Services, and the Composite Application Framework client runtime. Metadata
tags are not compiled into executable code but provide information about
how to interpret portions of your code.
Experience Services supports a set of metadata tags you can use
to:
Define where to inject composite application tiles and
application instances
Allow tiles to share information using a shared context object
Binds the components of a composite application service that
expose and consume information and functionality
Specify the attribute in which to inject the Security Manager
These annotations allow you to author components that support
Composite Application Framework functionality quickly and concisely.
However, you can achieve the same results using the Composite Application
Framework SDK.
For information on how these annotations work with AnnotationParseEvent,
see Annotation parse complete.
Injection metadata tags
Tag
|
Description
|
|
|
Specifies that Experience Services handles
the instances of the class as tiles. Can also specify that the client
runtime injects an instance of ITile into the specified variable.
For more information, see Tile metadata tag.
|
[Application]
|
Specifies that the client runtime injects
an instance of the composite application object (IApplication) into
the specified variable. For more information, see Application metadata tag.
|
Messaging metadata tags
Tag
|
Description
|
[ContextBind]
|
Creates a two-way binding to a context object
in a tile. For more information, see ContextBind metadata tag.
|
Service metadata tags
Tag
|
Description
|
[Expose]
|
Specifies that an interface or service implementation
is a part of the interface library for a composite application service.
For more information, see Expose metadata tag.
|
[Consume]
|
Creates a reference to a composite application
service in a tile. The specified service is loaded, started, and
imported at runtime. For more information, see Consume metadata tag.
|
Security metadata tags
Tag
|
Description
|
[SecurityManager]
|
Specifies the attribute into which the current
Security Manager is injected. For more information, see SecurityManager metadata tag.
|
For more information about how metadata
tags work, see “Metadata tags in custom components” in Using Flex 4.5.
Tile metadata tagWhen the Tile metadata tag adorns a class, Experience Services
automatically updates the appropriate catalog definition file (CXML)
with a corresponding tile reference.
For example, the following excerpt defines the class as a tile:
[Tile]
public class SomeTile(){
}
[Tile] can also adorn a member variable of a
class. In this context, the metadata tag directs the client runtime
to inject the variable with the value of the host tile. This injection
allows the tile to access the Composite Application Framework SDK.
For example:
[Tile]
public class someTile(){
[Tile] public var thisTile:ITile;
}
When you use Tile to define a variable, ensure that the variable
is public and typed as ITile.
The Tile metadata tag supports a bundle parameter
when it adorns a UIComponent tile class. It specifies that the
class is included in the named SWF file and allows multiple tiles
to reside in a single SWF file. Normally, each UIComponent tile
has its own SWF file. This ability improves efficiency and allows
you to control how many SWF files are downloaded.
Property
|
Type
|
Description
|
Required?
|
bundle
|
String
|
Valid only in a UIComponent tile. Specifies
the name of the SWF file to include this component in.
|
No. Defaults to the name of the component.
|
The MXML syntax is:
<fx:Metadata>
[Tile(bundle="manyTiles")]
</fx:Metadata>
In this example, any UIComponent tile with the specified bundle value
is added to the manyTiles.swf. The .swf filename extension is not
included in the value of the bundle parameter.
Application metadata tagYou use the Application metadata tag with a public variable
in an ActionScript class. It allows you to create a reference to
the instance of the composite application that the framework generates
at runtime. The variable is typed as IApplication.
For example, the following excerpt defines the variable app to
inject the application into:
[Application]
public var app:IApplication;
When you use [Application] to adorn a variable, ensure that the
variable is public and typed as IApplication.
ContextBind metadata tagComposite Application Framework uses contexts to set attribute
values and share those values among tiles and services. For example,
contexts are often used to automatically update information in a
tile or service when the user updates the same information in another
tile or service.
Use the ContextBind metadata tag to define a context and its
attributes.
Property
|
Type
|
Description
|
Required?
|
context
|
String
|
Specifies the name of the context.
|
Yes
|
|
|
String
|
Specifies the name of a context attribute
|
Yes
|
The [ContextBind] metadata tag must reside in
the MXML file that contains the [Tile] metadata
tag. This ensures that Experience Services can correctly identify
the file that the context belongs to.
For example, a tile can use multiple contexts where each instance
of [ContextBind] represents a different attribute
to communicate or listen for. However, although you can create a
tile using multiple MXML source files, you cannot include the contexts
in a MXML file other than the one that contains [Tile].
The following excerpt from a tile definition creates the context dashboardStatus and
the attributes bugID and clientID.
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300">
<fx:Script>
<![CDATA[
[Bindable]
[ContextBind(name="dashboardStatus",attribute="bugID")]
public var bugid:int;
[Bindable]
[ContextBind(name="dashboardStatus",attribute="clientID")]
public var client:int;
private function selectedCaseChanged():void
{
bugid = int(caseList.selectedItem.bugid);
client = int(caseList.selectedItem.clientid);
}
]]>
</fx:Script>
The attributes are bound to fields in a data grid that is defined
in the same tile’s user interface:
<mx:DataGrid id="caseList" width="100%" height="100%" dataProvider="{cases}" change="selectedCaseChanged()">
<mx:columns>
<mx:DataGridColumn headerText="id" dataField="id"/>
<mx:DataGridColumn headerText="issue" dataField="issue"/>
<mx:DataGridColumn headerText="os" dataField="os"/>
<mx:DataGridColumn headerText="clientid" dataField="clientid"/>
<mx:DataGridColumn headerText="bugid" dataField="bugid"/>
</mx:columns>
</mx:DataGrid>
</s:Group>
You can reference the context and its attributes as required
in other tiles. For example, the following tile excerpt retrieves
the value of the bugID attribute.
<fx:Script>
<![CDATA[
import mx.events.PropertyChangeEvent;
[Bindable] private var _bug:Object = new Object;
[ContextBind(name="dashboardStatus",attribute="bugID")]
public function get bugID():int{
return _bug.id;
}
public function set bugID(id:int):void{
_bug = findBug(id);
}
private function findBug(id:int):Object
{
var b:XMLList = bugs;
for each( var bug:XML in b) {
if( int(bug.id) == id )
{
return bug;
}
}
return new Object;
}
]]>
</fx:Script>
The following excerpt defines an XMLList that the findbug function
searches:
<fx:Declarations>
<fx:XMLList id="bugs" xmlns="">
<bug>
<id>23312</id>
<description>Nullam eget at nulla nec eget ipsum.</description>
<owner>Michael King</owner>
<notes>Ut sit amet dolor arcu, ac feugiat metus</notes>
<dateopen>2009-03-15</dateopen>
<priority>3</priority>
<status>open</status>
</bug>
.... more bug samples ....
<bug>
<id>23299</id>
<description>Nullam eget at nulla nec eget ipsum.</description>
<owner>Michelle Jones</owner>
<notes>Mauris euismodtempus ut.</notes>
<dateopen>2009-03-26</dateopen>
<priority>3</priority>
<status>open</status>
</bug>
</fx:XMLList>
</fx:Declarations>
When the user updates the bugID property in
the first tile, the new value is automatically displayed in both
tiles.
For more information on using [ContextBind], including limitations
on the data types you can use with contexts, see Add a context to a tile.
Expose metadata tagIn Composite Application Framework, components that use
a service make reference to it using an interface. The implementation
of the service exists separately. This design pattern allows any
binding to a service definition to happen dynamically at runtime.
The client runtime injects the appropriate instance of the service
at the location specified by the Consume metadata tag. The Expose
metadata tag indicates that classes are part of an interface or
implementation library.
The Expose metadata tag specifies that an interface is part of
a service interface library or that a class is part of a service
implementation library.
Use Expose with no additional properties to define an interface
for use in a service interface library. To define a class in an
implementation library, use Expose and the following properties
as required:
Property
|
Type
|
Description
|
Required?
|
catalog
|
String
|
Specifies the name of the catalog that contains
the interface library for the service. If the property is not specified,
the framework uses the default catalog for the Flex project at compile
time.
|
No
|
|
|
String
|
Specifies the name of the service interface
library. If the property is not specified, the framework uses the
name of the project at compile time.
|
Yes
|
id
|
String
|
Specifies the GXML bean identifier. By default,
the value uses the format [class name]N, where
classname is the name of the associated class and N is a unique
value. For example, if the class name is StockDataService, the default
value of id is stockDataService1.
|
No
|
scope
|
String
|
Specifies whether a new instance of a service
is created for each object that requests it. By default, the value
is prototype, which creates an instance for each
reference. If the value is singleton, the service
is constrained to a single instance that is associated with all
references.
|
No
|
exposedInterface
|
String
|
Specifies the Flex interface to expose.
By
default, Experience Services exposes the first interface it finds
in the class associated with Expose. If it does not find an interface,
it then checks any superclass for an interface according to their
order in the hierarchy.
|
No
|
initializer
|
String
|
Specifies the name of a method on the class
to invoke after an instance of the class is created.
|
No
|
*
|
String
|
A name-value pair that specifies a property.
The property allows components that consume a service to identify
a specific implementation of the interface at runtime.
|
No
|
In the following excerpt, Expose specifies that the interface
is deployed to the server in a service interface library. The interface
provides tiles with access to the information and functions that
the service provides:
[Expose]
public interface IStockDataService
{
...
}
You also use the Expose metadata tag and its properties to define
classes in an implementation library. The implementation library
contains classes that perform functions such as data lookup. For
example, the following excerpt defines a class that implements the
IStockDataService interface:
[Expose(catalog="StockService" library="StockDataInterfaceLibrary", scope="singleton")]
public class StockDataService implements IStockDataService
Consume metadata tagUse the Consume metadata tag to inject a tile with a service
at runtime. This configuration allows a tile to exist independently
and still access the functionality and information provided by the
service.
For composite applications, you define a service interface using
the Expose metadata tag.
Property
|
Type
|
Description
|
Required?
|
catalog
|
String
|
Specifies the name of the catalog that contains
the interface library for the service. If the property is not specified,
the framework uses the default catalog for the Flex project at compile
time.
|
No
|
|
|
String
|
Specifies the name of the service interface
library. If the property is not specified, Flash Builder uses the
name of the project when it compiles the application.
|
No
|
id
|
String
|
Specifies the GXML bean identifier. By default,
the value uses the format [class name]N, where
classname is the name of the associated class and N is a unique
value. For example, if the class name is StockDataService, the default
value of id is stockDataService1.
|
No
|
*
|
String
|
A name-value pair that specifies a filter.
This filter specifies properties of the exposed service instance
that the client injects at runtime.
|
No
|
In the following tile excerpt, Consume specifies the interface
that it is requesting:
<fx:Script>
<![CDATA[
import com.adobe.mosaic.samples.services.stockdata.IStockDataService;
[Bindable]
[Consume(catalog="StockService" library="StockDataInterfaceLibrary")]
public var stockDataService:IStockDataService;
]]>
</fx:Script>
The public variable stockDataService references
the exposed interface found in the interface library.
SecurityManager metadata tagUse the SecurityManager metadata tag to inject an attribute
with the current Experience Services Security Manager.
The Security Manager is the ISecurityManager interface provided
by the com.adobe.livecycle.ria.security.api class package. For more
information on this package, see ActionScript 3.0 Language Reference.
The variable must be public and typed as ISecurityManager. Typically,
you use the variable that [SecurityManager] adorns to obtain a user
ID. For example:
<?xml version="1.0" encoding="utf-8"?>
<s:Module xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:mc="com.adobe.mosaic.core.*"
preinitialize="{this.addEventListener(AnnotationParseEvent.COMPLETE, annotationsDone)}">
<fx:Metadata>
[Tile]
</fx:Metadata>
<fx:Script>
<![CDATA[
import com.adobe.mosaic.om.events.AnnotationParseEvent;
private function annotationsDone(event:AnnotationParseEvent):void {
this.removeEventListener(AnnotationParseEvent.COMPLETE, annotationsDone);
trace('Annotations Parse Event Complete!');
}
]]>
</fx:Script>
</s:Module>
If HTTP Basic Authentication is enabled on the Experience Server,
you cannot use the Experience Services Security Manager within a
tile. The injected ISecurityManager defaults to null.
You can see an example of [SecurityManager] in
the UserInfoTile tile (UserInfoTile.mxml) that the GeoMetrixxDashboard
sample application uses. GeoMetrixxDashboard is part of the Dashboard
sample. For more information on samples, see Sample composite applications.
Annotation and Client Component Framework filesWhen you add Expose, Consume, or Tile metadata tags to
a class, Experience Services automatically generates corresponding
Client Component Framework (GXML) files. These configuration files
are added to the project’s mosaic/generated folder.
Because the GXML files externalize the interface and implementation
of application services, you can modify services without changing
the composite application source code. For example, to change the
current service configuration, replace the appropriate GXML files
in the mosaic/generated folder with files that have the same name
and the desired configuration.
Set annotation parsing depthAt runtime, the Composite Application Framework client
checks tile components and their children in the display list for
metadata tags related to composite applications. Use the annotationDepth
property to set to what depth the client runtime checks for annotations.
The default value for annotationDepth is 10.
Checking for annotations as classes are loaded uses processing
resources. The higher the value of annotationDepth, the more processing
resources are required. For best performance, set this value to
the lowest value that is needed for your applications.
Log in to Experience Server as an administrator. The
default URL for the server is http://localhost:4502/.
Click CRXDE Lite.
Navigate to the /content/mosaic/viewer folder. Double-click
gravity-flex-di-swf11.gxml to display it in the Edit pane.
In the Edit pane, edit the value of annotationDepth.
Click Save All.
Preserving annotations during compilationThe composite application client processes some of the
composite application metadata tags at runtime. Therefore, ensure
that the metadata tags are included in the SWF file that the Flex
compiler generates.
The compiler retains annotations when it compiles the debug version
of the SWF file but removes and optimizes them when it compiles
the release version. For Flex projects that are enabled for Composite
Application Framework Services, Experience Services automatically
adds the following option to the project’s additional compiler arguments:
-keep-as3-metadata+=Tile,Application,ContextBind,SecurityManager
To preserve annotations when you compile a release build using
Ant, add a keep-as3-metadata element for each metadata tag to the
mxmlc target. (You do not have to add the option for debug builds.)
For example:
<mxmlc ...>
<keep-as3-metadata name="Application"/>
<keep-as3-metadata name="ContextBind"/>
<keep-as3-metadata name="SecurityManager"/>
<keep-as3-metadata name="Tile"/>
</mxmlc>
Alternatively, write a <flex-config> file and then load
it during the build. The Composite Application Framework samples
provide examples of this method.
Initialization completeThe initialization of tile, application, and service variables
in composite applications can take varying amounts of time. There
is more than one method that you can use to ensure that initialization
is complete and to detect it.
Annotation parse completeTo know when your application can safely refer to variables that
you have annotated with either [Tile] or [Application],
you can listen for AnnotationParseEvent events (com.adobe.mosaic.om.events.AnnotationParseEvent). For
each variable annotated with [Tile] or [Application],
you receive an AnnotationParseEvent with a type of AnnotationParseEvent.COMPLETE
when that variable is available to use.
Alternatively, you can use a preinitialize event with a handler
to verify that a composite application component is loaded. For
example:
<s:Module
...
preinitialize="this.addEventListener(AnnotationParseEvent.COMPLETE, handleAnnotationParseEvent);">
private function handleAnnotationParseEvent(event:AnnotationParseEvent):void {
this.removeEventListener(AnnotationParseEvent.COMPLETE, handleAnnotationParseEvent);
// The tile is now ready
}
For more information about Composite Application Framework annotations,
see Using composite application annotations (Tile, Application, ContextBind, Expose, Consume, SecurityManager).
Set when tiles are loadedUse the loadPolicy attribute to choose when an application
loads a Flex-based tile.
Loading a tile involves retrieving all the logic, styles, and
content associated with the tile from the Experience Server. If
your application has large or complex tiles, or many tiles, loading
them all at startup can increase how long it takes to open. The
loadPolicy attribute allows you to specify which tiles are not loaded
until the user opens a view in which they are displayed.
The loadPolicy attribute is available for TileClass elements
when you create catalogs. It is also available for TileReference
elements when you define the contents of a view or panel in an application.
It can have one of the following values:
Value
|
Description
|
all
|
When the user opens an application, the
tile is created, even if it is not displayed in the current view
or panel. This value is the default.
|
|
|
The tile is created only when the tile's
view or panel is displayed.
|
Tiles can inherit their loadPolicy setting from their parent
components. For example, a tile is defined in a catalog with a loadPolicy value
of all. When an application that uses this tile
is opened, the tile is loaded. However, if the same tile in the
application file has a loadPolicy value of auto,
the catalog setting is ignored. A tile with a loadPolicy value
of auto loads only when the panel is displayed.
In the following example, Open Issues and Order History are large
tiles. By setting loadPolicy to auto,
those tiles are not loaded until the user opens the view that contains
them (Customer Service).
<tile:TileReference name="OpenIssues" label="Open Issues" top="0" left="0" width="50%" height="40%" loadPolicy="auto"/>
<tile:TileReference name="Offers" label="Special Offers" top="0" right="0" width="50%" height="40%" loadPolicy="all"/>
<tile:TileReference name="Orders" label="Order History" left="0" right="0" bottom="0" height="60%" loadPolicy="auto"/>
Service injection completeClient Component Framework injects the variables marked
with the [Consume] metadata tag when the service
is loaded into your application, not during the annotation parsing
phase. Therefore, use a technique other than AnnotationParseEvent
to determine when service injection is complete.
One technique is to use a setter instead of a public variable.
When you use a public variable, the variable is set directly when
the service is injected.
[Consume(catalog="stockmosaicservice_catalog" library="StockDataInterfaceLibrary")]
public var _stockDataService:IStockDataService;
To determine when a service injection is complete, you can use
a setter and private variable. When the variable is private, the
public setter is called when the service is injected. After the
setter is called, you can safely make calls to the service. Because
tile developers provide the setter, they can add code to the setter
to notify that the service injection is complete.
import com.adobe.mosaic.samples.services.stockdata.IStockDataService;
[Consume(catalog="stockmosaicservice_catalog" library="StockDataInterfaceLibrary")]
private var _stockDataService:IStockDataService;
public function set stockDataService(service:IStockDataService){
//after this setter method is called by the Client Composite Framework, you can safely make calls to the service
_stockDataService = service;
//add your own code here to trigger an event or indicate the service has been initialized
}
For an additional technique and complete example, see Add a service to a tile.
Choosing a tile communication methodYou can use either a shared context or messaging to implement
communication between tiles. The method that you use depends on
whether you want data to be available after it has been communicated.
Data that is shared using the messaging APIs is transient. It
is passed to the message receivers for their use and then discarded.
In contrast, information that is stored in contexts can be persisted
or retrieved later. When a context attribute is updated, the context
stores the updated data values. These stored values are available
programmatically at a later time. That is, it is durable. For example,
a tile that the user opens later in the session can access the data.
Add a context to a tileTiles use contexts to set attribute values and pass those
values between tiles. Context can be specific for each tile, panel,
or view. Also, an application can share context using a default
context on the application or named context on the application.
When you name an application context, the context is specific to
the given name. Any tile can access any element's context using
the Composite Application Framework SDK.
[ContextBind] is a Composite Application Framework-specific
metadata tag that you use to create a two-way binding to a context
named attribute and its value. It allows you to select a named context
and "bind" one of your values to it. It then propagates updates
to the named attribute's value across tiles when the value data
changes.
During application runtime, the specified context is located,
and the attribute is bound to the context. The first context attribute
found is bound. If an attribute does not match the specified filter,
a new one is created if the contextType is available and has a registered
implementation.
You can use [ContextBind] with named contexts
only.
The Flex metadata tag [Bindable] is required
for any property that you annotate with [ContextBind].
The Flex runtime registers any [Bindable] property
and automatically copies the value of the source property to any
destination property when the source property's value changes. For
properties annotated with[ContextBind], Flex captures
any changes and updates any destination [ContextBind] properties.
Then Composite Application Framework detects the property change
and updates the context attribute value. For more information on
using the Flex [Bindable] metadata tag, see “Using
the Bindable metadata tag” in Flex 3 Developer's Guide.
Context persistenceContext changes can only be persisted in a saved view.
When the user saves a view, any tile, panel, or view context is
saved to Experience Server as part of the view. Although you can
define the default or named context in the application (AXML) file
saved on the server, changes to the default or named context are
not persisted.
Initializing contextYou can set the initial value for a context in a catalog
(CXML) file or application (AXML) file. All contexts defined in
the catalog or the application are available at runtime. Context
values that are defined in the application file override the ones in
the catalog.
The following example illustrates how to initialize a context
for a panel. This behavior also applies to views and tiles. The
example catalog defines two attributes:
<view:PanelClassList>
<view:PanelClass name="PanelExample">
<ct:Context xmlns:ct="http://ns.adobe.com/Mosaic/CommonTypes/1.0/">
<ct:Data key="defaultExample" type="string" value="A1"/>
<ct:Data key="overrideExample" type="string" value="B1"/>
</ct:Context>
<view:Content>
<view:Panel name="PanelExample" label="Panel Context Override Example" allowContentDelete="true" tileChrome="full" width="100%" height="100%">
<catalog:CatalogReference name="MyCat" uri="MyCat"/>
<view:Layout numColumns="2" paddingBottom="4" paddingRight="4" paddingTop="4" paddingLeft="4" name="SmartGridLayout"/>
<tile:TileReference catalog="MyCat" name="OpenCases" label="Open Cases" width="100%" height="50%" chrome="full"/>
</view:Panel>
</view:Content>
</view:PanelClass>
</view:PanelClassList>
An application references the panel and provides a different
definition of the context. The application definition adds the attribute
newAttributeExample and sets a new value for the attribute overrideExample.
<app:Shell >
<catalog:CatalogReference name="MyCat" uri="MyCat"/>
<view:PanelReference catalog="MyCat" name="PanelExample" >
<ct:Context xmlns:ct="http://ns.adobe.com/Mosaic/CommonTypes/1.0/">
<ct:Data key="newAttributeExample" type="string" value="C1"/>
<ct:Data key="overrideExample" type="string" value="B2"/>
</ct:Context>
</view:PanelReference>
</view:Panel>
</app:Shell>
At runtime, Experience Server initializes the context attributes
with the following values:
defaultExample = A1
overrideExample = B2
newAttributeExample = C1
To define the context for inline panels, initialize the context
in the view:Panel element.
<app:Shell >
<view:Panel name="PanelExample" label="Panel Context Override Example" allowContentDelete="true" tileChrome="full" width="100%" height="100%">
<ct:Context xmlns:ct="http://ns.adobe.com/Mosaic/CommonTypes/1.0/">
<ct:Data key="defaultExample" type="string" value="A1"/>
<ct:Data key="newAttributeExample" type="string" value="C1"/>
<ct:Data key="overrideExample" type="string" value="B2"/>
</ct:Context>
<view:Layout numColumns="2" paddingBottom="4" paddingRight="4" paddingTop="4" paddingLeft="4" name="SmartGridLayout"/>
<tile:TileReference catalog=" MyCat" name="OpenCases" label="Open Cases" width="100%" height="50%" chrome="full"/>
</view:Panel>
</app:Shell>
In the catalog file, you can define the context in the view:Panel
element of view:PanelClass as well as in the view:PanelClass element
itself. If you define the context in both of these catalog elements,
the context from the view:PanelClass overrides the context from
the view:Panel. However, the view:PanelReference context defined
in the application still overrides any context defined in the catalog.
Data types used with contexts and messagingThere are limitations on the types of data that composite
application components can share across the Composite Application
Framework environment.
For information on the restrictions that apply wherever composite
application components share data, see the limitations for service
interface libraries in Create a service.
Create tiles that use a contextCreate a tile (see Create a Flex-based tile).
In Source mode, under the Metadata block, add a Script block
that contains the [ContextBind] metadata tags.
Include set and get functions that manage attributes of the context.
For
example, you can add functions that use integer, string, and date
attributes:
<fx:Metadata>
//This module is a Composite Application Framework Tile
[Tile]
</fx:Metadata>
<fx:Script>
<![CDATA[
protected var _transID:int;
[Bindable]
[ContextBind(context="helloStatus",attribute="transID")]
public function get transid():int{
return _transID;
}
public function set transid(i:int):void{
_transID = i;
}
protected var _client:String;
[Bindable]
[ContextBind(context="helloStatus",attribute="clientName")]
public function get client():String{
return _client;
}
public function set client(s:String):void{
_client = s;
}
[Bindable] protected var _date:Date = new Date();
[Bindable]
[ContextBind(context="helloStatus",attribute="localDate")]
public function get cbDate():Date{
return _date;
}
public function set cbDate(d:Date):void{
_date = d;
dateField.selectedDate = d;
}
private function dateChanged(date:Date):void {
cbDate = date;
}
]]>
</fx:Script>
In the Script block, the context
attributes are bound to the functions themselves. You can reference
the functions in the MXML file either in simple assignment statements
or by binding attributes to user interface elements.
Add a layout block and controls that create user interface
elements. Bind the context attributes to your controls.
For
example, bind the transid and client context
attributes to the control properties to enable users to display
or update the context attributes.
<s:VGroup>
<s:NumericStepper id="value" change="{transid = value.value}" value="{transid}"/>
<s:TextInput id="clientValue" change="{client = clientValue.text}" text="{client}"/>
<mx:DateField id="dateField" change="dateChanged(DateField(event.target).selectedDate)"/>
</s:VGroup>
The get transid() and get client()
functions are called using the bound variables in the NumericStepper
and TextInput controls.
Save the tile.
Create a second tile. For example, a tile named Listener.mxml.
Add a Script block that contains the [ContextBind] metadata
tags. For example, you can add the Script block that you added to
the HelloWorld tile.
Add a layout block and controls to create a user interface.
For
example:
<s:layout>
<s:BasicLayout/>
</s:layout>
<s:NumericStepper id="value"
x="95" y="36"
change="{transid = value.value}"
maximum="100" minimum="0"
value="{transid}"/>
<s:TextInput id="clientValue"
x="95" y="78"
change="{client = clientValue.text}"
text="{client}"/>
<s:Label x="24" y="10"
fontSize="18"
fontWeight="bold"
text="Listener on ContextBind"/>
<s:Label x="6" y="123"
width="341" height="29"
fontSize="14"
text="These update as ContextBind attributes are changed."/>
<s:Label x="6" y="154"
fontSize="14"
text="Making changes these will propogate out to other Listeners."/>
<s:Label x="179" y="40"
fontSize="14"
fontWeight="bold"
text="integer"/>
<s:Label x="231" y="88"
fontSize="14"
fontWeight="bold"
text="String"/>
<s:Label x="210" y="112" fontSize="14" fontWeight="bold" text="Date"/>
<mx:DateField id="dateField"
x="60" y="108"
change="dateChanged(DateField(event.target).selectedDate)"/>
Use a context to create the URL for an HTML tileYou can use a context to create an HTML Tile that displays
a dynamically generated URL. For example, the following catalog
definition specifies a tile that displays financial information.
Part of the URL is specified using an application context attribute:
<tile:Content contentType="text/html" uri=" http://finance.yahoo.com/lookup?s=${application.symbol}"/>
At runtime, the value of the symbol attribute replaces ${application.symbol}. User
input in another tile in the application can set the value of the
symbol attribute. Whenever the symbol attribute value changes, the
HTML tile refreshes its content.
This mechanism allows you to use context to control any website
that uses query parameters in its URL. However, a developer has
less control over this type of tile because it does not communicate
any changes back to the context.
For example, if you change the symbol in the example financial
information tile, the HTML tile content is updated but the context
is not. To avoid this limitation, write your own HTML tile and use
the JavaScript code to keep the context synchronized with the HTML
tile. The JavaScript code is provided with the Composite Application
Framework SDK
The Concepts sample includes the Brokerage application, which
illustrates how to use a context in an HTML tile. For information
on samples, see Sample composite applications.
Adding tiles that use context to a composite applicationYou add tiles that use a shared context to a composite
application in the same way you add any other tile. The tiles communicate
in an application without any additional application configuration.
For information on adding a tile to an application, see Create a composite application file (AXML file).
For information on testing your application, see Deploy a composite application.
To test the application, change the values in the integer, string,
and date fields.
Changes you make in one tile are automatically reflected in the
other tile.
Add messaging to a tileApart from using contexts, the other method for communicating
between tiles is through the com.adobe.mosaic.om.events.Message class.
Conceptually, you create a system of broadcasting from tiles
to other tiles within the same application. Any given tile can receive
a message by adding a message listener, which identifies which message
the tile is interested in. It receives the broadcasted message and
then executes a message handler function to process the message.
It also executes any code that depends on the data, or payload,
sent in the message. Messages are sent out across an entire composite
application, but do not cross application instance boundaries.
Example of adding messaging to a tileFor
example, consider the MessageSender component from
the Basic example application provided for Composite Application
Framework (in the Concepts sample collection of applications):
<s:Application xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mc="com.adobe.mosaic.om.*"
xmlns:s="library://ns.adobe.com/flex/spark"
width="100%" height="100%">
<fx:Metadata>
[Tile]
</fx:Metadata>
<fx:Script>
<![CDATA[
import com.adobe.mosaic.om.events.Message;
import com.adobe.mosaic.om.interfaces.IApplication;
import com.adobe.mosaic.om.interfaces.ITile;
[Bindable] [Application] public var mosaicApp:IApplication;
[Bindable] [Tile] public var thisTile:ITile;
/** This tile sends message you can provide any namespace, message name and payload.
*/
private function sendMessage():void{
/** To send a message we create a new Message object and send the message over the runtime
*/
mosaicApp.sendMessage(new Message(txtNamespace.text,txtName.text,txtPayload.text));
}
]]>
</fx:Script>
<mx:Panel title="3a. MessageSender" width="100%" height="100%" paddingLeft="10" paddingRight="10" paddingTop="10" paddingBottom="10">
<mx:Text width="100%" text="This tile sends message with the specified namespace, message name and payload." />
<mx:HRule width="100%"/>
<mx:Spacer height="10"/>
<s:HGroup>
<s:Label text="Message Namespace" width="150"/>
<s:TextInput id="txtNamespace" width="250"/>
</s:HGroup>
<s:HGroup>
<s:Label text="Message Name" width="150"/>
<s:TextInput id="txtName" width="250"/>
</s:HGroup>
<s:HGroup>
<s:Label text="Message Payload" width="150"/>
<s:TextInput id="txtPayload" width="250"/>
</s:HGroup>
<s:Button label="Send Message" click="{sendMessage()}"/>
</mx:Panel>
</s:Application>
In this example, the sendMessage method
broadcasts a message to all other tiles in an application with the
values of the txtNamespace, txtName,
and txtPayload objects. However, for the broadcast
to be of value, other tiles in the application must have a message
listener added that receives the broadcast. Continuing this example,
the MessageReceiver component from the Basic example
application adds appropriate message listeners to tiles in the Basic application:
<s:Application xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mc="com.adobe.mosaic.om.*"
xmlns:s="library://ns.adobe.com/flex/spark"
width="100%" height="100%">
<fx:Metadata>
[Tile]
</fx:Metadata>
<fx:Script>
<![CDATA[
/** This tile can add message listeners for any namespace and name provided. It will then output the message details and its
* payload.
*/
import com.adobe.mosaic.om.events.Message;
import mx.collections.ArrayCollection;
import com.adobe.mosaic.om.interfaces.IApplication;
import com.adobe.mosaic.om.interfaces.ITile;
[Application][Bindable] public var mosaicApp:IApplication;
[Bindable] [Tile] public var thisTile:ITile;
[Bindable]
private var datagridData:ArrayCollection = new ArrayCollection();
private function addListener():void{
/** To listen for a message we call addMessageListener with a namespace, a message name and listener function. The listener function
* must take in one parameter whose type is com.adobe.mosaic.om.events.Message
*/
mosaicApp.addMessageListener(txtNamespace.text,txtName.text,onMessage);
}
private function onMessage(message:Message):void{
/** Here we access the properties of the message and print them out. Payload can be many other types besides just a string.
*/
datagridData.addItem({namespace: message.nameSpace, name: message.name, payload: message.payload});
}
]]>
</fx:Script>
<mx:Panel title="3b. MessageReceiver" width="100%" height="100%" paddingLeft="10" paddingRight="10" paddingTop="10" paddingBottom="10">
<mx:Text width="100%" text="This tile can add message listeners for the specified namespace and message name."/>
<mx:HRule width="100%"/>
<mx:Spacer height="10"/>
<s:HGroup>
<s:Label text="Message Namespace" width="150"/>
<s:TextInput id="txtNamespace" width="250"/>
</s:HGroup>
<s:HGroup>
<s:Label text="Message Name" width="150"/>
<s:TextInput id="txtName" width="250"/>
</s:HGroup>
<s:Button label="Add Listener" click="{addListener()}"/>
<mx:DataGrid id="datagridOutput" width="100%" height="100%" editable="false" dataProvider="{datagridData}" sortableColumns="false">
<mx:columns>
<mx:DataGridColumn headerText="Namespace" dataField="namespace"/>
<mx:DataGridColumn headerText="Name" dataField="name"/>
<mx:DataGridColumn headerText="Payload" dataField="payload"/>
</mx:columns>
</mx:DataGrid>
</mx:Panel>
</s:Application>
In this example, broadcast
messages from the MessageSender object are ignored
until the addListener method is called through
a user clicking the Button object.
Through
this mechanism of broadcasting and listening, you can create inter-tile communication
that gives users a much more dynamic experience.
Data types used with contexts and messagingThere
are limitations on the types of data that composite application
components can share across the Composite Application Framework
environment.
For information on the restrictions that apply
wherever composite application components share data, see the limitations
for service interface libraries in Create a service.
Add a service to a tileCreate the project for the tileIn Flash Builder, click File > New > Flex Project for
ADEP-Experience Services. For Project Name, enter PropertiesTest,
and then click Next twice.
On the Experience Services screen, on the General tab, select
Composite Application Framework Services. Click Finish.
On the Composite Application Framework Services Configuration
tab, use the Name list to select the catalog. For example, PropertiesCatalog.
Click Next.
On the Build Paths screen, click Add Project and select the
service interface library that you created. For example, PropertiesInterfaceService.
Click Finish.
Add content to the tileIn Package
Explorer, in the src folder, delete the file PropertiesTest.mxml.
Flash
Builder creates this file for the project by default, but it is
not configured to be a tile.
Right-click the new project and then click New > Composite
Application Tile. For this example, the tile is named PropertiesTile.
Click Finish.
Open the new tile in Source view.
By default, the new
MXML tile includes the metadata tag [Tile].
<fx:Metadata>
//This module is a Composite Application Framework Tile
[Tile]
</fx:Metadata>
Within the Script block, import classes or class packages
and add bindable variables as required. For example:
<fx:Script>
<![CDATA[
import com.adobe.mosaic.om.interfaces.*;
import com.adobe.aep.samples.services.properties.IPropertiesService;
import mx.events.FlexEvent;
import mx.controls.Alert;
import mx.binding.utils.ChangeWatcher;
import mx.events.PropertyChangeEvent;
[Bindable] [Application] public var mosaicApp:IApplication;
[Bindable] [Tile] public var thisTile:ITile;
...
Still in the Script block, after the bindable variables,
add the following elements:
[Bindable] and[Consume] metadata
tags. For [Consume], use catalog and library properties
to specify the catalog that contains the interface library and the
name of the interface library.
A variable that allows the tile to reference the service
using the IPropertiesService class, which is in the PropertiesInterfaceLibrary
library.
When the service is ready, Composite Application
Framework injects a type into this variable. Therefore, it must
be public. This variable can also be a setter, which allows the
tile to detect when Composite Application Framework sets the value.
Alternatively, you can use a ChangeWatcher to detect when Composite
Application Framework injects the service, as shown below.
A variable to hold the array of properties that the service
provides.
[Bindable]
[Consume(catalog="PropertiesCatalog", library="PropertiesInterfaceLibrary")]
public var theService:IPropertiesService;
private var propSet:Array;
Add additional elements as required to complete the tile.
For example:
...
<fx:Declarations>
<s:RadioButtonGroup id="WhichPropertySet"/>
</fx:Declarations>
...
private var watcher:ChangeWatcher;
protected function application1_preinitializeHandler(event:FlexEvent):void
{
watcher = ChangeWatcher.watch(this,"theService",onGotService,false,true);
}
protected function onGotService(e:PropertyChangeEvent):void{
if(theService) {
var propSet:Array = theService.getPropertySet("trader");
propA.text = propSet[0].toString();
propB.text = propSet[1].toString();
propC.text = propSet[2].toString();
}
else
Alert.show("theService is null!", "QE",4, this);
watcher.unwatch();
}
...
private function buttonClick():void {
var tempStr:String = WhichPropertySet.selectedValue.toString();
var setName:String = "trader";
if (theService == null) {
Alert.show("theService is null!", "QE",4, this);
return;
}
try {
switch (tempStr) {
case "Trader Properties":
setName = "trader";
break;
case "Manager Properties":
setName = "manager";
break;
case "Designer Properties":
setName = "designer";
break;
default:
setName = "trader";
}
var propSet:Array = theService.getPropertySet(setName);
if (propSet != null) {
propA.text = propSet[0].toString();
propB.text = propSet[1].toString();
propC.text = propSet[2].toString();
}
}
catch (err:Error) {
Alert.show("exception: " +err,"QE",4,this);
propA.text = "null property set";
propB.text = "null property set";
propC.text = "null property set";
}
}
...
<s:Group height="450" width="450" x="-3" contentBackgroundColor="#EEEEEE">
<s:layout>
<s:BasicLayout/>
</s:layout>
<mx:Label x="10" y="6" fontSize="18" text="RIA Properties Service Test D"
fontWeight="bold" />
<mx:Label x="25" y="41" fontSize="14" text="Select a Property Set" />
<s:RadioButton x="48" y="70" label="Trader Properties " groupName="WhichPropertySet" selected="true"/>
<s:RadioButton x="48" y="90" label="Manager Properties" groupName="WhichPropertySet"/>
<s:RadioButton x="48" y="110" label="Designer Properties" groupName="WhichPropertySet"/>
<mx:TextArea id="propA" x="27" y="136" height="20" width="250"/>
<mx:TextArea id="propB" x="27" y="164" height="20" width="250"/>
<mx:TextArea id="propC" x="27" y="192" height="20" width="250"/>
<s:Button x="36" y="223" label="Get Property Set" click="buttonClick()" fontSize="14"/>
</s:Group>
Save the file.
Allow users to manage views, panels, and tilesComposite Application Framework allows you to give users
the ability to change which views, panels, and tiles that are displayed
as they work. Users can add, save, close, and open views, and add
and close panels and tiles. Information on how to use the schema
to enable built-in buttons and menus for managing views, panels,
and tiles, is available. See Composite Application Framework XML Schema
Reference.
In addition, the Composite Application Framework SDK also provides
all the methods that can implement your own user interface or menu.
For details, see the Organizer tile that is included with the Dashboard
sample.
Using Data ServicesYou can create composite application tiles that interact
with Data Services data management services to retrieve, create,
update, and delete data.
The steps to create the data management service are similar to
the ones you use to create a composite application client-side service.
Flex library projects provide the client-side implementation and
interface libraries for the service. A separate Flex project contains
the composite application components that use the service.
However, for data management services, you do not have to create
the service implementation and service interface classes found in
the libraries. Instead, the Adobe application modeling technology
can automatically generate both the interfaces and implementation
classes that tiles use to interact with the data management service.
The modeler also creates the server-side data management service
on the Experience Server.
You add a reference to the data management service to tiles and
composite applications to allow them to interact with the data management
service. To configure the data management service to work with a
composite application, you add [Expose] metadata
tags to the appropriate service implementation and service interface
classes.
For information on using the modeler to create a service, in Develop model-driven applications, see “Generate libraries for the
Client Component Framework.”
For more information about composite application services, including
a discussion of the service design pattern, see Create a service.
Create the service implementation libraryClick File > New > Flex Library Project.
On the Project Location page, enter a name for the library
and then click Next. For example, call the library ProductService.
On the Build Paths page, on the Library Path tab, for Framework
Linkage, select Merged Into Code. Click Finish.
Merged Into
Code merges portions of the Flex SDK into the SWC for the library during
compilation. You select it to ensure that the runtime can resolve
references to the Flex SDK's remoting classes. These references
are located in the code that the data model generates.
To enable the project for Composite Application Framework
Services and select a catalog:
Right-click the project
and then click Properties. Expand Adobe and click Experience Services.
Select Enable Experience Services and then select Composite
Application Framework Services.
Click Apply. Click Yes to accept the changes.
In the list of property categories, under Adobe, click Composite
Application Framework. To change the catalog, click Use Project
Settings and then select a catalog from the Name list. For example,
select DataManagement.
Click OK to close the Properties dialog box.
Add a data model to the service implementation libraryRight-click the project and then click New > Data Model.
Enter a name for the model and then click Next. For example,
name it ProductModel.
On the Select Service Type page, select Use The Following
Service As A Starting Point and then click LCDS. Click Next.
On the Import BlazeDS/LCDS Service page, for RDS Server,
select Adobe Digital Enterprise Platform (localhost). Enter your
Experience Server username and password. By default, the username
and password are both admin.
In the Select the Destinations to Import table, under Destination,
select productService. Click Finish.
Click Yes to switch to Data Model perspective.
In Properties, click the Code Gen tab. At the bottom of the
tab, click Code Generation Preferences.
If it is not already selected, select Use Project Properties.
For both ActionScriptGeneration and Model Driven Form, ensure
that Client Component Framework is selected. Click OK.
Client
Component Framework operates on a strict separation of interface
and implementation to provide modularity and dynamic composition
features. The Modular Component Framework option provides generated
code that adheres to this pattern. That is, it generates distinct
interface and implementation classes as opposed to behavior of the
Default code generation, which emits a single, “value object” pattern.
In the toolbar of the model editor, click the Generate Code
button.
Create and configure the service interface libraryIn Flash Perspective, create another Flex Library Project
and enable it for Composite Application Framework. Select the catalog
that you are using for your Data Services project.
For example,
create a library project named ProductInterfaceLibrary that uses the
DataManagement catalog.
Right-click the src folder, and then click New > Package.
Name the package services.
Create another package at the same location named valueObjects.
Configure the service implementation libraryRight-click the service implementation library project and
then click Properties. For example, right-click ProductService.
Click Flex Library Build Path. Click Add Project.
Select the service interface library and click OK. For example,
select ProductInterfaceLibrary.
Click OK to close the Properties dialog box.
Move the interface to the interface libraryDrag the services/api folder for the implementation library
to the services folder for the interface library. For example, under
ProductService, drag the services/api folder to services under ProductInterfaceLibrary.
In
the Move dialog box, select Include Subpackages, and then click
OK.
Drag the valueObjects/api folder for the implementation library
to the services folder for the interface library. For example, under
ProductService, drag the valueObjects/api folder to services under
ProductInterfaceLibrary.
In the Move dialog box, select Include
Subpackages, and then click OK.
If Project > Build Automatically is not selected, rebuild
both projects using Project > Build Project.
Create a tile that uses Data ServicesTo create a client application project, click New > Flex
Project for ADEP-Experience Services.
On the Project Location page, enter a name for the project
and click Next twice. For example, name it ProductTile.
On the Experience Services page, select Composite Application
Framework Services. and then click Next.
On the Composite Application Framework Services tab, use
the Name list to select the catalog that you are using for your
client application. For example, select DataManagement.
Click Next.
On the Build Paths page, click Add Project. Select the service
interface library and click OK. For example, click ProductInterfaceLibrary.
Click Finish.
To add a tile to the project, right-click the project and
then click New > Composite Application Tile.
Enter a name for the tile. For example, MyProductTile.
Add elements as required to match the following example code:
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="100%" height="100%"
preinitialize="{application1_preinitializeHandler(event)}">
<fx:Script>
<![CDATA[
import com.adobe.gravity.utility.async.IToken;
import com.adobe.mosaic.om.interfaces.IApplication;
import com.adobe.mosaic.om.interfaces.ICatalog;
import com.adobe.mosaic.om.interfaces.IPanel;
import com.adobe.mosaic.om.interfaces.ITile;
import mx.binding.utils.ChangeWatcher;
import mx.collections.ArrayCollection;
import mx.collections.IList;
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.events.PropertyChangeEvent;
import services.api.IProductService;
[Bindable]
private var products:ArrayCollection = new ArrayCollection();
[Application]
public var mosaicApp:IApplication
[Tile]
public var thisTile:ITile;
]]>
</fx:Script>
In the Script block, add the following elements:
[Bindable] and [Consume] metadata
tags. For [Consume], use catalog and library properties
to specify the catalog that contains the interface library and the
name of the interface library.
An IToken variable for storing the results that ProductService
returns.
A gotProducts function to use as the success handler for
the IToken variable. The function defines a parameter of type IList,
and stores the given IList object in the products variable.
A function that displays an error message if the service
does not load.
[Bindable]
[Consume(catalog="DataManagement",library="ProductInterfaceLibrary")]
public var theService:IProductService;
private var getProductToken:IToken;
private function gotProducts(list:IList):void{
products.list = list;
}
private function failedGetProducts(...rest):void{
Alert.show("Got an error when calling the service");
}
Add elements as required to match the following example code:
private var watcher:ChangeWatcher;
protected function application1_preinitializeHandler(event:FlexEvent):void
{
watcher = ChangeWatcher.watch(this,"theService",onGotService,false,true);
}
protected function onGotService(e:PropertyChangeEvent):void{
if(theService){
getProductToken = theService.getProducts();
getProductToken.addSuccessHandler(gotProducts);
getProductToken.addFaultHandler(failedGetProducts);
watcher.unwatch();
}
}
<mx:DataGrid id="dataGrid" x="19" y="115"
dataProvider="{products}">
<mx:columns>
<mx:DataGridColumn dataField="category" headerText="category"/>
<mx:DataGridColumn dataField="price" headerText="price"/>
<mx:DataGridColumn dataField="description" headerText="description"/>
<mx:DataGridColumn dataField="name" headerText="name"/>
<mx:DataGridColumn dataField="qtyInStock" headerText="qtyInStock"/>
<mx:DataGridColumn dataField="image" headerText="image"/>
<mx:DataGridColumn dataField="productId" headerText="productId"/>
</mx:columns>
</mx:DataGrid>
<s:Label x="28" y="28" fontSize="18" fontWeight="bold" text="Tile - Data Management Service"/>
<s:Label x="28" y="57" fontSize="14" fontWeight="bold"
text="Tile 1 - connects to ProductsService"/>
<s:Label x="28" y="81" text="http://127.0.0.1:4502/dataservices/messagebroker/amf"/>
Configure the service interface and implementation library as a composite application serviceIn
the service interface library project, open the appropriate service
interface class. For example, in ProductInterfaceLibrary, open IProductService.as.
Add the [Expose] metadata tag before the
interface definition to specify that the exposed service be deployed
as a composite application service interface library.
For
example:
[Expose]
public interface IProductService
In the service implementation library project, open the appropriate
service implementation class. For example, in ProductService, open
ProductService.as.
Before the class definition, to create a reference to the
service interface library, import the IPropertiesService class.
For example:
import services.api.IProductService;
public class ProductService extends _Super_ProductService implements IProductService
Add [Expose]before the interface definition
to specify that the exposed service be deployed as a composite application
service implementation library. Use the library property to specify
the name of the service interface library. Add implements IProductService to
provide the implementation of the interface.
For example:
import services.api.IProductService;
[Expose(library="ProductInterfaceLibrary")]
public class ProductService extends _Super_ProductService implements IProductService
|
|
|