close

Вход

Забыли?

вход по аккаунту

?

Flash & Flex. 2011.09

код для вставкиСкачать
FFDM 2011.09
4
09/2011 (27)
5
09/2011 (27)
Nobody Is Perfect
I think that it is high time to give you the next issue of FFD magazine. We have a huge delay this month. It happens, even to us. I hope that it is the irst and the last time. I’m really sorry about that. Please, see what we have for you. Thank you for your understanding.
In this issue, we gathered the articles to give you deep insight into the FF world. Our regular columnist Huw Collingbourne wrote the article on Adding Categories To XML. In his last two columns he showed how to create an XML ile, load it into memory and display the data one record (or XML item) at a time in text ields or the columns of a data grid. The main weakness of last month’s program was that it did not provide any way of iltering the display of items. It was a case of all or nothing. Just go to page 22 and see how to deal with such problems.
If you want to learn more about Flex solution, just go to page 12 to read the article on Adobe Flex Mobile, Swiz Framework and FlexORM by Stefan Horochovec. He demonstrates how you can create a Adobe Flex application to run on mobile devices, using two frameworks, Swiz and FlexORM. You will learn how to create Flex Mobile projects; how to conigure and create projects using Swiz Framework; and how to conigure and create projects using Flex ORM.
The next article I would recommend that we publish in FFD is on page 26. Russ Ferguson shows you one of the strengths of the Flash Platform and its ability to handle real-time data, multiple live users in addition to audio and video in a way that can be delivered across multiple devices and platforms.
As every month we have special chapters from Manning Publishing. You will ind the articles Flex on Java by Bernerd Allmon and Jeremy Anderson on page 32 and Spring Dynamic Modules in Action by Arnaud Cogoluegnes, Thierry Templier, and Andy Piper on page 40. This month we also present articles written by Tim Kridel for Intelligence in Software. They are very good piece of knowledge. Just go to next page to ind them in table of content.
Thank You All for your great work and help. Enjoy reading!
Ewa Dudzic & FFD team
Editor in Chief: Ewa Dudzic ewa.dudzic@ffdmag.com
Proofreaders: Betsy Irvine, Patrick French
DTP Team: Ireneusz Pogroszewski ireneusz.pogroszewski@software.com.pl
Art Director: Ireneusz Pogroszewski ireneusz.pogroszewski@software.com.pl
Senior Consultant/Publisher: Paweł Marciniak
Flex/ActionScript 101 Section Editor: Marc Pires marcpiresrj@gmail.com
iPhone Development Section Editor: Ryan D’Agostino
ActionScript in Action Section Editor: Huw Collingbourne
Games Section Editor: Chris Hughes
Contributing Editors: Pedro de La Rocque, Ali Raza, Csomák Gábor
Publisher: Software Press Sp. z o.o. SK
ul. Bokserska 1 02-682 Warszawa Poland Worldwide Publishing Software Press Sp. z o.o. SK
is looking for partners from all over the World.
If you are interested in cooperating with us,
please contact us by e-mail: cooperation@software.com.pl
Whilst every effort has been made to ensure the high quality of the magazine, the editors make no warranty, express or implied, concerning the results of content usage.
All trade marks presented in the magazine were used only for informative purposes.
All rights to trade marks presented in the magazine are reserved by the companies which own them.
Thanks to the most active and helping beta testers:
Russell TangChoon, Lee Graham, Jassa Amir Lang, Ed Werzyn, Yann Smith-Kielland, Justus, Csomák Gábor, Kevin Martin, Charles Wong, Ali Raza, Almog Koren, Izcoatl Armando Estanol Fuentes, Lionel Low, Michael J. Iriarte, Paula R. Mould, Rosarin Adulseranee, Sidney de Koning
To create graphs and diagrams we used program by company.
The editors use automatic DTP system Mathematical formulas created by Design Science MathType™
ATTENTION!
Distributing current or past issues of this magazine – without permission of the publisher – is harmful activity and will result in judicial liability.
DISCLAIMER!
The techniques described in our articles may only be used in private, local networks. The edi
-
tors hold no responsibility for misuse of the presented techniques or consequent data loss.
Editor’s Note
4
09/2011 (27)
5
09/2011 (27)
CONTENTS
Tech Corner
06 11 Tips for Mobile Software Development
BY TIM KRIDEL FOR INTELLIGENCE IN SOFTWARE
Special Report
08 The Fragmented Mobile Device Market
BY TIM KRIDEL FOR INTELLIGENCE IN SOFTWARE
InBrief
10 News
BY CSOMÁK GÁBOR
Flex Development
12 Adobe Flex Mobile, Swiz Framework and FlexORM
BY STEFAN HOROCHOVEC ActionScript in Action
22 Adventures In ActionScript: Adding Categories To XML
BY HUW COLLINGBOURNE LiveCycle
26 Inroduction To LiveCycle Collaboration Service
BY RUSS FERGUSON Flex on Java
32 Flex on Java
BY BERNERD ALLMON AND JEREMY ANDERSON
Spring DM
40 Spring Dynamic Modules in Action
BY ARNAUD COGSOLUEGNES, THIERRY TEMPLIER, AND AN
DY PIPER TechTrends
46 Smartphones and Tablets Go Multicore: Now What?
BY TIM KRIDEL FOR INTELLIGENCE IN SOFTWARE
Tip of the issue
Smoothing bitmaps with jsfl by Tom Rassweiler
If you are creating code driven animations with bitmaps, e.g. rotating, or scaling bitmaps in your code, it is important to make sure that “allow smoothing” is checked of in the bitmap properties so that the images do not appear jagged. This can be a time consuming process, especially if you are using 3D animation rendered as many bitmaps. JSFL can provide an easy solution.
Run this command:
l.outputPanel.clear();
var item _ array = l.getDocumentDOM().library.items;
var i = item _ array.length;
while(i--){
var item = item _ array[i];
if(item.itemType == „bitmap”){
if(item.allowSmoothing == false){
item.allowSmoothing = true;
}
}
}
Influxis www.influxis.com
..........................................1, 2, 3
PlugrMan
www.plugrman.com
.......................................... 11
Flash&Math
www.flashandmath.com
....................................
31
SapphireSteel Software www.sapphiresteel.com
....................................
45
ActionScriptJobs.org
www.actionscriptjobs.com
................................
48
MonoGram CoverPage ™
www.monograminteractive.com
.......................
49
Sponsors of the Issue
09/2011 (27)
6
TECH CORNER
11 Tips for Mobile Software Development
09/2011 (27)
7
T
hat trend means, sooner or later, you’ll have to develop smartphone apps. Here are 11 tips:
Track market shares
It’s critical to keep up with trends in smartphone platforms, where the only constant is change. Sure, BlackBerry has long been synonymous with business, but it now lags both Android and Apple’s iOS in the race for market share, which affects what your company uses. In fact, Android is a case study in how quickly a platform’s fortunes can change: Between late 2009 and late 2010, Android’s market share grew 615 percent – enough to leapfrog into first place, says analyst firm Canalys
.
MeeGo and Windows Mobile are two other platforms to monitor. And don’t overlook Symbian, especially if your company has a lot of employees based outside of North America.
Learn the language
Platform companies try to build market share by using programming languages and equipment that developers already know. For example, Windows Mobile lets developers reuse their existing Visual Studio and .NET development skills and server infrastructure to extend their applications to mobile devices. Meanwhile, iOS requires Objective-C development. Partnerships and outsourcing are two ways to develop for platforms that use unfamiliar languages.
Develop for multiple platforms
Cross-platforming requires time and resources, but it ensures that your app’s fate isn’t tied to a single platform. One obvious way is by creating a separate app for each platform. But some developers say it can be cheaper, 11 Tips for Mobile Software Development
More than 99 million smartphones shipped in just the first quarter of this year, says analyst firm IDC
. Many of them are winding up in the hands of business users, including your employees and business partners. 01
02
03
09/2011 (27)
6
TECH CORNER
11 Tips for Mobile Software Development
09/2011 (27)
7
easier and faster to use CSS to recode Web apps to fit small screens, and then use JavaScript to control the events. The downside is that you might lose access to some of the device’s features, such as an accelerometer.
Look beyond smartphones
Android and iOS now run on tablets too. The good news is that apps originally developed for smartphones can typically run on tablets without modification. But be aware that tablet users increasingly expect developers to create versions that take advantage of their devices’ larger screens and often faster processors. So identify tablet-
specific features and leverage those when developing a tablet-only version of your app. Strive for consistency
It can be challenging to develop an app so it has the same look and feel across all Android or BlackBerry devices, let alone across multiple platforms or across both smartphones and tablets. But it’s still a goal worth pursuing, because most enterprises have a mix of devices. For starters, create a database of all of your company’s approved devices and their features – particularly screen size, resolution and aspect ratio – and whether they have a physical or virtual keyboard. Then, design your app to ensure that every function provides at least a basic, user-friendly experience for each device’s user group.
Identify integration needs
If your app needs to tap into another system, such as your company’s CRM and other back-office systems, it’s never too early to figure out how your app will get that access. Just as important, ensure that it gets access in a way that doesn’t leave data in the open and doesn’t create back doors for hackers. Once you’ve got a beta app, test it to verify that the integration works.
Don’t hog the CPU and memory
Sure, many of today’s smartphones have 1 GHz or faster processors and are connected to networks with speeds north of 1 Mbps. But many don’t, so it’s important to develop apps that provide a good user experience even on midrange handsets and older, slower networks. Most of today’s mobile platforms now support some level of multitasking, meaning your app will likely compete with TIM KRIDEL FOR INTELLIGENCE IN SOFTWARE
several others for processing, memory and battery power. But be aware that no two platforms support multitasking quite the same way. For example, check whether a platform allows your app to do everything you need it to when it’s running in the background.
Be aware of carrier restrictions
Wireless carriers have the power to block apps, such as those that compete with their fee-based services, or use what they deem as excessive amounts of bandwidth. Learn about these concerns and respect them rather than trying to do an end run. Be aware that even low-
bandwidth apps can clog up cellular networks – and sap batteries – by constantly generating unnecessary signaling traffic
. For example, an overly chatty IM app
almost single-handedly crashed T-Mobile’s network in 2009.
Respect enterprise concerns
Design apps so they use bandwidth sparingly, which helps users stay under their rate plan’s monthly usage cap and avoids the need for putting all mobile employees on a pricey unlimited-use plan. Bandwidth efficiency also helps extend battery life. Ideally, your app should not be the reason why a tablet or smartphone can’t go an entire workday before it needs charging.
Register with app stores and developer networks
Registering with developer networks gets you access to their SDKs, while registering as a publisher ensures you get paid. Even if you’re outsourcing development, you can still register as the publisher so you can manage the sales revenue.
Certify
Some app stores require certification, a process that includes vetting at both the platform and network usage levels. Certification often takes longer than developers expect, so don’t build your business model around the assumption that your app will be ready for employees the day after it’s finished.
04
05
06
07
08
09
10
11
09/2011 (27)
8
SPECIAL REPORT
09/2011 (27)
T
hose specs are designed to be consistent across multiple vendors, making it easier to develop software and applications for smartphones. By 2013, the organization says its specs will be in 100 percent of smartphones – up from 20 percent in 2009.
We recently sat down with Joel Huloux, MIPI Alliance chairman of the board, to get a sense of how his organization’s interface specs are helping address one of the mobile market’s biggest headaches: fragmentation.
Q: Next month marks the MIPI Alliance’s eighth anniversary. But for many software developers, this interview probably is the first time they’ve heard of your organization. Why?
Huloux:
Historically, software developers have never been very active in the MIPI organization. Most of the time, when we court software developers, they see MIPI as hardware development specifications. In some ways, that’s true because most of the work we’ve done is to consolidate the different interfaces in mobile terminals, starting from the camera and display.
Today, we have a common set of specifications that will be the same for any display that are connected to the application processor. We’ve also done some memory work that’s also very useful for software. I believe that more and more software developers do see the implementation of MIPI specifications in the platform. Before 2010, from a software point of view, all of the specifications we were building were quite far from their day-to-day occupation. Today, because more and more companies are implementing the MIPI interface, we do see that software developers have an interest to do something there. Within the Technical Steering Group of the MIPI Alliance, now there are more and more people looking to define specific technologies, which will be very relevant to the job of the software developers.
The Fragmented Mobile Device Market
If you’re a mobile software developer, the MIPI Alliance (
MIPI.org
) belongs on your radar. Since it was founded in July 2003, the organization has released more than 30 interface specs for processors, radios, displays, cameras and other components in mobile devices. 09/2011 (27)
8
SPECIAL REPORT
09/2011 (27)
Q: How exactly does MIPI’s work reduce the lead time, costs and headaches of developing for mobile devices?
Huloux:
One of the benefits of understanding the MIPI interfaces is that there’s one common area to go to for all of the peripherals: the RF and the processors. So a software developer that has knowledge about MIPI interfaces is going to be one step ahead. That’s certainly going to save time from a design standpoint. Also, regardless of the OS, the MIPI specifications are consistent across the board. Design reuse is another key factor.
One of the reasons MIPI was founded was to address fragmentation. There are a lot of proprietary interfaces out there. Oftentimes that’s a company’s first response to address a new technology: develop their own interface. That’s a costly endeavor. If a company can go to some standardized interfaces that are extremely flexible, that are optimized for the mobile applications space, that address the entire mobile ecosystem, there are no other organizations that address the entire phone. Q: So by looking at the MIPI specs in a device, developers can understand what all of the hardware can support?
Huloux:
You would need to study one specification because we have been able to consolidate the display specification on one side and the camera specification on the other. Studying the MIPI specification, the software guys know how to build one driver.
Q: The more consumers and business users rely on their mobile phones and tablets, the more important it is for those devices to be able to last an entire day before they need a charge. Is MIPI doing anything to make it easier for developers to create energy-
efficient software?
Huloux:
We have a new group that’s working on a battery interface. We haven’t announced any details, but the focus of this group is not only power management, but also green power. We’ll probably have some more information in the third quarter.
TIM KRIDEL FOR INTELLIGENCE IN SOFTWARE
1
0
IN BRIEF
09/2011 (27)
New on Adobe Labs: Flash Player 11 beta 2 and AIR 3 beta 2
StageVideo now supported on mobile with AIR3!!
There are some movement in the Adobe Labs, so for a quick reminder, here is the most important new features what you can find and play with in these prereleases. So here is some of the best new features of the betas: For Flash Player 11 it has to be Stage3D (the API previously know as Molehill). 3D on the web is nothing new but when all of a sudden (just about) every web user has 3D capabilities it becomes a whole different ball game. Some of the early demos are absolutely mind-blowing. Another great feature in Flash Player 11 (and an easy one to miss) is native JSON support! (Both features are also available in AIR 3. Stage3D currently only available for desktop, but it will be enabled for mobile in a future release.)
AIR 3 beta 2 is also a really exciting beta release! For AIR 3 is definitely the ability to add the AIR runtime to your installer package. So with AIR 3 you can control exactly which version of the runtime an app executes against and make the installation process a lot easier as well. Hardware accelerated video (aka StageVideo) on mobile is also a big one. And let’s not forget the addition of the encrypted local storage feature on mobile.
Both betas are available on labs.adobe.com. Flash on!
source: Serge Jespers
Adobe Edge – HTML5 Development Tool
Adobe further embraces HTML5 with Adobe Edge. As we already know, thanks to HTML5, Flash can focus on more intuitive solutions, so it still will be the leading innovative technology for the Internet. So Adobe wants to provide the best tools for every developer, no metter of which technologies they choose. Adobe Edge will help to develop animated websites in a similar UI with Flash Professonal, in HTML5 CSS and JavaScript. It is free while in beta stage, if you’re interested, try it on adobe.com
source: hwsw.hu
Updated guidance on Flash Builder 4.5 compatibility with Mac OS X 10.7
Following the release of Mac OS X 10.7 (Lion) recently, Adobe issued guidance recommending that Flash Builder customers should not upgrade to the latest version of the operating system due to compatibility issues.
This guidance was based upon testing with earlier pre-release builds of Lion made available to Adobe and other software vendors. Now that we have had an opportunity to undertake further testing with the final release of Mac OS X 10.7, we are pleased to report that there are only minor usability issues when using Flash Builder 4.5.1 on Mac OS X 10.7 and, as such, we will be updating our previous statement to confirm compatibility of these releases.
Known Issues
There is one issue that affects new installations of Flash Builder 4.5.1 on Mac OS X 10.7 – before running the Flash Builder installer, you should install Java for Mac OS X. Failure to do this will result in Flash Builder 4.5, rather than 4.5.1 being installed on the system.
There is also one usability issue that will affect all users of Flash Builder on Mac OS X 10.7 – right-clicking in the package explorer may stop working after prolonged use of Flash Builder. To resolve the issue Flash Builder must be restarted.
Finally, the Flash Builder installer includes a version of Flash Player that is not recommended for use with Mac OS X 10.7. Rather than installing the default version, you should download and install the latest debugger version fromAdobe.com.
Please note that Flash Builder 4 remains incompatible with Mac OS X 10.7
. Upgrades from Flash Builder 4.0 to Flash Builder 4.5.1 are available for $49.
source: The Official Flex Team Blog
Emerging Technology and Advertising, October 14, 2011 Toronto, ON Canada
Marketing is at a crossroads. Significant changes in consumer behaviour and needs, paired with a dynamically changing marketing toolkit, has resulted in a challenging new landscape for marketers. To solve the problems we now face requires a new way of thinking and planning. Emerging Technology and Advertising event
(ETA) is about breaking ingrained assumptions and removing the blinders to new and innovative ways to think about marketing.
ETA event brings together seven brilliant speakers who all have an interest and an educated opinion on emerging technology and how it will impact advertising and marketing. These speakers are coming together for one day in Toronto to lead a conversation that will outline the future shape of the advertising and marketing industries. http://www.fitc.ca/events/about/?event=123
News selected by Gábor Csomák
09/2011 (27)
1
2
FLEX DEVELOPMENT
T
he first framework that we discuss in detail in our article is Swiz. If you are starting your development with Adobe Flex and not yet familiar with the consolidated frameworks in the market, Swiz is one of the most used frameworks for developing Adobe Flex applications.
Currently, Swiz is on version 1.3.1, and their support for mobile devices is available since version 1.0. In its early versions, its support was through a file. SWC separated from the current project, however, since version 1.2.0 occurs through their support of it .SWC used for projects that use the 4.x version of the Flex SDK.
It can be downloaded in the framework site with no mystery (
http://www.swizframework.org
), or via your repository on github (
https://github.com/swiz/swiz-
framework/
). The Swiz is not a MVC framework, its great facilitators are:
Inversion of Control
The inversion of control in Swiz provides the developer the ability to add classes, into a BeanLoader container, within a framework that should allow the injection of dependencies. They become the responsible for instance at the beginning of the application using the design pattern Singleton, thus only one instance of the registered objects are created. They are often registered as beans in the container classes, models, controllers, delegates and services.
Bean Life Cycle Management
Another important feature that we should highlight the Swiz, is that it provides to developer an event-
based mechanism for the creation and destruction of objects. You can have control of only the creation of a bean and its removal, as well as its addition or removal of Singleton based BeanFactory. You can also use metadata such as
[PostConstruct]
and [PreDestroy] to create triggers at the time of creation and removal of a bean.
Dependence Injection
The DI pattern, suggests that in some scenarios its application layer does not have the need for instantiation of objects. Dependency injection is the responsibility of Swiz to inject a object registered in our BeanLoader on some application layer. This dependency injection occurs through the use of a simple Metadata called [Inject], te most common are:
• Inject Model into View;
• Inject Model into Controller;
• Inject Delegate into Controller;
• Inject Service into Delegate;
Mediation of events
One of the great facilitators Swiz is its treatment of events inside the application. His concept removes from the developer the need to use methods such Adobe Flex Mobile, Swiz Framework and FlexORM
The purpose of this article is to demonstrate how you can create a Adobe Flex application to run on mobile devices, using two frameworks, Swiz and FlexORM.
What you will learn…
• How to create Flex Mobile projects;
• How to con�gure and create projects using Swiz Framework;
• How to con�gure and create projects using Flex ORM;
• Some important concepts about design patters for Flex projects;
What you should know…
• Basic knowledge of Flex 4
• Basic knowledge of OOP concepts
Adobe Flex Mobile, Swiz Framework and FlexORM
09/2011 (27)
1
3
Listing 1. Class representing Persistence Model
package
com
.
horochovec
.
model
{
[
Bindable
]
[
Table
(
name
=
"contact"
)]
public
class
Contact
{
private
var
_id
:
int
;
private
var
_name
:
String
;
[
Id
]
public
function
get
id
()
:
int
{
return
_id
;
}
public
function
set
id
(
value
:
int
)
:
void
{
_id
= value
;
}
[
Column
(
name
=
"name"
)]
public
function
get
name
()
:
String
{
return
_name
;
}
public
function
set
name
(
value
:
String
)
:
void
{
_name
= value
;
}
}
}
Listing 2. Our Generic Data Access Object Class
package
com
.
horochovec
.
dao
{
import
lash
.
data
.
SQLConnection
;
import
lash
.
ilesystem
.
File
;
import
mx
.
collections
.
ArrayCollection
;
import
nz
.
co
.
codec
.
lexorm
.
EntityManager
;
public
class
GenericDAO
{
/**
* Controller for a Singleton
*/
public
static
var
instance
: GenericDAO
;
/**
* EntityManager
*/
private
var
dao
: EntityManager
= EntityManager
.
getInstance
();
/**
* Constructor
*/
public
function
GenericDAO
()
{
var
appDataBase
: File
= File
.
application
StorageDirectory
.
resolvePath
(
"swizandlexorm.db"
);
var
sqlConn
: SQLConnection
= new
SQLConnection
();
sqlConn
.
open
(
appDataBase
);
this
.
dao
.
sqlConnection
= sqlConn
;
}
/**
* Get a instance for GenericDAO class
*/
public
static
function
getInstance
()
: GenericDAO
{
if
(
instance
== null
)
instance
= new
GenericDAO
();
return
instance
;
}
/**
* Persist a object into our database
*/
public
function
persist
(
object
:
Object
)
: void
{
this
.
dao
.
save
(
object
);
}
/**
* Merge a object into our database
*/
public
function
merge
(
object
:
Object
)
: void
{
this
.
dao
.
save
(
object
);
}
/**
* Remove a object in our database
public function remove(object:Object) : void
{
this.dao.remove(object);
}
/**
* Get a list of determined object
*/
public
function
listAll
(
clazz
:
Class
)
: ArrayCollection
{
return
this
.
dao
.
indAll
(
clazz
);
}
}
}
09/2011 (27)
1
4
FLEX DEVELOPMENT
Adobe Flex Mobile, Swiz Framework and FlexORM
09/2011 (27)
1
5
as addEventListner in your application, simply add the metadata [EventHandler]
, the Swiz will automatically create an event listner to the object and invoke the desired method when the event is captured. To trigger an event, it can be done in two ways, through the dispatchEvent()
method present in all components to interfaces, or where necessary through the use of a nonvisual object, you can use the metadata [Dispatcher]
.
ServiceHelper
Another great feature is the ServiceHelper on Swiz. It is used as a great facilitator for interaction with services such as RemoteObject
, HTTPService and WebService running the service and returning a AsyncToken
. In our example, we will use to run our persistence as if we used a RemoteObject or other any service running on Web. So at some point, if necessary change the shape of the persistence of our application, it will be totally independent of the business rule applied.
ViewNavigator
This Metadata was added in this latest release of Swiz, and its purpose is to allow navigation between screens of our application powering the exchange of PresentationModel through our windows. The use of design patter Presetentation Model is strongly Listing 3. ContactEvent implementation
package
com
.
horochovec
.
event
{
import
com
.
horochovec
.
model
.
Contact
;
import
lash
.
events
.
Event
;
import
mx
.
collections
.
ArrayCollection
;
public
class
ContactEvent
extends
Event
{
/**
* Type for Add a new Contact
*/
public
static
const
ADD_CONTACT
: String
= "ADD_
CONTACT"
;
/**
* Type for Delete a Contact
*/
public
static
const
DEL_CONTACT
: String
= "DEL_
CONTACT"
;
/**
* Type for Update a Contact
*/
public
static
const
UPD_CONTACT
: String
= "UPD_CONTACT"
;
/**
* Type for obtain a List of Contacts
*/
public
static
const
LIST_CONTACT
: String
= "LIST_CONTACT"
;
/**
* Type for a list will returned
public static const LIST_RETURNED: String = "LIST_RETURNED";
/**
* Contact object
*/
public
var
contact
: Contact
;
/**
* ArrayCollection for dataProvider with Contact list
*/
public
var
dataProvider
: ArrayCollection
;
public
function
ContactEvent
(
type
:
String
, bubbles
:
Boolean
=
true
, cancelable
:
Boolean
=
false
)
{
super
(
type
, bubbles
, cancelable
);
}
override
public
function
clone
()
:
Event
{
return
new
ContactEvent
(
type
, bubbles
, cancelable
);
}
}
}
09/2011 (27)
1
4
FLEX DEVELOPMENT
Adobe Flex Mobile, Swiz Framework and FlexORM
09/2011 (27)
1
5
recommended for a better structure and maintenance of your application.
These six features are in my opinion, the key to be analyzed to begin developing applications using the Swiz Framework.
The second framework we will look before we started our project is the FlexORM. The objective of this framework is the object-relational mapping for projects using SQLite as embedded database.
The FlexORM is a creation of Mark Moloney and is hosted by RIAForge (
http://flexorm.riaforge.org/
). We list some of its advantages for their use:
•
No need to create and update tables. The FlexORM takes care of creating the database structure through a mapping done within the object to be persisted;
•
Supports for CRUD operations;
•
Supports associations 1: N, N, M, N: 1 and 1:1;
•
Support for transient attributes;
•
Support for consistency constraints, foreign keys, triggers using SQLite;
•
Transactions;
•
Automatic creation of indexes;
•
Lazy Loading;
•
Among other;
Listing 4. ContactService implementation
package
com
.
horochovec
.
service
{
import
com
.
horochovec
.
dao
.
GenericDAO
;
import
com
.
horochovec
.
model
.
Contact
;
import
mx
.
rpc
.
AsyncToken
;
import
org
.
swizframework
.
utils
.
services
.
MockDelegat
eHelper
;
public
class
ContactService
{
/**
* Mock for services
*/
private
var
mockDelegateHelper
: MockDelegateHelper
;
/**
* GenericDAO for CRUD operations
*/
private
var
genericDAO
: GenericDAO
= GenericDAO
.
getInstance
();
* Class
for
list
method
*/
private
var
contactClass
: Class
= Contact
;
public
function
ContactService
()
{
mockDelegateHelper
= new
MockDelegateHelper
();
}
/**
* Persist an object into our database
*/
public
function
persist
(
contact
: Contact
)
: AsyncToken
{
this
.
genericDAO
.
persist
(
contact
);
return
mockDelegateHelper
.
createMockResult
(
this
.
genericDAO
.
listAll
(
contactClas
s
)
);
}
/**
* Remove an object into our database
*/
public
function
remove
(
contact
: Contact
)
: AsyncToken
{
this
.
genericDAO
.
remove
(
contact
);
return
mockDelegateHelper
.
createMockResult
(
this
.
genericDAO
.
listAll
(
contactClas
s
)
);
}
/**
* Get a list of objects
*/
public
function
listContact
()
: AsyncToken
{
return
mockDelegateHelper
.
createMockResult
(
this
.
genericDAO
.
listAll
(
contactClas
s
)
);
}
}
}
09/2011 (27)
1
6
FLEX DEVELOPMENT
Adobe Flex Mobile, Swiz Framework and FlexORM
09/2011 (27)
1
7
Listing 5. ContactController implementation
package
com
.
horochovec
.
controller
{
import
com
.
horochovec
.
event
.
ContactEvent
;
import
com
.
horochovec
.
model
.
Contact
;
import
com
.
horochovec
.
service
.
ContactService
;
import
lash
.
events
.
IEventDispatcher
;
import
mx
.
rpc
.
events
.
ResultEvent
;
import
org
.
swizframework
.
utils
.
services
.
ServiceHelper
;
public
class
ContactController
{
/**
* Event Dispatcher
*/
[
Dispatcher
]
public
var
dispatcher
:
IEventDispatcher
;
/**
* ContactService
*/
[
Inject
]
public
var
contactService
: ContactService
;
/**
* ServiceHelper
*/
[
Inject
]
public
var
serviceHelper
: ServiceHelper
;
/**
* Call ContactService for add a new Contact
*/
[
EventHandler
(
event
=
"ContactEvent.ADD_CONTACT"
, properties
=
"contact"
)]
public
function
addContact
(
contact
: Contact
)
: void
{
this
.
serviceHelper
.
executeServiceCall
(
contactService
.
persist
(
contact
)
, addContactResultHandler
);
}
/**
* Call ContactService for delete a Contact
*/
[
EventHandler
(
event
=
"ContactEvent.DEL_CONTACT"
, properties
=
"contact"
)]
public
function
delContact
(
contact
: Contact
)
: void
{
this
.
serviceHelper
.
executeServiceCall
(
contactService
.
remove
(
contact
)
, delContactResultHandler
);
}
/**
* Call ContactService for update a Contact
*/
[
EventHandler
(
event
=
"ContactEvent.UPD_CONTACT"
, properties
=
"contact"
)]
public
function
updContact
(
contact
: Contact
)
: void
{
}
/**
* Call ContactService for list the Contacts into our database
*/
[
EventHandler
(
event
=
"ContactEvent.LIST_CONTACT"
)]
public
function
listContact
()
: void
{
this
.
serviceHelper
.
executeServiceCall
(
contactService
.
listContact
()
, listContactResultHandler
);
}
/**
* ResultEvent for listContact function
*/
private
function
listContactResultHandler
(
event
: ResultEvent
)
:
void
{
var
contactEvent
: ContactEvent
= new
ContactEvent
(
ContactEvent
.
LIST_RETURNED
);
contactEvent
.
dataProvider
= event
.
result
as
ArrayCollection
;
this
.
dispatcher
.
dispatchEvent
(
contactEvent
);
}
/**
* ResultEvent for addContact function
*/
private
function
addContactResultHandler
(
event
: ResultEvent
)
:
void
{
trace
(
'add'
);
}
/**
* ResultEvent for delete function
*/
private
function
delContactResultHandler
(
event
: ResultEvent
)
: void
{
trace
(
'delete'
);
}
/**
* ResultEvent for updContact function
*/
private
function
updContactResultHandler
(
event
: ResultEvent
)
: void
{
trace
(
'update'
);
}
}
}
09/2011 (27)
1
6
FLEX DEVELOPMENT
Adobe Flex Mobile, Swiz Framework and FlexORM
09/2011 (27)
1
7
Listing 6a. Presentation Model implementation
package
com
.
horochovec
.
views
.
contact
{
import
com
.
horochovec
.
event
.
ContactEvent
;
import
com
.
horochovec
.
model
.
Contact
;
import
lash
.
events
.
IEventDispatcher
;
import
mx
.
collections
.
ArrayCollection
;
import
spark
.
components
.
ViewNavigator
;
[
Bindable
]
public
class
ContactPM
{
/**
* Dispatcher
*/
[
Dispatcher
]
public
var
dispatcher
:
IEventDispatcher
;
/**
* ViewNavigator to change the views
*/
[
ViewNavigator
]
public
var
viewNavigator
: ViewNavigator
;
/**
* Contact
*/
public
var
contact
:
Contact
;
/**
* Dataprovider for List
*/
public
var
dataProvider
:
ArrayCollection
;
/**
* Constructor
*/
public
function
ContactPM
()
{
this
.
contact
= new
Contact
();
}
/**
* Click on button to change view to List all Contacts
*/
public
function
btnListContactClickHandler
()
: void
{
var
contactEvent
: ContactEvent
= new
this
.
dispatcher
.
dispatchEvent
(
contactEvent
);
this
.
viewNavigator
.
pushView
(
List
);
}
/**
* Click on button to change view to Add a new Contact
*/
public
function
btnAddContactClickHandler
()
: void
{
this
.
contact
= new
Contact
();
this
.
viewNavigator
.
pushView
(
Add
);
}
/**
* Function called before click on List Component
*/
public
function
viewDetail
(
object
:
Contact
)
: void
{
this
.
contact
= object
;
this
.
viewNavigator
.
pushView
(
Add
);
}
/**
* Click on button to create a new object
*/
public
function
btnNewClickHandler
()
: void
{
this
.
contact
= new
Contact
();
}
/**
* Click on button to save or update a object
*/
public
function
btnSaveClickHandler
()
: void
{
var
contactEvent
: ContactEvent
;
if
(
this
.
contact
.
id
> 0
)
contactEvent
= new
ContactEvent
(
ContactEvent
.
UPD_CONTACT
);
else
contactEvent
= new
ContactEvent
(
ContactEvent
.
ADD_CONTACT
);
contactEvent
.
contact
= this
.
contact
;
this
.
dispatcher
.
dispatchEvent
(
contactEvent
);
this
.
contact
= new
Contact
();
09/2011 (27)
1
8
FLEX DEVELOPMENT
Adobe Flex Mobile, Swiz Framework and FlexORM
09/2011 (27)
1
9
After presenting the frameworks that will be used, we will leaving for the development of our example. The example is a simple address book, the purpose of this article is not to develop a great application but to show how we can use concepts of good frameworks so that they can help us in our daily work.
In your Adobe Flash Builder, open the menu: File, New, Flex Mobile Project
Step 1 – Project Location
•
Project Name: SwizAndFlexORM;
•
Project Location: Use default location;
•
Use a specific SDK: 4.5.1;
•
Click on Next;
Step 2 – Mobile Settings
•
Target Platforms: Google Android;
•
Application Template: View-Based Application;
•
Initial view title: HomeView
•
Application Template:
•
Automatic reorient: true;
•
Full screen: false;
•
Automatically scale application for different screen densities: false;
Listing 6b. Presentation Model implementation
}
/**
* Click on button to delete a object
*/
public
function
btnDeleteClickHandler
()
: void
var
contactEvent
: ContactEvent
= new
ContactEvent
(
ContactEvent
.
DEL_
CONTACT
);
contactEvent
.
contact
= this
.
contact
;
this
.
dispatcher
.
dispatchEvent
(
contactEvent
);
this
.
contact
= new
Contact
();
}
/**
* EventHandler to trigger the event to get the result of search Contacts
*/
[
EventHandler
(
event
=
"ContactEvent.LIST_
RETURNED"
, properties
=
"dataProvide
r"
)]
public
function
getListContact
(
dataProvider
: ArrayCollection
)
: void
{
this
.
dataProvider
= dataProvider
;
}
}
}
Listing 7. Our Fisrt View – Add
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
s
:
View
xmlns
:
fx
=
"http://ns.adobe.com/mxml/2009"
xmlns
:
s
=
"library://ns.adobe.com/lex/spark"
title
=
"New Contact"
>
<
fx
:
Script
>
<!
[
CDATA
[
[
Inject
(
source
=
"contactPM"
)]
[
Bindable
]
public
var
contactPM
:
ContactPM
;
]]
>
</
fx
:
Script
>
<
s
:
actionContent
>
<
s
:
Button
id
=
"btnListContact"
label
=
"List"
click
=
"{this.contactPM.btnListContactClick
Handler()}"
/>
</
s
:
actionContent
>
<
s
:
Label
left
=
"10"
top
=
"20"
text
=
"ID"
/>
<
s
:
Label
left
=
"10"
top
=
"120"
text
=
"Name"
/>
<
s
:
TextInput
left
=
"10"
right
=
"10"
top
=
"45"
text
=
"{this.contactPM.contact.id}"
editable
=
"false"
/>
<
s
:
TextInput
left
=
"10"
right
=
"10"
top
=
"145"
text
=
"@{this.contactPM.contact.name}"
/>
<
s
:
HGroup
left
=
"10"
right
=
"10"
top
=
"230"
height
=
"80"
>
<
s
:
Button
width
=
"33%"
label
=
"New"
click
=
"{this.contactPM.btnNewClickHandler(
)}"
/>
<
s
:
Button
width
=
"33%"
label
=
"Save"
<
s
:
Button
width
=
"33%"
label
=
"Delete"
click
=
"{this.contactPM.btnDeleteClickHandl
er()}"
/>
</
s
:
HGroup
>
</
s
:
View
>
09/2011 (27)
1
8
FLEX DEVELOPMENT
Adobe Flex Mobile, Swiz Framework and FlexORM
09/2011 (27)
1
9
•
Permissions: Plataform: Google Android
•
Permission: WRITE _ EXTERNAL _ STORAGE
;
•
Click on Next;
Step 3 – Server Settings
•
Application server type: None/Other;
•
Click on Finish;
Step 4 – Adding the frameworks to project •
On menu: Project, Properties;
•
Select the option: Flex Build Path;
•
Select the option: Library path;
•
Select the button: Add SWC;
•
Add the SWC for FlexORM and Swiz to your project;
Step 5 – Create our model class
As mentioned earlier, it is not necessary to create the structure of tables in our database when we use the FlexORM. He is responsible for creating and updating tables based on existing classes that represent entities in the database.
•
On menu: File, New, ActionScript Class;
•
Package: com.horochovec.model;
•
Name: Contact;
Result:
package com.horochovec.model
{
public class Contact
{
public function Contact()
{
}
}
}
To identify which table of our database we are using, we will use the Metadata [Table]
in declaring our class.
Now we will add two attributes to our class, the first is the id of the record persisted, and second, the person’s name added to our contact list. For the first attribute, we will add the Metadata [Id]
, indicating that the attribute is a key sequence in the database, and the second attribute, we will add the Metadata [Column]
indicating Listing 8. Our Second View – List
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
s
:
View
xmlns
:
fx
=
"http://ns.adobe.com/mxml/2009"
xmlns
:
s
=
"library://ns.adobe.com/lex/spark"
title
=
"Contact List"
>
<
fx
:
Script
>
<!
[
CDATA
[
[
Inject
(
source
=
"contactPM"
)]
[
Bindable
]
public
var
contactPM
:
ContactPM
;
]]
>
</
fx
:
Script
>
<
s
:
actionContent
>
<
s
:
Button
id
=
"btnAddContact"
label
=
"Add Contact"
click
=
"{this.contactPM.btnAddConta
ctClickHandler()}"
/>
</
s
:
actionContent
>
<
s
:
List
left
=
"10"
right
=
"10"
top
=
"10"
bottom
=
"10"
id
=
"list"
dataProvider
=
"{this.contactPM.dataProvider}"
labelField
=
"name"
click
=
"{contactPM.viewDetail(this.list.selected
Item)}"
/>
</
s
:
View
>
Listing 9. Our Swiz Con�guration �le
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
BeanProvider
xmlns
:
fx
=
"http://ns.adobe.com/mxml/2009"
xmlns
:
s
=
"library://ns.adobe.com/lex/spark"
xmlns
=
"http://swiz.swizframework.org"
xmlns
:
controller
=
"com.horochovec.controlle
r.*"
xmlns
:
service
=
"com.horochovec.service.*"
xmlns
:
pm
=
"com.horochovec.views.contact.*"
>
<
ServiceHelper
id
=
"serviceHelper"
/>
<
service
:
ContactService
id
=
"contactService"
/>
<
controller
:
ContactController
id
=
"contactController"
/>
<
pm
:
ContactPM
id
=
"contactPM"
/>
</
BeanProvider
>
09/2011 (27)
2
0
FLEX DEVELOPMENT
which column of our table is referring to the attribute. Result see Listing 1.
Step 6 – Create our Data Access Object Class
Now we’ll create a class that will be responsible for making access to our database and will also be responsible for basic CRUD operations.
•
On menu: File, New, ActionScript Class;
•
Package: com.horochovec.dao;
•
Name: GenericDAO (Listing 2);
At this point we’ve done all the necessary implementations to use the FlexORM. We create our bean that represents an entity in our database, we add the necessary metadata for your understanding, and create a DAO to perform CRUD operations in our our application. That done, leave for the structuring of our application to use the Swiz Framework.
Step 7 – Create our ContactEvent class
The Swiz is a framework that works as an event-driven, other words, communication between services occur through triggered events, where a controller driven classes and functions as they occur notifications, so it is necessary to create a class for defining which events are triggered by our application.
•
On menu: File, New, ActionScript Class;
•
Package: com.horochovec.event;
•
Name: ContactEvent; (Listing 3)
Right now, we have all our events that are fired in our application set. Step 8 – Implementing our ServiceHelper
This class is responsible for implementing our CRUD methods. If you require a change to our persistence, only this class will change in our application.
•
On menu: File, New, ActionScript Class;
•
Package: com.horochovec.service;
•
Name: ContactService; (Listing 4)
Step 9 – Creating our ContactController Class
The objective of this class is to centralize business rules for executions of services related to our CRUD.
•
On menu: File, New, ActionScript Class;
•
Package: com.horochovec.controller;
•
Name: ContactController; (Listing 5)
Step 10 – Creating our Presentation Model Class
With this technique, we have the possibility of removing the ActionScript code to our views, that is, our class that accesses our controller to perform tasks not need to understand the behavior of View, and in turn, the View does not need to worry with your controller, just observe their behavior and update when necessary.
•
On menu: File, New, ActionScript Class;
•
Package: com.horochovec.views.contact;
•
Name: ContactPM; (Listing 6)
Step 11 – Creating our �rst View – Add
In this step, we create our first view for our application, it will be responsible for the registration of new contacts. Note that the only reference to other classes is to create an object contactPM with type ContactPM. It made it through Dependency Injection of metadata [Inject]
. And at some point in our View, we make reference to contactPM for information objects and events of some components of our view, nothing else, the View does not know of the existence of all of our Listing 10. Creating our Presentation Model Class
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
s
:
ViewNavigatorApplication
xmlns
:
fx
=
"http://
ns.adobe.com/mxml/2009"
xmlns
:
s
=
"library://ns.adobe.com/lex/
spark"
xmlns
:
swiz
=
"http://
swiz.swizframework.org"
xmlns
:
conig
=
"com.horochovec.conig.*"
irstView
=
"com.horochovec.views.contact.Add"
>
<
fx
:
Declarations
>
<
swiz
:
beanProviders
>
<
conig
:
Beans
/>
</
swiz
:
beanProviders
>
<
swiz
:
conig
> <
swiz
:
SwizConig
eventPackages
=
"com.horo
chovec.event.*"
viewPackages
=
"com.horochovec.views.con
tact.*"
/>
</
swiz
:
conig
> </
swiz
:
Swiz
>
</
fx
:
Declarations
>
</
s
:
ViewNavigatorApplication
>
Adobe Flex Mobile, Swiz Framework and FlexORM
09/2011 (27)
2
1
application. Being completely decoupled from all the business rules created so far.
•
On menu: File, New, MXML Component;
•
Package: com.horochovec.views.contact;
•
Name: Add;
•
Layout: None;
•
Based on: spark.components.View; (Listing 7)
Step 12 – Create our View – List
•
On menu: File, New, MXML Component;
•
Package: com.horochovec.views.contact;
•
Name: List;
•
Layout: None;
•
Based on: spark.components.View; (see Listing 8)
Step 13 – Creating the Swiz Con�g
This configuration file represents our IoC container, through him that Swiz know which objects should be created in the instance of the application and make dependency injection when they are requested.
•
On menu: File, New, File;
•
Enter ou select the parent folder: SwizAndFlexORM/src/
com/horochovec/conig
;
•
File Name: Beans.mxml; (Listing 9)
Step 14 – Final step
Finally, our last stage of the project is to add to our ViewNavigatorApplication the Swiz settings, and change the address of our firstView (Listing 10).
Now you can compile the project and install it on your phone. If you want to download the project, feel the will, it is available at this url: http://www.horochovec.com/
SwizAndFlexORM.fxp
.
I hope I have contributed to their learning, until the next opportunity.
STEFAN KUGLER HOROCHOVEC Stefan Horochovec is postgraduate degree in Software Engineering, Business Consultant in Adobe Flex/
Java at Avanti Prima Engenharia, Rio de Janeiro – Brazil and also Adobe User Group Manager of AUG – Adobe Mobile and Devices Usergroup.
a d
v e
r t
i s e m e n
t
09/2011 (27)
2
2
ACTIONSCRIPT IN ACTION
Adding Categories To XML
09/2011 (27)
2
3
O
ver the past couple of months I’ve explained how to create a Flex-based application that loads and displays data stored in XML format. You could use these techniques to create any sort of data-browsing application such as a question-and-
answer game, a list of products or (as I am doing in this series) an FAQ Browser.
In my last two columns I showed how to create an XML file, load it into memory and display the data one record
(or XML item) at a time in text fields or the columns of a data grid (Figure 1). A combo box allows the user to select different data files to be loaded so that, for example, a different set of FAQ items (or quiz questions or products lists) could be chosen by the user. The main weakness of last month’s program was that it did not provide any way of filtering the display of items. It was a case of all or nothing
. If the user were Adding Categories To XML
When displaying XML data, you may want to add ‘filters’ to display specific categories. This month, Huw Collingbourne adds filters to his FAQ Browser application. What you will learn…
• How to search for data in XML
• How to use XMLListCollections
• How to trim strings loaded from a �le
What you should know…
• The basics of XML and XMLList classes
• How to load XML (see previous columns)
• How to create a Flex user interface
Figure 1. I’ve designed the user interface for my FAQ Browser using the Amethyst IDE. The user loads a speci�c data �le by selecting an item in the combo box (bottom right) and �lters records according to the categories of the selected check boxes on the right
09/2011 (27)
2
2
ACTIONSCRIPT IN ACTION
Adding Categories To XML
09/2011 (27)
2
3
to load a data file with 100 questions and answers, all 100 would be shown in the data grid.
It would be far more useful if the Browser allowed the user to filter the display according to category. Let’s assume, for example, that this is an FAQ about Flex development. Some questions might be relevant to Spark, others to Halo, yet others to ActionScript. A Flex 3 developer might want to view all questions about Halo and ActionScript but none about Spark. How can we find a way to select specific categories of questions to display? That’s what this month’s column is about.
Adding Categories
Before doing anything else, the first thing I need to do is make sure that my XML data file contains information on the category of each question and answer data item. As explained last month, I enclose each item between a pair of <QA></QA>
tags. These enclosed two sets of nested tags: <QUESTION></QUESTION>
which encloses the text of a question and <ANSWER></
ANSWER> which encloses the text of an answer. I now need to add information on a category. I do this, predictably, by placing text between a pair of tags which I’ve called <CATEGORY></CATEGORY>
. In a sensible database, you would probably use have sensible categories such as <CATEGORY>ActionScript</CATEGORY>
or <CATEGORY>TestQuestion</CATEGORY>
. My data is based on nonsense rhymes, however, so I have decided to use three nonsense categories: Spligget, Bee and Futtock. Here is a typical data item: see Listing 1.
I’ve added three check boxes to the user interface, one for each of my three categories. The idea is that the user will be able to select one or more check boxes and then click the Refresh button in order to display only those FAQ items with the corresponding categories. I’ve also added two radio buttons, All
and Selected
. When the All
radio button is clicked, no selections are applied. When the Selected
radio button is clicked, the data is filtered to show only the items with categories that match the selected check boxes.
Applying A Filter
The real work is done in the refreshBtn_click()
method which executes when the Refresh button is clicked (see Listing 2). The aim here is to create a new XMLListCollection object with which to populate the rows of the datagrid called qagrid. If the All
radio button is checked then it simply create an XMLListCollection object from all the XML items. These items were assigned to the XMLList object, _xmlList
, when the data file was loaded and this is how an XMLListCollection is created from this:
xmlListColl = new XMLListCollection( _xmlList );
Listing 1. XML of Question and Answer Data
<
QA
>
<
CATEGORY
>
Futtock
</
CATEGORY
>
<
QUESTION
>
Do
futtocks
need
to
be
tuned
?</
QUESTION
>
<
ANSWER
>
The
Pobble
swam
fast
and
well
,
And
when
boats
or
ships
came
near
him
,
He
tinkledy
-
blinkledy
-
winkled
a
bell
,
So
that
all
the
world
could
hear
him
.
And
all
the
Sailors
and
Admirals
cried
,
When
they
saw
him
nearing
the
further
side
-
"He has gone to ish for his Aunt Jobiska's
Runcible Cat with crimson whiskers!"
</
ANSWER
>
</
QA
>
Listing 2. Show only the selected ‘categories’ of data
private
function
refreshBtn_click
(
event
: lash
.
events
.
MouseEvent
)
: void
{
var
cat
: String
;
var
ilter
: Array
= [];
var
xmlListColl
: XMLListCollection
;
if
(
allRB
.
selected
)
{
xmlListColl
= new
XMLListCollection
(
_xmlList
);
}
else
{
if
(
futtockCB
.
selected
){
ilter
.
push
(
"Futtock"
);}
if
(
spliggetCB
.
selected
){
ilter
.
push
(
"Spligget"
);}
if
(
beeCB
.
selected
){
ilter
.
push
(
"Bee"
);}
xmlListColl
= new
XMLListCollection
(
);
for
each
(
var
item
: XML
in
_xmlList
)
{
cat
= item
.
CATEGORY
;
if
(
ilter
.
indexOf
(
cat
)
> -
1
)
{
xmlListColl
.
addItem
(
item
);
}
}
}
qagrid
.
dataProvider
= xmlListColl
;
}
09/2011 (27)
2
4
ACTIONSCRIPT IN ACTION
If the Selected
radio button is checked, then we need to created an XMLListCollection containing only those items matching the selected categories. First I create an array called filter and to this array I add or push
the category names corresponding to the selected check boxes:
if( futtockCB.selected ){ilter.push( „Futtock” );}
if( spliggetCB.selected ){ilter.push( „Spligget” );}
if( beeCB.selected ){ilter.push( „Bee” );}
Now, my code traverses all the data items in _ xmlList inside a for each loop. At each turn through the loop it finds the category that was stored between the <CATEGORY></CATEGORY> tags of the XML data:
cat = item.CATEGORY;
It then tries to make a match with that category in the filter array. The indexOf method returns a value of 0 or higher if a match is made, -1 if no match is made. Only those items with a matching category are added to the XMLListCollection
:
if( ilter.indexOf( cat ) > -1 ) {
xmlListColl.addItem( item );
}
And finally the XMLListCollection is assigned to the dataProvider property of the data grid:
Listing 3. Trimming leading whitespace from multiple lines of text
private
function
trimLines
(
someText
: String
)
: String
{
// Trim lines before displaying them
// XML data may include white space at start of lines!
var
sArray
: Array
= someText
.
split
(
"\n"
);
var
trimmedString
: String
= ""
;
for
each
(
var
line
: String
in
sArray
)
{
trimmedString
+= StringHandler
.
trimStart
(
line
)
+ "\n"
;
}
return
trimmedString
;
}
Listing 4. Enabling and disabling the check boxes according to which radio button is changed
private
function
selectedRB_change
(
event
: lash
.
events
.
Event
)
: void
{
if
(
event
.
currentTarget
== selectedRB
)
{
futtockCB
.
enabled
= true
;
spliggetCB
.
enabled
= true
;
beeCB
.
enabled
= true
;
}
else
{
futtockCB
.
enabled
= false
;
spliggetCB
.
enabled
= false
;
beeCB
.
enabled
= false
;
}
}
Figure 2. I have used Amethyst’s Event palette to assign the same event-handler method, selectedRB_change() to both the ‘All’ and the ‘Selected’ radio buttons (see the Amethyst Designer in the lower window). The code examines event.currentTarget to determine which radio button was changed
Adding Categories To XML
09/2011 (27)
2
5
qagrid.dataProvider = xmlListColl;
And that is really all there is to it! Added Extras
Before wrapping up, I’d just like to mention a couple more points. One thing that you might want to bear in mind when loading XML from a file is that any indents
in the original data (many XML editors will automatically insert spaces or tabs to create indents) will be preserved after loading. That would be problematic in my application since I display multiple lines of text (the answer
) in the Text Area component when an item is clicked in the grid. This looks very odd if the lines are indented. I solve this by parsing text into an array of strings then using my StringHandler.trimStart routine (this was explained in a previous column) to remove leading whitespace (Listing 3).
One final thing that deserves mention is the code I used to disable the check boxes when the All
radio button is selected. I’ve put this code into the selectedRB_
change()
function which is designated as the event-
handler for both of the two radio buttons when the selection state of either changes (Figure 2). I determine which of the two buttons was changed using the currentTarget property of the event that is sent from the radio button to the function (Listing 4). If the target is the selectedRB radio button, my code disables all the check boxes, otherwise it enables them.
HUW COLLINGBOURNE
Huw Collingbourne is Director of Technology at SapphireSteel Software. Over more than 20 years, he has programmed in languages ranging from Ruby to C# and has been a technical columnist for computer magazines such as PC Pro and PC Plus. He is the software lead of the Amethyst Designer, the Flex user interface design environment of the Amethyst IDE for Visual Studio. SapphireSteel Software: http://
www.sapphiresteel.com/
Get The Source Code
The archive containing all the source code for this game is available for download from the SapphireSteel Software site at: http://www.sapphiresteel.com/tutorials/amethyst-tutorials/
actionscript-programming/article/faq-browser
.
� � � � � � � � � � � � �
09/2011 (27)
2
6
LIVECYCLE
T
he tricky part is in order to develop an application that can do this requires some knowledge of server side applications like Flash Media Server or LiveCycle Data Services. If the server side is not your thing you can use LiveCycle Collaboration Service.
Before we get into building a simple application, lets try to first explain what it is, and try to answer a few questions about it isn’t.
LiveCycle Collaboration Service
(LCCS) is not software that you host on your server. So there is nothing to buy. It is a service hosted by Adobe with a pay-as-you-go model. When you sign up you get a free $15 credit for the account to develop with. This credit gets renewed every month.
Once your account has been created, you are then provided with both the ActionScript and Flex SDK’s to develop your application. These SDK’s are provided for different versions of Flash Player (as of this writing players 10,10.1 and 10.3). With the SDK you write an application that connects to the service and allows you to build things like multi-user games and chat applications. Some of the features of LCCS include a whiteboard component and webcam components.
Getting Started
To use LCCS you need to create a developers account. As mentioned, a developer’s account gives you a $15 credit every month for fee to develop your application. At a later date you can change the account to a paid one if necessary. Introduction to LiveCycle Collaboration Service
One of the strengths of the Flash Platform is the ability to handle real-time data, multiple live users in addition to audio and video in a way that can be delivered across multiple devices and platforms. What you will learn…
• How to develop application.
• How to use What you should know…
• Basic knowledge of server side applications.
• Flash Media Server.
• LiveCycle Data Service.
Figure 1. Getting started
Figure 2. Account details
Introduction to LiveCycle Collaboration Service
09/2011 (27)
2
7
Launch Flash Builder (or what ever IDE your using) and create a new Flex Project. Called LCCSIntro. In this example we are not going to worry about the version of the Flex SDK or if its going to be an AIR application. For the moment it will just be a Flash Player application with everything else set at the default settings. Click Finish after adding the project name. When the project has been created using the default settings you will find the libs folder. Copy the lccs.swc
file from the SDK (
libs/player10.3/lccs.swc
) and paste it into the libs folder for your project. Along side the .swc file is the source code for that file. For this example we won’t use it but it can be helpful when you run into a bug.
Once this has been added to your project all the code hinting should work and we can write a quick script that will connect to LCCS.
Add a script tag and create a few variables for your application. The data type of these variables _userName
, _password
and _accountURL
will be String. The value of these variables will be the same as what you used to create your LCCS account. Back in your browser, if your still logged into your LCCS account, on the bottom left corner there is a field called Account URL. Copy the URL in that field and use it in your application, then add the room name to the end. You don’t need to use the Shared Secret at this time.
Once this has been added to the application we need to create some LCCS specific objects. The first object will be called _connectSession
with a data type of connectSession
.
var _connectSession:ConnectSession = new ConnectSession();
Go to https://afcs.acrobat.com/
and click on the new developer sign up button at the bottom of the page.
One your logged in you will get prompted to watch a tutorial video.
If you choose not to watch click the close button, the diolouge box will go away and you will be looking at your account page. We need to create a room for this application to run in. Rooms are where all the people using your application gather. Your SWF file sits on your server. The ActionScript will log your user into a room and share data with other people in that room. The rooms are really URL’s that are made up of your acount name + room name. So it will look like this: https://collaoration.
adobelivecycle.com/MYACCOUNT/MYROOM
.
Under the heading My Rooms
click the add button and give your room a name like devroom
.
Next download the SDK by clicking on the button on the right side of the page. Don’t close this window, you will need it later.
This will install the LCCS SDK Navigator. It’s and AIR application that will give you most of what you need to start building your application. (As a side note, when the LCCS team updates the SDK this application will prompt you to be updated.)
If the application does not automatically try to download the current SDK then click on the Fetch the Latest SDK
button to download the current version to your machine.
Once downloaded you will have a folder called com.adobe.lccs
within that will be the whole SDK, example applications and asDocs.
Connect to the Service
The first example we are going to build will simply connect to the service. There isn’t going to be a dependency on if you use the Flex SDK or the ActionScript one, but I’m going to recommend using the Flex SDK so the other examples will work.
Figure 3. How to download SDK
Figure 4. Create a Flex project
09/2011 (27)
2
8
LIVECYCLE
Introduction to LiveCycle Collaboration Service
09/2011 (27)
2
9
Listing 1. Application
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
s
:
Application
xmlns
:
fx
=
"http://ns.adobe.com/mxml/2009"
xmlns
:
s
=
"library://ns.adobe.com/lex/spark"
xmlns
:
mx
=
"library://ns.adobe.com/lex/mx"
minWidth
=
"955"
minHeight
=
"600"
creationComplete
=
"application1_creationCompleteHandler(event)"
>
<
fx
:
Declarations
>
<!-- Place
non
-
visual
elements
(
e
.
g
.
, services
, value
objects
)
here
-->
</
fx
:
Declarations
>
<
fx
:
Script
>
<!
[
CDATA
[
import
com
.
adobe
.
rtc
.
authentication
.
AdobeHSAuthenticator
;
import
com
.
adobe
.
rtc
.
events
.
SessionEvent
;
import
com
.
adobe
.
rtc
.
session
.
ConnectSession
;
import
mx
.
events
.
FlexEvent
;
var
_userName
:
String
= "EMAIL ADDRESS"
;
var
_password
:
String
= "PASSWORD"
;
var
_accountURL
:
String
= "https://collaboration.adobelivecycle.co
m/ACCOUNT_NAME/ROOM_NAME"
;
var
_connectSession
:
ConnectSession
= new
ConnectSession
();
var
_adobeAuth
:
AdobeHSAuthenticator
= new
AdobeHSAuthenticator
();
protected
function
onSyncChange
(
event
:
SessionEvent
)
:
void
{
trace
(
"you are loged in to lccs"
);
}
protected
function
application1_creationCompleteHandler
(
event
:
FlexEvent
)
:
void
{
_connectSession
.
authenticator
= _adobeAuth
;
_adobeAuth
.
userName
= _userName
;
_adobeAuth
.
password
= _password
;
_connectSession
.
roomURL
= _accountURL
;
_connectSession
.
addEventListener
(
SessionEvent
.
SYNCHRONIZATION_CHANGE
, onSyncChange
, false
,
0
,
true
);
_connectSession
.
login
();
}
]]
>
</
fx
:
Script
>
09/2011 (27)
2
8
LIVECYCLE
Introduction to LiveCycle Collaboration Service
09/2011 (27)
2
9
The next is _ adobeAuth
with the data type of AdobeHSAuthenticator
.
var _adobeAuth:AdobeHSAuthenticator = new AdobeHSAuthenticator()
As you added these objects the class paths should import into your project.
If not the path for each would be:
import com.adobe.rtc.authentication.AdobeHSAuthenticator;
import com.adobe.rtc.session.ConnectSession;
Since this is a Flex app we need to add an event to Application tag. Add the creationComplete event and let Flash Builder create a function.
Inside that function lets work with objects we created.
protected function application1_creationCompleteHandler(
event:FlexEvent):void
{
_connectSession.authenticator = _adobeAuth;
_adobeAuth.userName = _userName;
_adobeAuth.password = _password;
_connectSession.roomURL = _accountURL;
_connectSession.addEventListener(SessionEvent.SYNCH
RONIZATION_CHANGE, onSyncChange, false,0,true);
_connectSession.login();
}
Finally we add the function onSyncChange to handle when we logged in:
protected function onSyncChange(event:SessionEvent):void
{
trace(„you are loged in to lccs”);
}
So at this point our application should look like on Listing 1.
Click the debug icon to run the application though the debugger. This way we can see all the activity in the Console panel. It should connect and the trace statement should be displayed once the application connects to the room.
Now there are a few important things to keep in mind here. At this moment your account credentials are hard coded in the application. That’s fine when you need to build something, however remember to take them out for production. If you were to run this on your site not only would everyone log in as you (it is using your user name and password), it would also take very little effort to have your swf file decompiled and your account taken over. So DON’T leave your credentials in your production application. In the SDK there are tutorials on external authentication. This would be how you can control users login experience and assign the appropriate role to them.
LCCS also allows users to have roles. As the account owner your role is owner
with level of 100. Unless you want other uses to have the same amount of access as you, they need a lower role. Publisher (50) gives the ability to publish things like the microphone and camera into the room. Viewer (10) just lets you watch what is going on in the room. If you need to you can create custom roles.
Roles are important, especially in development. As owner you’re the only one who is allowed to add components to a room. For example, the components that you add to your application are specific to your room. If some other flash move tried to login and that movie had different components inside, it would be rejected based on role.
Only you can (and should) add whiteboards, webcam’s, rosters and other components to your room. Figure 5. Room Console
Figure 6. Account information
09/2011 (27)
3
0
LIVECYCLE
Think of it like your apartment. You don’t want other people moving your furniture out and moving their furniture in. (no matter how nice it is).
Watching the room
Once people are connected to a room you can use the Room Console to monitor everything that is going on.
Back over to the LCCS SDK Navigator. We are going to launch the Room Console and add our account to it.
On the left side navigator select DEVELOPER TOOLS
then select Room Console
. This will launch a new window.
On the bottom left click Add and add your account information. Once logged in you can then select your room and enter. This gives you a high level view of everyone that is in the room. It also shows whose camera or microphone is on.
If your application is running while you are in the room console. Then you will see your name listed twice. This is because you are logged in with the same credentials twice.
Close the browser that is running the application and you will see the extra name disappear from the room console. Everything that is happening here is in real time, so you get a good idea of what is going on.
Adding Chat, Roster and Video
So now that you can login and monitor activity in the room console, lets give people something to do.
In Flash Builder under your Script tag add the roster component.
<rtc:Roster/>
When you compile the app, the roster will connect to the service and display all the names of everyone in the room (right now just you). If you login with the room console then you can see that you are listed in the roster twice.
Adding video and audio is just as easy. LCCS comes with a few components that let you do this. In order to get your webcam on you need to understand that you are publishing your audio/video into the room. By default everyone in the room can subscribe to that stream.
For this example we will use the webcamera component. Since this is Flex, lets create a HGroup and place our current component inside it. Then add the WebCamera component in right after.
<s:HGroup>
<rtc:Roster/>
<rtc:WebCamera/>
</s:HGrop>
When you compile the application the WebCama component will be to the right of the roster. At the moment the camera isn’t on, you will just see a button to turn it on. Click the button and allow Flash to access your camera.
Now you are broadcasting your camera in the room. If you had a second browser running and connected to this room you would see your self in both browsers. Hopefully you can see that developing these types of applications has been made a lot simpler using LCCS. A large part of the code that you would usually write to connect to Flash Media server has been taken care of by the SDK. I would encourage you to create an account and start experimenting with LCCS. Since you are working with the Flash Platform you can deploy your project anywhere the platform is supported. So developing a application that works on IPad, Android and the Desktop would be possible.
For help working with LCCS the forums (
http://
forums.adobe.com/community/livecycle/lccs
) are an excellent place to go. The LCCS team is actively participating answering questions and taking requests to make the product better.
There is also the developer guide (
http://
learn.adobe.com/wiki/display/lccs/LiveCycle+Coll
aboration+Service
) and the API reference (
http://
livedocs.adobe.com/labs/acrobatcom/index.html
).
Try it out, it would be great to see what kind of collaborative applications people come up with.
RUSS FERGUSON
Russ Ferguson is a New York based Flash platform developer.
He also teach ActionScript and Dreamwever at Pratt Institute as well as contribute to InsideRIA.com
and the Adobe Cookbooks.
09/2010 (27)
3
2
FLEX ON JAVA
Flex on Java
09/2010 (27)
3
3
A
dobe provides data visualization components, but only when you purchase a license for the professional version of the Flash Builder IDE. Because our goal is to do Flex development using only free and open source technologies, we’ve decided to create our own visualization components – besides, it’s more fun.
Drawing in Flex
Flex and Flash provide powerful drawing libraries that we could leverage to create our custom graph components, but we’re going to leverage an open source graphics library called Degrafa. Using Degrafa gives us the ability to declaratively build our graphing components rather than having to deal with the complex calculations involved in drawing pie chart slices as illustrated in Listing 1, which shows an example ActionScript class specifically for drawing a pie chart slice found at http://
www.adobe.com/devnet/flash/articles/adv_draw_
methods.html
. Notice how much trigonometry is involved in creating something as simple as a pie chart slice from scratch.
Adobe has released the specifications for its declarative graphics library, called FXG. It appears that the Degrafa team has collaborated with the Adobe team to create this specification, but the FXG functionality is only a subset of what is available from the Degrafa library. This may be a library to keep your eye on as it’s being developed.
Common Degrafa concepts
Before diving into developing the component, let’s familiarize ourselves with some of the terms and concepts that we’ll see as we work through this example.
• Surface – This is the base component for everything you’ll do in Degrafa. All other Degrafa components will be composed within a Surface
.
• GeometryGroup – After the Surface
, this is the next level of composition. The GeometryGroup tag allows you to group Degrafa components to compose an object.
• Stroke – Stroke is the object that is used to define the look of an object’s outline, in terms of color, thickness, and style. Degrafa provides different Stroke objects for your use depending on the style of stroke you want: SolidStroke
, Linear-Gradient
, and RadialGradient
.
Flex on Java
Flex on Java
By Bernerd Allmon and Jeremy Anderson
Using Degrafa gives us the ability to declaratively build our graphing components rather than having to deal with complex calculations. In this article based on chapter 8 of Flex on Java
, the authors show you how to create a custom pie chart component using Degrafa. You may also be interested in… Excerpted from
For source code, sample chapters, the Online Author Forum, and other resources, go to
http://www.manning.com/allmon/
Creating a Custom Pie Chart Component with Degrafa
09/2010 (27)
3
2
FLEX ON JAVA
Flex on Java
09/2010 (27)
3
3
Listing 1. Example of drawing in ActionScript
/*---------------------------------------------------
----------
mc.drawWedge is a method for drawing pie shaped
wedges. Very useful for creating charts. Special
thanks to: Robert Penner, Eric Mueller and Michael
Hurwicz for their contributions.
-----------------------------------------------------
--------*/
MovieClip
.
prototype
.
drawWedge
= function
(
x
, y
, startAngle
, arc
,
►
radius
, yRadius
)
{
==============
// mc.drawWedge() - by Ric Ewing (ric@formequalsfu
nction.com) -
►
version
1.3
- 6.12
.
2002
//
// x, y = center point of the wedge.
// startAngle = starting angle in degrees.
// arc = sweep of the wedge. Negative values draw clockwise.
// radius = radius of wedge. If [optional] yRadius is deined,
►
then
radius
is
the
x
radius
.
// yRadius = [optional] y radius for wedge.
// ==============
// Thanks to: Robert Penner, Eric Mueller and Michael Hurwicz
►
for
their
contributions
.
// ==============
if
(
arguments
.
length
<
5
)
{
return
;
}
// move to x,y position
this
.
moveTo
(
x
, y
);
// if yRadius is undeined, yRadius = radius
if
(
yRadius
== undeined
)
{
yRadius
= radius
;
}
// Init vars
var
segAngle
, theta
, angle
, angleMid
, segs
, ax
, ay
, bx
, by
, cx
, cy
;
// limit sweep to reasonable numbers
if
(
Math
.
abs
(
arc
)
>
360
)
{
arc
= 360
;
}
// Flash uses 8 segments per circle, to match that, draw in a maximum
// of 45 degree segments. First calculate how many segments are needed
// for our arc.
segs
= Math
.
ceil
(
Math
.
abs
(
arc
)
/
45
);
// Now calculate the sweep of each segment.
segAngle
= arc
/
segs
;
// The math requires radians rather than degrees. To convert from degrees
// use the formula (degrees/180)*Math.PI to get radians.
theta
= -
(
segAngle
/
180
)
*
Math
.
PI
;
// convert angle startAngle to radians
angle
= -
(
startAngle
/
180
)
*
Math
.
PI
;
// draw the curve in segments no larger than 45 degrees.
if
(
segs
>
0
)
{
ax
= x
+
Math
.
cos
(
startAngle
/
180
*
Math
.
PI
)
*
radius
;
ay
= y
+
Math
.
sin
(
-
startAngle
/
180
*
Math
.
PI
)
*
yRadius
;
this
.
lineTo
(
ax
, ay
);
// Loop for drawing curve segments
for
(
var
i
= 0
; i
<
segs
; i
++
)
{
angle
+= theta
;
angleMid
= angle
-
(
theta
/
2
);
bx
= x
+
Math
.
cos
(
angle
)
*
radius
;
by
= y
+
Math
.
sin
(
angle
)
*
yRadius
;
cx
= x
+
Math
.
cos
(
angleMid
)
*
(
radius
/
Math.cos(theta/
2
));
cy
= y
+
Math
.
sin
(
angleMid
)
*
(
yRadius
/
Math.cos(theta/
2
));
this
.
curveTo
(
cx
, cy
, bx
, by
);
}
// close the wedge by drawing a line to the center
this
.
lineTo
(
x
, y
);
}
};
09/2010 (27)
3
4
FLEX ON JAVA
Flex on Java
09/2010 (27)
3
5
• Fill – Fill refers to the appearance of the bounded area of a graphical component. Degrafa provides the following fills: SolidFill
, LinearGradient
, Radial-
Gradient
, BitmapFill
, BlendFill
, and ComplexFill
.
• Shapes – Degrafa supports drawing many different shapes out of the box, such as Circle
, Ellipse
, RegularRectangle
, RoundedRectangle
, Polygon
, and more. For irregular shapes, Degrafa also has an extensive library of auto shapes and enables defining any shape you’d like by providing a Scalable Vector Graphics
(SVG) path.
• Repeaters – This gives you the ability to repeat a shape any number of times on the surface.
Much like other Flex components, the Degrafa components are considered either container components, meaning they will contain other Degrafa components, or graphical elements. Figure 1 shows the relationship of the common components.
We’re only going to scratch the surface; to learn more about Degrafa, you can start with the Foundation section of the documentation at http://www.degrafa.org/
samples/foundation.html
.
Creating a pie chart for fun and profit
Now that we have some of the basic concepts, let’s get on with the task of creating a custom pie chart component. We were inspired by a blog posting by Derrick Grigg titled appropriately enough Degrafa Pie Chart
, which can be found at http://www.dgrigg.com/post.cfm/04/
15/2008/Degrafa-Pie-Chart
. After we decomposed it and removed some of the extra visual effects such as tweening and gradients, it barely resembles what we started with. Figure 2 shows a mock-up of the chart we’ll be developing in this article.
For this example you’ll be developing only a single pie chart component, but some of the concepts illustrated here could potentially be applied to creating any number of charting components.
The component you’ll develop is a combination of a pie chart and a data grid, which will serve the purpose of a legend for the pie chart. Without this it may be difficult for someone looking at the chart to differentiate between data points on the graph. The pie chart will consist of the pie chart itself and another component for each of the slices that make up the chart. You’ll also develop a simple custom ItemRenderer for the chart legend to draw a simple box inside one of the cells in the data grid.
You’ll also be adding a label and a combo box to the GraphView to allow the user to change the data the chart shows. By changing the value of the combo box the user can show how many issues there are by project, type, status, or severity.
Figure 1. Relationship of Degrafa components
Figure 2. Mock-up of the Graph View
Listing 2. PieChartEvent.as
package
org
.
foj
.
event
{
import
lash
.
events
.
Event
;
public
class
PieChartEvent
extends
Event
{
public
static
const
DATA_PROVIDER_UPDATED
:
String
=
"dataProviderUpdated"
;
public
var
data
:*;
public
var
id
:*; #
1
public
function
PieChartEvent
(
type
: String
,
bubbles
: Boolean
= true
,
cancelable
: Boolean
= false
)
{
super
(
type
, bubbles
, cancelable
);
}
}
}
#
1
id
property
09/2010 (27)
3
4
FLEX ON JAVA
Flex on Java
09/2010 (27)
3
5
Listing 3. PieChart.mxml
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
s
:
Group
xmlns
:
fx
=
"http://ns.adobe.com/mxml/2009"
xmlns
:
s
=
"library://ns.adobe.com/lex/spark"
xmlns
:
mx
=
"library://ns.adobe.com/lex/halo"
xmlns
:
degrafa
=
"http://www.degrafa.com/2007"
creationComplete
=
"init()"
> #
1
<
s
:
layout
> #
2
</
s
:
layout
>
<
fx
:
Script
>
<!
[
CDATA
[
import
mx
.
collections
.
ICollectionView
;
import
org
.
foj
.
event
.
EventDispatcherFactory
;
import
org
.
foj
.
event
.
PieChartEvent
;
import
org
.
foj
.
presenter
.
PieChartPresenter
;
private
var
_presenter
:
PieChartPresenter
; #
3
private
var
_dataProvider
:
ICollectionView
; #
4
private
function
init
()
:
void
{
_presenter
= new
PieChartPresente
r
(
this
, id
);
#
5
}
public
function
set
dataProvider
(
dataProvider
:
ICollectionView
)
:
void
{
#
6
var
refreshEvent
:
PieChartEvent
=
new
PieChartEvent
(
PieChartEvent
.
DATA_
PROVIDER_UPDATED
);
refreshEvent
.
id
= id
;
refreshEvent
.
data
= dataProvider
;
EventDispatcherFactory
.
getEventDispatcher
().
dispa
tchEvent
(
refreshEvent
);
}
]]
>
</
fx
:
Script
>
...
</
s
:
Group
>
#
1
CreationComplete
handler
#
2
HorizontalLayout
#
3
Deine
presenter
ield
#
4
Deine
data
provider
ield
#
5
Pass
component
’
s
id
to
presenter
#
6
Set
property
for
data
provider
Listing 4. PieChart.mxml (continued)
<
s
:
Group
xmlns
:
fx
=
"http://ns.adobe.com/mxml/2009"
xmlns
:
s
=
"library://ns.adobe.com/lex/spark"
xmlns
:
mx
=
"library://ns.adobe.com/lex/halo"
xmlns
:
degrafa
=
"http://www.degrafa.com/2007"
creationComplete
=
"init()"
>
...
</
fx
:
Script
>
<
mx
:
Spacer
width
=
"10"
/> #
1
width
=
"200"
height
=
"200"
> #
2
<
degrafa
:
GeometryGroup
id
=
"pieGroup"
> #
3
<
degrafa
:
ilters
>
<
mx
:
DropShadowFilter
color
=
"0x000000"
alpha
=
"0.5"
/>
</
degrafa
:
ilters
> #
4
</
degrafa
:
GeometryGroup
>
</
degrafa
:
Surface
>
<
mx
:
DataGrid
id
=
"legendDataGrid"
> #
5
<
mx
:
columns
>
<
mx
:
DataGridColumn
width
=
"40"
sortable
=
"false"
#
6
itemRenderer
=
"org.foj.components
.PieLegendRenderer"
/>
<
mx
:
DataGridColumn
dataField
=
"label"
headerText
=
"Label"
/>
<
mx
:
DataGridColumn
dataField
=
"units"
headerText
=
"Units"
/>
</
mx
:
columns
>
</
mx
:
DataGrid
>
</
s
:
Group
>
#
1
Spacer
to
help
lay
out
the
component
#
2
Degrafa
surface
#
3
Geometry
group
containing
pie
chart
#
4
Drop
shadow
for
pie
chart
#
5
Legend
for
pie
chart
#
6
Custom
ItemRenderer
09/2010 (27)
3
6
FLEX ON JAVA
Flex on Java
09/2010 (27)
3
7
New custom event
We’re going to create a new custom event for our pie chart. The reason we’re creating a new one is that if we ever wanted to put more than one pie chart component into our application, we’d need to be able to distinguish which component fired the event.
This event differs from the one created previously in the addition of an id property (#1). This is done so that the presenter can decide whether or not it needs to react to the event. With the new event created, you can move on to creating the component itself.
PieChart component
First, you’ll develop the view that contains the pie chart and legend. You’ll create these view components in a new package, so create a file named PieChart.mxml in the org.foj.components
package of your project. The following listing shows the first part of the code for the PieChart view.
You set the creationComplete event (#1) to call the init method. Next, you set the layout of your component to use HorizontalLayout (#2). Then, you declare a couple of private member variables for the data provider and its presenter (#3, #4).
Inside the init method, you bootstrap your presenter (#5). Last, you create a set property (#6) for the data provider where you create an event to notify the presenter that the data provider was updated. Listing 4 shows the rest of your pie chart component.
First, you added a spacer (#1) to the component to put a bit of padding between your pie chart and its surrounding components. Next you added a Degrafa Surface component (#2) and a GeometryGroup (#3) to hold the rest of the Degrafa components necessary for the pie chart component. The GeometryGroup is the component to which you’ll add your pie chart slices when you create them. You’ve also added a Drop-
ShadowFilter (#4) to the GeometryGroup to add a bit of visual flair to the pie chart. Last you defined the Listing 5. PieChartSlice.mxml
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
degrafa
:
GeometryGroup
xmlns
:
fx
=
"http://
ns.adobe.com/mxml/2009"
xmlns
:
degrafa
=
"http://
www.degrafa.com/2007"
height
=
"400"
width
=
"400"
> #
1
<
fx
:
Script
>
<!
[
CDATA
[
public
function
refresh
()
:
void
#
2
{
this
.
graphics
.
clear
();
this
.
arc
.
preDraw
();
this
.
arc
.
draw
(
graphics
, null
);
}
]]
>
</
fx
:
Script
>
<
degrafa
:
EllipticalArc
#
3
id
=
"arc"
width
=
"200"
height
=
"200"
closureType
=
"pie"
/>
</
degrafa
:
GeometryGroup
>
Extends
GeometryGroup
Your
pie
chart
slice
Adds
EllipticalArc
Listing 6. PieLegendRenderer.mxml
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
mx
:
HBox
xmlns
:
fx
=
"http://ns.adobe.com/mxml/2009"
xmlns
:
s
=
"library://ns.adobe.com/lex/spark"
xmlns
:
mx
=
"library://ns.adobe.com/lex/halo"
xmlns
:
degrafa
=
"http://www.degrafa.com/
2007"
> #
1
<
mx
:
Spacer
width
=
"2"
/> #
2
<
degrafa
:
Surface
>
<
degrafa
:
GeometryGroup
>
<
degrafa
:
ill
> #
3
<
degrafa
:
SolidFill
id
=
"ill"
>
<
degrafa
:
color
>
{
data
.
legend
}
"</degrafa:
color> #4
</degrafa:SolidFill>
</degrafa:ill>
<degrafa:RegularRectangle #5
width="
20
"
height="
20
"
ill="
{
ill
}
"/>
</
degrafa
:
GeometryGroup
>
</
degrafa
:
Surface
>
</
mx
:
HBox
>
#
1
Extends
HBox
Spacer
to
help
align
box
#
2
SolidFill
for
rectangle
#
3
Color
of
legend
item
#
4
Rectangle
09/2010 (27)
3
6
FLEX ON JAVA
Flex on Java
09/2010 (27)
3
7
Listing 7a. PieChartPresenter.as
package
org
.
foj
.
presenter
{
import
com
.
degrafa
.
paint
.
SolidFill
;
import
org
.
foj
.
components
.
PieChart
;
import
mx
.
collections
.
ArrayCollection
;
import
org
.
foj
.
components
.
PieChartSlice
;
import
org
.
foj
.
event
.
EventDispatcherFactory
;
import
org
.
foj
.
event
.
PieChartEvent
;
import
org
.
foj
.
model
.
PieChartModel
;
private
var
_view
:
PieChart
; #
1
private
var
_model
:
PieChartModel
;
private
var
_id
:
String
;
private
var
_dataProvider
:
ArrayCollection
;
public
function
PieChartPresenter
(
view
:
PieChart
, id
:
String
)
{
#
2
this
.
_view
= view
;
this
.
_model
= new
PieChartModel
();
this
.
_id
= id
;
EventDispatcherFactory
.
getEventDispatcher
()
.
addEventListener
(
PieChartEvent
.
DATA_PROVIDER_
UPDATED
,
refreshData
);
}
public
function
set
dataProvider
(
data
:
ArrayCollection
)
:
void
{
#
3
_view
.
legendDataGrid
.
dataProvider
= data
;
this
.
_dataProvider
= data
;
}
public
function
get
dataProvider
()
:
ArrayCollection
{
return
this
.
_dataProvider
;
}
private
function
refreshData
(
event
:
PieChartEvent
= null
)
:
void
{
#
4
if
(
event
.
id
== _id
)
{
changeData
(
event
.
data
);
}
}
private
function
changeData
(
data
:
ArrayCollection
)
:
void
{
dataProvider
= data
;
createSlices
();
}
private
function
createSlices
()
:
void
{
#
5
while
(
dataProvider
.
length
> _view
.
pieGroup
.
numChi
ldren
)
{
_view
.
pieGroup
.
addChild
(
new
PieChartSlice
());
}
setLegendColors
();
redrawSlices
();
}
private
function
setLegendColors
()
:
void
{
#
6
for
(
var
i
:
int
= 0
; i
< dataProvider
.
length
; i
++
)
{
dataProvider
.
getItemAt
(
i
).
legend
= _model
.
getLeg
endColorForIndex
(
i
);
}
}
var
currentAngle
:
Number
= 0
;
var
totalUnits
:
Number
= _model
.
getTotalUnits
(
_
dataProvider
);
for
(
var
i
:
int
= 0
; i
< _view
.
pieGroup
.
numChildren
; i
++
)
{
var
slice
:
PieChartSlice
= _view
.
pieGroup
.
getChi
ldAt
(
i
)
as
PieChartSlice
;
var
legendColor
:
Number
= _model
.
getLegendColorFo
rIndex
(
i
);
var
arc
:
Number
= i
< dataProvider
.
length
?
_model
.
getAngleForItem
(
dataProvider
[
i
].
units
, totalUnits
)
: 0
;
// workaround for weird display if only one arc and it's 360 degrees
arc
= arc
< 360
? arc
: 359.99
; #
8
redrawSlice
(
slice
, currentAngle
, arc
, legendColor
);
currentAngle
+= arc
;
}
_view
.
pieGroup
.
draw
(
null
, null
);
}
private
function
redrawSlice
(
slice
:
PieChartSlice
, #
9
startAngle
:
Number
,
arc
:
Number
,
color
:
Number
)
:
void
{
slice
.
arc
.
ill
= new
SolidFill
(
color
, 1
);
09/2010 (27)
3
8
FLEX ON JAVA
Flex on Java
09/2010 (27)
3
9
DataGrid component (#5) for your chart legend, with a custom Item-Renderer (#6) to display the color that corresponds to the data in the chart, which you’ll create in a bit.
PieChartSlice
Now that we’ve defined the pie chart component, let’s move on to defining the slices that will make up the pie chart. The pie chart slice is a rather simple component. We probably could have created the pie chart slice programmatically in ActionScript; however, this approach allows us to define sensible defaults declaratively in MXML, adding behavior as well.
The pie chart slice will extend from GeometryGroup (#1). Next, you define a refresh method (#2) to abstract behavior away from your presenter. Last you add an EllipticalArc component to the component (#3) and set default values such as its width, height, and most importantly closureType property, which you set to pie
. Listing 7b. PieChartPresenter.as
slice
.
arc
.
startAngle
= startAngle
;
slice
.
arc
.
arc
= arc
;
slice
.
refresh
();
}
}
}
#
1
Private
member
variables
#
2
Constructor
#
3
Set
property
for
dataProvider
#
4
Event
handler
#
5
Create
slices
method
#
6
Set
legend
colors
on
data
#
7
Redraw
slices
after
update
#
8
Workaround
#
9
Redraw
slice
Listing 8. PieChartModel.as
package
org
.
foj
.
model
{
import
mx
.
collections
.
ICollectionView
;
public
class
PieChartModel
{
private
var
colors
:
Array
= [
#
1
0x468966
,
0
xFFF0A5
,
0x999574
,
0x007
D9F
,
0x8
E2800
,
0x8
E28F4
,
0x0528
F4
,
0
xF42105
,
0x0
CF405
];
public
function
getLegendColorForIndex
(
index
:
Number
)
:
Number
{
#
2
return
colors
[
index
];
}
public
function
getAngleForItem
(
units
:
Number
,
totalUnits
:
Number
)
:
Number
{
#
3
return
((((
units
/ totalUnits) * 100) * 360) /
100
)
;
}
public
function
getTotalUnits
(
dataProvider
:
ICollectionView
)
:
Number
{
#
4
var
total
:
Number
= 0
;
for
each
(
var
item
:
Object
in
dataProvider
)
{
total
+= item
.
units
;
}
return
total
;
}
}
}
#
1
Array
of
colors
for
legend
#
2
Convenience
method
for
getting
color
#
3
Calculate
angle
for
item
#
4
Calculate
total
number
of
items
for
pie
chart
09/2010 (27)
3
8
FLEX ON JAVA
Flex on Java
09/2010 (27)
3
9
Custom ItemRenderer
The next component you’re going to create is the custom ItemRenderer for the pie chart legend. This simple component will draw a colored box in the data grid cell to correspond with the colors of the pie chart.
The ItemRenderer is extending HBox (#1) because all ItemRenderer objects for the DataGrid component must be halo components. Add a Spacer component (#2) to help align the rectangle the way you want it. The SolidFill component (#3) defines the fill color for the RegularRectangle (#5). Now that you’ve finished creating all the visual components for the pie chart, let’s move on to creating the Presenter. An implicitly defined variable is available to the ItemRenderer named data
, which corresponds to the item in the dataProvider that you’re rendering. Use this implicit variable to set the color of the Fill object (#4), which is contained in the legend property of the object.
Presenter for the PieChart
Now that all the visual components are created for the pie chart, let’s create the Presenter. The Presenter for the pie chart becomes more involved than any of your previous ones, but it shouldn’t be hard to follow.
You first define private member variables to hold onto references to the view and the model
, the id of the component this Presenter belongs to, and the dataProvider for your pie chart (#1). The constructor (#2) for this Presenter not only takes in a reference to the view, but also is used to bootstrap the id for the view component because there may be multiple pie charts contained in the application. You also define an event listener for the dataProvider being updated in the view component. Next you define a pair of get and set properties (#3) for the dataProvider you leverage to update the dataProvider property of the legend data grid whenever the data-Provider for the pie chart is updated.
You then define the event handler method for the event that is fired whenever the dataProvider for the view is updated (#4). Inside this method you check to see if the id of the component firing the event is the same as the id that created this Presenter.
That way if there are multiple pie chart components, this method can determine whether or not it needs to react.
The createSlices method (#5) checks to see if the data provider has more elements contained in it than there are pie chart slices in your pie chart. If there are more elements in the data provider, it will create more pie chart slices. In the set-LegendColors method (#6) you iterate through the items in the dataProvider and set the legend property of the item to the corresponding color, which you’ll get from the pie chart model class.
After all of that, refresh your pie chart with a call to the redrawSlices method (#7).
This will iterate over the pie chart slices and update the data values, such as the start angle of the slice and its arc. You iterate over the pie chart slices instead of the data provider because there may be more slices than items in the dataProvider
, and this will draw the extra slices with an arc of 0. There is also a little workaround (#8) for when there is only a single slice and its arc is 360, which sets its arc to 359.99 so that it would draw correctly. After all of the data for the slice is updated, it is passed into the redrawSlice method (#9) to tell the slice to redraw itself.
Model for the PieChart
Now you only have one piece of the MVP triad to complete for your pie chart. Even though the pie chart doesn’t need to call out to any remote services, you’ve still refactored a couple of methods that could be considered business logic rather than presentation logic and have no need to maintain any kind of state. The following listing shows the code for the pie chart model.
An array of 10 different hex values (#1) corresponds to the colors you want the pie chart to use for its data points. This number could easily be increased should the need arise for more data points in your graphs; for this example this number should suffice.
Next, you define a convenience method (#2) for getting the color value for a specific index. The method getAngleForItem (#3) takes care of the calculation for determining the size of the angle for an item based on the total number of items contained within the pie chart and the number of items passed in. The last method you define (#4) in your model iterates through the data set passed in and returns back the total number of items for the pie chart.
Summary
In this article, we’ve introduced the Degrafa framework and created a custom pie chart component. Using Degrafa gives us the ability to declaratively build our graphing components rather than having to deal with complex calculations.
09/2010 (27)
4
0
SPRING DM
Spring Dynamic Modules in Action
09/2010 (27)
4
1
T
he core of the OSGi technology is a standard that’s described in the OSGi core specification. OSGi also comes with the compendium services specifications that build on the features provided by the core specification. Each compendium service addresses a particular requirement and can be used on any conformant OSGi platform. The Event Admin Service provides a standardized and centralized service to manage events triggered by entities used within the OSGi container. It’s based on an event channel called topic, which makes it possible for entities to subscribe to, receive, and send events. At the moment, Spring DM doesn’t support this service directly, but it’s possible to implement a bridge between Spring and Spring DM events and the Event Admin Service.
We’ll first explain how to install and use the service and the concepts behind linking Spring DM to the service. Then we’ll see how to implement this bridge.
OSGi Event Admin Service
Before using the Event Admin Service with Spring DM, we need to know how to install it, how to reference the corresponding OSGi service, and how to send and receive events.
Installing the Event Admin Service
Table 1 lists the components needed to install the Event Admin Service from the SpringSource EBR.
Adding these two components within your OSGi container will install the Event Admin Service.
Accessing the Event Admin Service using Spring DM
Once the implementation bundle for the Event Admin Service has been installed, a service will appear in the OSGi service registry under the name org.osgi.service.e
vent.EventAdmin
corresponding to the service interface.
This service can be referenced using Spring DM just like any other service, by using its reference XML element and then injecting the result into any bean. This is shown in the following snippet:
Spring Dynamic Modules in Action
Spring Dynamic Modules in Action
By Arnaud Cogoluegnes, Thierry Templier, and Andy Piper The Event Admin Service provides a standardized way of exchanging events between components – event producers and consumers don’t need to be tied to a particular API. In this article based on chapter 11 of Spring Dynamic Modules in Action
, the authors explain how a bridge can be implemented to forward events triggered by Spring or Spring DM to the Event Admin Service. You may also be interested in…
Excerpted from
For Source Code, Sample Chapters, the Author Forum and other resources, go to
http://www.manning.com/cogoluegnes/
Spring DM’s Event Admin Service Support
Table 1. Bundles related to the Event Admin Service from the SpringSource EBR
Group ID
Artifact ID
Version
org.osgi
org.osgi.compendium
4.1.0.build-200702212030
org.apache.felix
org.apache.felix.eventadmin
1.0.0
09/2010 (27)
4
0
SPRING DM
Spring Dynamic Modules in Action
09/2010 (27)
4
1
The Event Admin Service can also implement event listeners based on the whiteboard pattern. These listeners must implement the EventHandler interface, and they have to be registered as OSGi services. When an event occurs, the Event Admin Service dispatches the event to all the registered implementations by calling their handle-Event method. The following snippet shows a sample implementation of the Event-Handler interface.
public class SampleEventHandler implements EventHandler {
public void handleEvent(Event event) {
(...)
}
}
Event data can be accessed using properties contained in the instance of the Event class passed <osgi:reference id=”eventAdminService”
interface=”org.osgi.service.event.Event
Admin”/>
<bean id=”eventAdminManager” class=”com.manning.sdmia
►.compendium.event.EventAdminManager”>
<property name=”eventAdminService” ref=”eventAdminService”/>
</bean>
In the preceding snippet, the OSGi service for the Event Admin Service is referenced with the identifier org.osgi.service.event.Eve
ntAdmin
. This service can then be injected in the eventAdminManager bean using its eventAdminService property.
The EventAdminManager class configured in the preceding snippet contains a configured reference to the installed Event Admin Service, enabling the class to interact with it. Listing 1 shows the structure of the class.
Now that the eventAdminService property is set, all the methods of the EventAdmin interface can be used to interact with the service. Before describing how to implement a bridge between Spring DM and the Event Admin Service, we’ll first see how to exchange events.
Interacting with the Event Admin Service
The Event Admin Service is primarily used to send events. This can be done explicitly using the EventAdmin service that we automatically registered. This service provides a sendEvent method that takes an event object to send an event. The following snippet shows how to send an event.
Event event = new Event(topicName, eventProperties);
eventAdmin.sendEvent(event);
Listing 1. Structure of the EventAdminManager class
public
class
EventAdminManager
{
private
EventAdmin
eventAdminService
; #
A
(...)
public
EventAdmin
getEventAdminService
()
{
#
B
return
eventAdminService
;
}
public
void
setEventAdminService
(
#
B
EventAdmin
eventAdminService
)
{
this
.
eventAdminService
= eventAdminService
;
}
}
#
A
Attribute
for
Event
Admin
Service
instance
#
B
Accessor
and
mutator
for
service
instance
Figure 1. Linking Spring DM’s event-handling mechanisms so that they forward events to the Event Admin Service ��������������������
����������������������������
�����
����������������������������
�����
������������������������������������
��������
�����������������
����������
�������
���������������������
���������������������
�����������
�����������
�����������
��������������
�����������
������������������
Figure 2. Linking Spring’s event-handling mechanisms with the Event Admin Service
��������������������
����������������������������
�����
�����������������
����������
�������
���������������������
�������������������
�����������
�����������
��������������
�����������
������������������
��������������������������
09/2010 (27)
4
2
SPRING DM
Spring Dynamic Modules in Action
09/2010 (27)
4
3
as arguments to the handleEvent method. The class contains the event topic and its associated properties. The event topic has the same value as the topic-Name variable used to send the event.
Now that you know how to use the Event Admin Service to send and receive events, let’s see how we can use it with Spring DM.
Linking Spring DM and the OSGi Event Admin Service
Spring DM and Spring raise a set of events during their normal operation. Applications, and components, in our case, can register event listeners to be notified of these events when they occur. These system elements then use their own strategies for implementing event handling and delivering messages.
In Spring, listeners are implemented as regular classes implementing the ApplicationListener interface. The scope of this event system is restricted to the owning Spring application context, and with this framework events are propagated synchronously.
In Spring DM, events are intended to be consumed by bundles other than the one that triggers them. Event handling is based on the whiteboard pattern, which allows for the decoupling of event producers from their consumers and provides support for registering and unregistering listeners dynamically. In the context of this pattern, delivery has important requirements because OSGi is dynamic and the implementation mustn’t freeze the entire system. For this reason, Spring DM delivers events asynchronously to registered listeners.
In the next sections, we’ll describe how to link Spring DM and Spring events to the Event Admin Service. When events occur in either framework, they’re redirected to this service.
Handling Spring DM events
A dedicated Spring DM listener receives any Spring DM events and forwards them to the Event Admin Service. To do so, the listener builds an event compatible with the Event Admin Service using data contained in the initial Spring DM event and then sends it using the EventAdmin service API.
This listener isn’t provided by Spring DM and needs to be implemented. Figure 1 summarizes the steps for implementing the link between Spring DM events and the Event Admin Service.
First, like every Spring DM event listener, the bridge listener must implement Spring DM’s OsgiBundleApplicati
onContextListener
interface. Spring DM dispatches events to these listeners registered as services following the whiteboard pattern. The bridge listener references the EventAdmin service through the OSGi service registry and sends events to the Event Admin Service when it receives events from Spring DM. Every class registered as a listener on the Event Admin Service will then be notified.
This mechanism allows for third-party bundles to receive events and notifications from Spring DM without having to be tied to its use.
Handling Spring events
With Spring, things are a little different because its event management is completely independent from OSGi, and event listeners must be directly defined within the Spring application context. Having detected all these configured classes, Spring notifies them when an event occurs. For our purposes, we can use a special Spring application listener that receives these events and forwards them to the Event Admin Service.
Figure 2 summarizes the steps for implementing the link between Spring events and the Event Admin Service.
First, like every Spring application event listener, the bridge listener must implement Spring’s ApplicationListener interface. Spring dispatches events to these listeners configured within the Spring container. So far, nothing is specific to OSGi.
The bridge listener then references the EventAdmin service through the OSGi service registry and sends events to the Event Admin Listing 2. A listener implementation linking Spring DM and the Event Admin Service
public
class
EventAdminAdapterListener
implements
OsgiBundleApplicationContextListener
{
#
A
private
EventAdmin
eventAdmin
;
public
void
onOsgiApplicationEvent
(
#
A
OsgiBundleApplicationContextEvent
event
)
{
String
topicName
= buildTopicName
(
event
);
#
B
Properties
eventProperties
#
B
= buildEventProperties
(
event
)
#
B
eventAdmin
.
sendEvent
(
new
Event
(
#
B
topicName
, eventProperties
));
}
(...)
public
void
setEventAdmin
(
EventAdmin
eventAdmin
)
{
this
.
eventAdmin
= eventAdmin
;
}
}
#
A
Implements
Spring
DM
listener
interface
and
method
#
B
Creates
, conigures
, and
sends
event
09/2010 (27)
4
2
SPRING DM
Spring Dynamic Modules in Action
09/2010 (27)
4
3
Service when it receives events from Spring. Every class registered as a listener on the Event Admin Service will then be notified.
This mechanism allows for third-party bundles to receive events and notifications from Spring without having to be tied to the framework. Note that the bridge listener must deliver events asynchronously.
Now that we’ve described how to have events triggered by Spring and Spring DM dispatched to the Event Admin Service, we’ll focus on how to implement the bridge listener for Spring DM events.
Implementing the bridge between Spring DM and Event Admin Service
Handling Spring DM events consists of creating a listener class that implements Spring DM’s OsgiBundleAp
plicationContextListener
interface. Having registered this listener as an OSGi service, this class will then be able to handle Spring DM events and forward them to the Event Admin Service.
By implementing this interface, the class must also define the onOsgiApplication-Event
method. This method is called when an event is triggered and is responsible for handling it correctly.
Because the class provides the link with the Event Admin Service, it has an attribute of type EventAdmin
. We’ll configure this attribute later on by using the corresponding EventAdmin OSGi service referenced with Spring DM facilities.
Listing 2 shows the structure of this listener implementation.
Building the event for the Event Admin Service requires several steps, which are implemented in listing 2 by the buildTopicName and buildEventProperties methods within the onOsgiApplicationEvent method. We’ll describe the implementation of buildTopicName and buildEventProperties methods shortly.
The first step in building the event is creating the name of the topic on which the event will be published. Topic names allow classification of topics using tokens separated by the slash (/) character. The following snippet shows how to use the class name of the Spring DM event to build the topic name:
private String buildTopicName(OsgiBundleApplicati
onContextEvent event) {
String eventClassName = event.getClass().getN
ame();
return eventClassName.replace(„.”, „/”);
}
Properties for the event then need to be specified – they should contain all the information describing the event. In our context, this information can be obtained from the event instance provided by Spring DM. Listing 3 shows how to build properties for an event compatible with the Event Admin Service.
Implementations of the buildTopicName and buildEventProperties methods provide all of the information necessary to build an Event instance, which is the event class for the Event Listing 3. Implementing buildEventProperties to build event properties
private
Properties
buildEventProperties
(
OsgiBundleApplicationContextEvent
event
)
{
Properties
eventProperties
= new
Properties
();
eventProperties
.
put
(
"event.timestamp"
, #
A
event
.
getTimestamp
());
Object
source
= event
.
getSource
();
eventProperties
.
put
(
"event.source.class"
#
A
source
.
getClass
().
getName
());
Bundle
bundle
= event
.
getBundle
();
eventProperties
.
put
(
"event.bundle.id
#
B
bundle
.
getSymbolicName
())
#
B
eventProperties
.
put
(
"event.bundle.state"
, #
B
bundle
.
getState
());
(...)
return
eventProperties
;
}
#
A
Sets
general
properties
#
B
Sets
properties
related
to
bundle
Listing 4. Con�guring the bridge listener
<
bean
id
=
"eventAdminAdapterListener"
#
A
class
=
"org.springframework.osgi
► .compendium.event.EventAdminAdapterListener"
>
<
property
name
=
"eventAdmin"
#
A
ref
=
"eventAdminService"
/>
</
bean
>
<
osgi
:
reference
id
=
"eventAdminService"
interface
=
"org.osgi.service.event.EventAdmin"
/>
<
osgi
:
service
ref
=
"eventAdminAdapterListener"
#
B
interface
=
"org.springframework.osgi
► .context.event.OsgiBundleApplicationContextListene
r"
/>
#
1
Deines
listener
and
injects
EventAdmin
service
#
2
Registers
listener
as
OSGi
service
09/2010 (27)
4
4
SPRING DM
Admin Service. This instance can then be used when using the sendEvent method of the EventAdmin instance to send the event.
The last step consists of configuring the bridge listener. Because this listener uses the EventAdmin service, it first needs to be referenced using Spring DM’s facilities. The listener itself can then be configured as a bean in the Spring application context and exported as an OSGi service with the same facilities. Once these configurations are done, the listener is ready to receive events from Spring DM and forward them to the Event Admin Service.
Listing 4 shows how to configure the bridge listener.
We saw how to implement and configure a bridge listener that receives and forwards Spring DM events to the Event Admin Service. This listener is primarily a Spring DM listener that builds a new Event Admin Service event from the initial Spring DM event and sends it to interested parties via the EventAdmin service.
Let’s look now at how to implement listeners in Spring DM that can receive and handle events triggered by the Event Admin Service.
Implementing OSGi event handlers
Creating event listeners for the Event Admin Service involves implementing the EventHandler interface, which requires defining a handleEvent method that is called whenever an event occurs. The event is provided as parameter to this method.
Listing 5 shows how to implement such a listener.
From the event instance passed as a parameter, we can get the topic names and the properties of the event and iterate through them.
Because the Event Admin Service follows the whiteboard pattern for finding all the registered listeners, the listener we just defined must also be defined as an OSGi service under the name org.osgi.service.event.Ev
entHandler
. Spring DM can be used to accomplish this. The event.topics service property can also be added when exporting the listener to specify which topic it’s interested in. Wildcards are allowed here.
TIP
Topic names support hierarchies and become more specific when going from left to right. You can take advantage of this to define an event handler that receives a set of event kinds. For example, specifying the expression org/springframework/osgi/*
in the event.topics
property of an event handler service will allow the handler to receive events whose names begin with org/springframework/osgi/
. This means using hierarchies when creating event names is very important.
Listing 6 shows how to configure a listener for the Event Admin Service using Spring DM’s facilities.
The listener is configured as bean within the configuration and then registered as an OSGi service with Spring DM’s service XML element. Within this element, the topic names are specified in service properties with the event.topics key.
Given the configuration in Listing 6, all events with topic names beginning with org/springframework/osgi
are sent to the listener corresponding to the AdminEvent-
Handler
class. For each event, the handleEvent method is called with the event instance passed as a parameter.
We’ve now seen how to use the Event Admin Service with Spring DM, even though this compendium service isn’t directly supported by Spring DM.
Summary
The Event Admin Service is an interesting compendium service. It provides a standardized way of exchanging events between components – event producers and consumers don’t need to be tied to a particular API. Although Spring DM doesn’t provide support for this service, a bridge can be implemented to forward events triggered by Spring or Spring DM to the Event Admin Service. This allows components to be notified without having to use the API provided by these two frameworks.
Listing 5. An event listener implementation for the Event Admin Service
public
class
AdminEventHandler
implements
EventHandler
{
public
void
handleEvent
(
Event
event
)
{
String
topicName
= event
.
getTopic
();
String
[]
propertyNames
= event
.
getPropertyName
s
();
for
(
int
cpt
=
0
; cpt
<
propertyNames
.
length
; cpt
++
)
{
String
propertyName
= propertyNames
[
cpt
];
}
}
}
Listing 6. Con�guring the Event Admin Service listener using Spring DM
<
bean
id
=
"eventAdminHandler"
class
=
"org.springframework.osgi.compendium.event.A
dminEventHandler"
/>
<
osgi
:
service
ref
=
"eventAdminHandler"
interface
=
"org.osgi.service.event.EventHand
ler"
>
<
osgi
:
service
-
properties
>
<
entry
key
=
"event.topics"
value
=
"org/
springframework/osgi/*"
/>
</
osgi
:
service
-
properties
>
</
osgi
:
service
>
09/2011 (27)
4
6
TECHTRENDS
Smartphones and Tablets Go Multicore: Now What?
09/2011 (27)
4
7
T
his trend is no surprise, considering how mobile devices are increasingly handling multiple tasks simultaneously, such as serving as a videoconferencing endpoint while downloading email in the background and running an antimalware scan.
Today’s commercially available dual-core mobile devices include Apple’s iPad 2, HTC’s EVO 3D and Samsung’s Galaxy Tab, and some vendors have announced quad-core processors
that will begin shipping next year. Operating systems are the other half of the multicore equation. Android and iOS, which are No. 1 and No. 2
in terms of U.S. market share, already support multicore processors.
IOS and Android are, at their core, based on multithreaded operating systems
, says Geoff Kratz, chief scientist at FarWest Software
, a consultancy that specializes in system design. Android is basically Linux, and iOS is based on Mac OS, which in turn is based on BSD UNIX. That means that, out of the box, these systems are built to support multicore/multi-CPU systems and multithreaded apps
.
For enterprise developers, what all this means is that it’s time to get up-to-speed on programming for mobile multicore devices. That process starts with understanding multicore’s benefits – and why they don’t always apply.
Divide and Conquer
Performance is arguably multicore’s biggest and most obvious benefit. But that benefit doesn’t apply across the board; not all apps use multithreading. So when developing an app, an important first step is to determine what can be done in parallel.
This type of programming can be tricky at first, but once you get used to it and thinking about it, it becomes straightforward,
says Kratz. For multithreaded programming, the important concepts to understand are queues (for inter-thread communications) and the Smartphones and Tablets Go Multicore: Now What?
Within three years, nearly 75 percent of smartphones and tablets will have a multicore processor, predicts In-Stat, a research firm
. 09/2011 (27)
4
6
TECHTRENDS
Smartphones and Tablets Go Multicore: Now What?
09/2011 (27)
4
7
various types of locks you can use to protect memory (like mutexes, spin locks and read-write locks).
It’s also important to protect shared data.
Most programmers new to multithreaded programming assume things like a simple assignment to a variable (e.g., setting a long variable to 1) is atomic, but unfortunately it often isn’t
, says Kratz. That means that one thread could be setting a variable to some value, and another thread catches it halfway through the write, getting back a nonsense value
.
It’s here that hardware fragmentation can compound the problem. For example, not all platforms handle atomic assignments. So an app might run flawlessly on an enterprise’s installed base of mobile devices, only to have problems arise when non-atomic hardware is added to the mix.
Using mutexes (which allow exclusive access to a variable) or read/write locks (which allow multiple threads to read the data, but lock everyone out when a thread wants to write) are the two most common approaches, and mutexes are by far the most common
, says Kratz. For Android programmers, this is easily done using the synchronized construct in the Java language, protecting some of the code paths so only one thread at a time can use it.
For iOS, options include using POSIX mutexes, the NSLock class or the @synchronized directive.
Ideally, a programmer should minimize the amount of data shared between threads to the absolute bare minimum
, says Kratz. It helps with performance and, more importantly, makes the app simpler and easier to understand – and less liable to errors as a result
.
No Free Power-lunch
As the installed base of mobile multicore devices grows, it doesn’t mean developers can now ignore power consumption. Just the opposite: If multicore enables things that convince more enterprises to increase their usage of smartphones and tablets, then they’re also going to expect these devices to be able to run for an entire workday between charges. So use the extra horsepower efficiently, such as by managing queues.
You want to use a queue construct that allows anything reading from the queue to wait efficiently for the next item on the queue
, says Kratz. If there is nothing on the queue, then the threads should basically go idle and use no CPU. If the chosen queue forces you to poll and repeatedly go back and read the queue to see if there is data on it, then that results in CPU effort for no gain, and all you’ve done is use up power and generate heat. If a programmer has no choice but to poll, then I would recommend adding a small sleep between polling attempts where possible, to keep the CPU load down a bit
.
TIM KRIDEL FOR INTELLIGENCE IN SOFTWARE
When it comes to power management, many best practices from the single-core world still apply to multicore. For example, a device’s radios – not just cellular, but GPS and Wi-Fi too – are among the biggest power-draws. So even though multicore means an app can sit in the background and use a radio – such as a navigation app constantly updating nearby restaurants and ATMs – consider whether that’s the most efficient use of battery resources.
For some apps, like a turn-by-turn navigation app, it makes sense that it wants the highest-resolution location as frequently as possible
, says Kratz. But for some apps, a more coarse location and far less frequent updates may be sufficient and will help preserve battery
.
There may be times where an app will adapt its use of the GPS, depending on if the device is plugged into power or not. In this case, if you are plugged into an external power source, then the app can dial up the resolution and update frequency. When the device is unplugged, the app could then dial it back, conserving power and still working in a useful fashion
.
Документ
Категория
Информатика
Просмотров
267
Размер файла
3 432 Кб
Теги
flash, flex, adobe
1/--страниц
Пожаловаться на содержимое документа