Friday, September 5, 2008

Ramscode software company Profile

RamsCode Soft Tech Pvt Ltd is focused on providing software development services and solutions that leverage the evolving and innovative business models including the global (Onshore/offshore) delivery model and latest technology advancements to allow RamsCode customers to achieve maximum operational efficiencies, reduce costs, and increase return on investment

RamsCode is a diversified offshore software development company offering world-class services to help your organization exceed its software expectations. Our company supplies software to simplify and accelerate the development, deployment, integration, and management of business applications. We strive to offer superior solutions through state-of-the-art technology, innovation, leadership and partnerships. We are focused on providing services that leverage the evolving and innovative business models including the global (Onshore/offshore) delivery model and latest technology advancements, competencies lie in setting up offshore software development teams for custom product development, High-End ERP Solutions and maintenance using superior project management experience.

RamsCode is an actively growing offshore software development company that provides professional software outsourcing, offshore software and web site development services. Business software like Project Management software, Application Software, web application and accounting solutions(including Google Maps) too feature in our portfolio.

RamsCode Expertises and experience in website development enables RamsCode to understand clients requirements and develop a website carving an exclusive image of your company in the market. RamsCode talent pool of experts is different fields of website design and development work with clients not only build a website but also restructure/revamp website according to the developments in business environment

RamsCode provides high quality on site services for software development and the end users on a broad range of hardware & software platforms and latest technologies.

OUR GUIDELINES FOR DEVELOPING A QUALITY PRODUCT

* The globally accepted Rational Unified Process is followed.
* Skilled force ensures a product with international standard.
* Focus on successful and robust executable application.
* In depth analysis to understand the actual requirement and business constraint.
* Stress for generating new ideas during analysis which will enhance your business. Quality is a way of our life, not an afterthought.
* Catch the major risks early and continuously and search for their remedy or alternate solution.
* A future vision before developing an application assists in extensibility of application, less and easy maintenance.
* Be in touch with you during whole life cycle of project. This makes the things transparent that we are doing work on common tasks or requirements. Standard design patterns (object oriented) are adopted to make the reusability of the things.
* Work with some of the most successful and expertise individuals, entrepreneurs and corporations and bring solutions to their most challenging and complex issues of the day.
* Formed by a team of young and enterprising IT professionals, RamsCode aims at blending knowledge and skills to provide results that match your requirements.
* At RamsCode, we believe in listening, analyzing, advising, and implementing new projects and concepts to effectively present complex information.

Thursday, August 14, 2008

Personalized Print Markup Language (PPML)

Personalized Print Markup Language (PPML) Version 2.0 Supports Digital Print Job Ticketing. A communiqué from Tracy Burkovich announces the release of the Personalized Print Markup Language specification version 2.0. This version of the specification includes support for digital print job ticketing, and has been endorsed by several key industry partners. PPML is designed for "XML-based, efficient printing of documents with reusable and variable content. It was developed through a special program of PODi (The Digital Printing Initiative), a consortium of leading companies in digital printing. The main purpose of the PPML language is to provide object-level addressability and reusability; it provides an open, XML-based architecture for digital print projects. PPML was first introduced to the market at the worldwide 'drupa' exhibition in Dusseldorf in May, 2000, and has become the first widely-adopted print stream based entirely on an open standard. The PPML version 2.0 architecture includes generic printer control. This means PPML 2.0 jobs, including advanced printer features such as duplexing, finishing, and paper selection, can be created without knowing what machine will print them. Any PPML-compliant printer with the appropriate features will accept the same print file, no matter what software created it and what printer does the output. The PPML job ticketing architecture is designed to support ticket data in any format." [Full context]
[January 12, 2002] "The Personalized Print Markup Language is a new, XML-based, industry standard print language developed by the world's leading manufacturers of print technology for high-speed production of reusable page content. It has been developed through a special program of PODi - the Digital Printing initiative, a consortium of leading companies in digital printing. The purpose of this language is to provide a fast, industry-standard way to print documents that have reusable content. The language uses XML, the Extensible Markup Language, as its syntactical base, giving it an affinity to many Web-based applications... PPML is an open, interoperable, device-independent standard that will enable the widespread use of personalized print applications. It is a standard developed with commercial intent, to create commercial impact - to genuinely change the economics of personalized printing." [From the PODi information server, 2002-01.]
[January 12, 2002] Pageflex Persona Publishing Application Supports Personalized Print Markup Language (PPML). The version 1.5 release of 'Pageflex Persona' from Pageflex, Inc. offers enhanced support for the Personalized Print Markup Language (PPML) specification, providing [one of] "the first variable publishing solutions to use XML as the intermediate data format between a profile database and the page composition process." The Persona desktop application offers improved optimization for PPML and for CreoScitex VPS (Variable Print Specification) output drivers. [Full context]
PPML description from Dave deBronkart: "PPML is a new printer language gaining widespread support in variable data printing applications. PPML uses XML as its syntactical base, and can access page content files generated in many different formats. Applications will ultimately range from desktop to high-end digital printing presses. PPML output is being integrated into a variety of complete workflows, several of which can use other XML methodologies. We envision a fully automated workflow of the future, in which data may flow directly from its source to automated production equipment, untouched by human hands, with every aspect of the process expressed in XML. In such a workflow, PPML will be the printer language by which content and page layout are delivered to the output system." [Paper presented at XML Europe 2001]
Hierarchical structure of PPML: "PPML is a hierarchical structure, in which the properties and resources of an element are inherited from its enclosing ('parent') structure. The contents of the child element may temporarily override (or mask) the parent's properties and resources; when the child element ends, the previous state is restored. [1] A PPML element (the highest level) can contain resource definitions and JOB elements. [2] A JOB element (a set of personalized documents) can contain resource definitions and DOCUMENT elements. [3] A DOCUMENT element (which prints one complete document, of one or more pages) can contain resource definitions and PAGE elements. [4] A PAGE element can contain resource definitions and MARK elements. MARK elements are what actually cause page content to be printed onto a page, using ink or toner. PPML, JOB, DOCUMENT and PAGE are known as levels in the PPML hierarchy. [5] A MARK element (which places image marks on a page) can contain two kinds of content elements: OBJECT and OCCURRENCE_REF. (Each of these content elements contains smaller elements as well.)..." [v1.5 spec]
PPML and printer languages. "PPML is independent of printer language: PPML can be used to create output that will support any printer language. Manufacturers will decide which languages a particular machine will support. PPML machines have already been announced that will support PostScript, PDF, TIFF, and JPEG. We expect to see support for numerous other languages in the future. For information on a specific product, contact the manufacturer. This is comparable to choosing a laser printer today: if you want, you can buy a printer that supports PostScript, PCL, or some other combination... PPML is a meta-language. It describes the structure of jobs, documents, and pages. It places 'marks' on a page via PPML elements, which point to content data, such as EPS files [Encapsulated PostScript]. PPML itself does not describe page content; rather, it selects content elements, to be placed on a page. For instance, there is nothing in PPML that says 'Go to this point on the page and draw a three inch circle filled with red.' Instead, the PPML code might say 'At this point on the page, place file ThreeInchRedCircle.EPS.' [from the FAQ]
PODi "offers a free Developer Support discussion forum for PPML. Additional specification information available through the forum includes (1) A PPML Quick Reference Card, which summarizes the PPML language on a Single page, and (2) Errata document (list of known errors in the current specification)."
PPML origins: "PPML 1.0 grew out a combined proposal approved in July 1999 by the PPML Working Group. This proposal was a merger of proposals from Scitex, Barco and Pageflex: Scitex, by way of its VPS language, contributed the foundation for the basic object model, object-level granularity, and job structure of PPML; Barco contributed the foundation for the production-centric parts of the specification, including major work on imposition; PageFlex contributed the original proposal for an XML-based language called PPML. NexPress contributed substantial work from its proposed vPDF specification, and Xerox presented additional information at the July conference based on its substantial experience with its VIPP PostScript-based variable data software..." [from the May 2001 specification]
PODi PPML Working Group [v1.5]. In alphabetical order: Adobe Systems: John Green; Agfa: Roger Baeten and Marcus Delhoune; Barco: Dirk De Bosschere; EFI: Margaret Motamed; HP: Bob Taylor; IBM: D. R. Palmer; Indigo: Sigal Krumer and Ouri Poupko; NexPress: David Blaszyk, Tim Donahue, and Wayne Minns; Pageflex: Peter Davis; Scitex: Jacob Aizikowitz, Israel Roth, and Reuven Sherwin; Xeikon: Anthony Porter; Xerox: Steve Strasen.

Pageflex Persona

The version 1.5 release of 'Pageflex Persona' from Pageflex, Inc. offers enhanced support for the Personalized Print Markup Language (PPML) specification, providing [one of] "the first variable publishing solutions to use XML as the intermediate data format between a profile database and the page composition process." PPML, developed by a working group of the Digital Printing Initiative (PODi), "is a new XML-based printer language gaining widespread support in variable data printing applications. PPML is an open, interoperable, device-independent standard designed to enable the widespread use of personalized print applications. PPML uses XML as its syntactical base, and can access page content files generated in many different formats. Applications will ultimately range from desktop to high-end digital printing presses. PPML output is now being integrated into a variety of complete workflows, several of which can use other XML methodologies." The Persona desktop application offers improved optimization for PPML and for CreoScitex VPS (Variable Print Specification) output drivers.
"The Personalized Print Markup Language is a new, XML-based, industry standard print language developed by the world's leading manufacturers of print technology for high-speed production of reusable page content. It has been developed through a special program of PODi - the Digital Printing initiative, a consortium of leading companies in digital printing. The purpose of this language is to provide a fast, industry-standard way to print documents that have reusable content. The language uses XML, the Extensible Markup Language, as its syntactical base, giving it an affinity to many Web-based applications... PPML is an open, interoperable, device-independent standard that will enable the widespread use of personalized print applications. It is a standard developed with commercial intent, to create commercial impact - to genuinely change the economics of personalized printing." [From the PODi information server, 2002-01.]
From the announcement:
Pageflex, Inc. announced today the release of Pageflex Persona 1.5. Persona is Pageflex's desktop application for variable content publishing. Persona 1.5 provides improved optimization for PPML (Personalized Print Markup Language) and CreoScitex VPS (Variable Print Specification) output drivers. In addition, Persona supports other vendor specific output drivers, such as, Indigo JLYT and Xeikon Intellicache. The VPS driver for Persona is available through Xerox. PPML and all other vendor specific output drivers may be purchased separately from Pageflex.
Persona provides page layout and composition tools, including the ability to design page templates and modify composition settings, such as leading, kerning, justification, and hyphenation. Persona users can create conditional rules that determine which content is used in each copy of a document based on a database of customer profiles. Text and image containers then "flex" (resize) based on the size or orientation of the dynamic content that flows into them. In addition, surrounding containers move in concert to adjust with the change, maintaining the page design integrity. Persona is the first variable publishing solution to use XML as the intermediate data format between a profile database and the page composition process.
PPML is a new XML-based industry standard print language for high-speed production of reusable page content. It is an open, interoperable, device-independent standard that will enable the widespread use of personalized print applications. PPML was developed by the world's leading manufacturers of print technology (including Pageflex) as part of the Print on Demand Initiative (PODi).
Principal references:
Announcement 2002-01-08: "Pageflex Releases Persona 1.5. New Release Provides Enhanced Support for PPML and VPS Output."
PPML web site
PPML v 1.02 XML DTD
"The PPML Print Language in XML Workflows for Digital Print." By Dave deBronkart. Paper presented at XML Europe 2001, May 21-25, 2001, Internationales Congress Centrum (ICC), Berlin, Germany.
Related:
"Job Definition Format (JDF)."
printcafe eProduction eCommerce eXchange (PCX)
Printing Industry Markup Language (PrintML)
PML: Markup Language for Paper and Printing
PrintTalk Consortium
XML for Publishers and Printers (XPP)
"Personalized Print Markup Language (PPML)" - Main reference page.

Pageflex

Pageflex is a variable publishing platform that provides the flexible capabilities you need to produce all things variable. Pageflex offers unparalleled design control with powerful graphic design features created specifically for variable publishing. You can produce rich, creative, award-winning document designs that look like they were given the individual attention of a graphic designer but were, in reality, created on-the-fly with Pageflex variable publishing technology.
Pageflex provides a flexible, scalable platform to meet the demands of a broad spectrum of variable data projects, regardless of the media used to deliver them. No third-party software dependencies dictate your workflow. One application supplies all functionality you need to produce all things variable. You can produce a wide variety of printed materials including direct mail, business cards, signage, packaging, and custom books. You can extend a campaign to include personalized URLs, microsites, and HTML e-mail.
Pageflex has the server support you need to run small and large installations. The queue-based architecture lets you add new servers quickly. Automatic failover and backup options make sure your system is running all day every day.
Flexible Modules
The flexible modules offered by Pageflex mean this is a technology that grows with you as your business grows. Simply choose the features you need, and start producing results immediately. You can continue to turn on new features and expand your capabilities over time.
Data Merge—Direct mail documents: postcards, brochures, flyers, forms
Form-Driven Customization—Stationery, business cards, marketing collateral
Online Design and Editing—Design or edit documents through a Web browser such as postcards, business cards, and other collateral
Cross Media Campaigns—Personalized URLs, Web sites, and personalized e-mail

Tuesday, August 12, 2008

PPML Introduction

PPML is the industry's first open, interoperable, device-independent standard that enables the widespread use of personalized print applications in high volumes. This XML-based print language enables personalized print to be more flexible, easier to use and more affordable to produce. It supports a full range of on-demand printing ranging from the office environment to high-speed production environments.. First introduced in 2000, and now in its third generation, PPML is supported by dozens of companies across different market segments.

“New PPML applications are being announced every few months,” observes Rab Govil, president of PODi. “PPML is the fastest and most versatile language of its kind, substantially changing the value proposition for digital print. It’s ideally suited for direct mail and fulfillment applications in the graphic arts, and is today the most widely adopted variable data language.”

PODi’s standards development group wrote the PPML specification. The team consists of twenty-four leading technical and marketing figures from the digital print industry. Rapid development has continued to increase capabilities, and enhance interoperability across the digital print spectrum.

To learn more about the PPML and what the PPML family of standards offers, download the Introduction to PPML now. [PDF file. 8 pages/478K/Jul-2003]
To download the PPML specifications, click here

Thursday, July 24, 2008

Building Flex Applications with JSPs

Problem Summary

Flex applications are client side applications which must communicate over the network to retrieve data from and store data in a database. There are many ways to communicate between the client and the server. If you are using Java you may already have JSPs which allow your users to view and modify data. How can you put a Flex UI front-end on top of your existing JSP based infrastructure?

Solution Summary

Flex can make requests to your existing JSPs using the HTTPService object. These requests can work with any JSPs. A Flex application contains all of the view logic so the JSPs should not return HTML but rather just serialized data.

Explanation

You might have a JSP similar to this one:

<%@page import="flex.samples.product.ProductService,
                                flex.samples.product.Product,
                                java.util.List"%>
<html>
<body>
<table>
  <tr>
    <th>Name</th>
    <th>Description</th>
    <th>Price</th>
    <th>Image</th>
    <th>Category</th>
    <th>Quantity</th>
  </tr>
<%
        ProductService srv = new ProductService();
        List list = null;
        list = srv.getProducts();
        Product product;
        for (int i=0; i<list.size(); i++)
        {
                product = (Product) list.get(i);
%>    
    <tr>
        <td><%= product.getName() %></td>
        <td><%= product.getDescription() %></td>
        <td><%= product.getPrice() %></td>
        <td><%= product.getImage() %></td>
        <td><%= product.getCategory() %></td>
        <td><%= product.getQtyInStock() %></td>
    </tr>
<%
        }
%>
</table>
</body>
</html>

This JSP just displays a simple HTML table of data which it fetched from the database.  If you have a Flex application and want to display the same data in a tabular format you may just use a DataGrid in your mxml application.  To get the data into your DataGrid you will need to modify the JSP so that it outputs serialized data rather than HTML:

<%@page import="flex.samples.product.ProductService,
                                flex.samples.product.Product,
                                java.util.List"%>
<?xml version="1.0" encoding="utf-8"?>
<catalog>
<%
        ProductService srv = new ProductService();
        List list = null;
        list = srv.getProducts();
        Product product;
        for (int i=0; i<list.size(); i++)
        {
                product = (Product) list.get(i);
%>    
    <product productId="<%= product.getProductId()%>">
        <name><%= product.getName() %></name>
        <description><%= product.getDescription() %></description>
        <price><%= product.getPrice() %></price>
        <image><%= product.getImage() %></image>
        <category><%= product.getCategory() %></category>
        <qtyInStock><%= product.getQtyInStock() %></qtyInStock>
    </product>
<%
        }
%>
</catalog>

Since this JSP now outputs XML serialized data, Flex will be able to parse that data and turn it into objects which can then be displayed in the DataGrid.  The entire Flex application to request the data and display it in a DataGrid could be as simple as:


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="srv.send()">
    <mx:HTTPService id="srv" url="catalog.jsp"/>
    <mx:DataGrid dataProvider="{srv.lastResult.catalog.product}"/>
</mx:Application>

The HTTPService tag instantiates an object which will make the request to the JSP and deserialize the results into object.  The url property on the HTTPService should point to the JSP which returns the XML data.  The DataGrid tag instanciates an object which will display objects in a tabular format.  The dataProvider property on the DataGrid tells the DataGrid which data to display.  In this case the value uses data binding.  A binding expression goes between the curly braces.  The data binding tells the DataGrid to watch the specified object for changes and when changes occur the DataGrid will refresh it's view of the data.  In this case the dataProvider is set to bind to the lastResult property on the HTTPService object (srv is the referencable identifier of the HTTPService).  The lastResult object contains an object named "catalog" which corresponds to the catalog node of the XML which is returned from the JSP.  On the catalog node there is another array of nodes in the XML called "product".  Thus the expression "srv.lastResult.catalog.product" corresponds to the array of product which are returned from the HTTPService request to the JSP.  The finial piece of logic in the code is an event handler which causes the Flex application to make a request to the JSP.  The "creationComplete" event handler is triggered when the Flex application has fully initialized.  When this event is triggered the Flex application makes a request to the JSP by calling the send method on the HTTPService.

Remote Object Service in Flex

» Der Remote Object Service in Flex

Was unterscheidet den Remote Object Service vom HTTPService oder dem WebService?
Wie auch der HTTPService und der WebService greift der Remote Object Service über das HTTP Protokoll auf die Ressourcen des Servers zu. Im Gegensatz zu den erst genannten Services benutzt der RemoteObject Service aber nicht das auf Text basierende XML Format für den Informationsaustausch, sondern das proprietäre AMF (Action Message Format). Dieses codiert die auszutauschenden Informationen binär, die gesendete Nachricht wird dadurch wesentlich kleiner und kann schneller übertragen werden.
Java Entwickler mag diese Technik an die RMI API erinnern und der Vergleich ist durchaus angebracht. RMI nutzt jedoch statt des HTTP Protokolls (Port 80) ein eigenes Übertragungsprotokoll, scheitert damit an den meisten Firewalls und macht deshalb nur in firmeninternen (oder anderen geschlossenen) Umgebungen Sinn. Im Gegensatz dazu kann der Remote Object Service ohne Einschränkungen auch im Internet verwendet werden.

darstellung des RemoteObject Service mit dem Flex Data Service


Das POJO auf dem Tomcat
Um den Remote Object Service zu verwenden, muss zunächst ein Service Objekt in Java implementiert werden, welches die auf dem Client benötigten Methoden zur Verfügung stellt. Die Methoden, die der Client später verwenden soll, müssen als public deklariert werden. Die Klasse muss sich zudem im CLASSPATH des Flex Data Service befinden und einen leeren Konstruktor haben. Eine simple Testanwendung könnte wie folgt aussehen:

 Die Service Klasse auf dem Tomcat


public class RemoteObjectService {

public RemoteObjectService() {}

public String sayHello() {
return "Hallo Flexwelt";
}
}

Bekanntmachen der Klasse
Damit der Flex Data Service die erzeugte Klasse als RemoteObject erkennt, muss diese in der remote-config.xml bekannt gemacht werden. Die remote-config.xml befindet sich, genau wie die proxy-config.xml, im Verzeichnis WEB-INF/flex unterhalb des Context-Root.
Für die erzeugte Service Klasse wird eine neue Destination angelegt. Diese bekommt eine eindeutige Id, die später in der Flex Anwendung zur Referenzierung des entfernten Objektes gebraucht wird. Zusätzlich wird der vollständige Klassenname und der Scope deklariert.

 Auszug aus der remote-config.xml          




org.fleksray.samples.RemoteObjectService
application



Scoping
Die drei Möglichkeiten um einen Scope zu definieren sind application, session und request. Diese Varianten den Scope zu definieren sind Java Entwicklern hinreichend bekannt, deshalb hier nur eine kurze Erklärung.
Wird für das RemoteObject der Scope application definiert, wird für jede Serverinstanz nur eine einzige Klasse instantiiert. Alle Anwender der Applikation greifen also auf das gleiche Objekt zu. Im session Scope wird für jeden User ein eigenes Objekt angelegt. Dieser Scope wird deshalb in der Regel für Session Tracking, das Speichern von Warenkörben und Ähnlichem verwendet. Im request Scope wird für jeden HTTP Request ein neues Objekt erzeugt. Dieser Scope erhöht die Rechenlast des Servers empfindlich und sollte nur, wenn unbedingt notwendig angewendet werden.
21. Oktober 2007

» Aufruf entfernter Methoden

Verarbeiten der Daten auf dem Client mit Hilfe der Binding Expressions
Um die vom RemoteObject bereitgestellten Daten zu verarbeiten, stehen dem Entwickler zwei Möglichkeiten zur Verfügung: Binding Expressions und in ActionScript geschriebene Event Handler. Erstere Methode ist einfacher und weniger verbose. Werden dagegen eigene Event Handler benutzt stehen mehr Möglichkeiten zur Verfügung, die Daten zu verarbeiten.
Mit Hilfe der Binding Expression ist das entgegennehmen der Daten recht einfach.

 Auszug aus der MXML Datei die das RemoteObject verwendet


destination="myRemoteObjectService"/>




Verwenden der Event Handler
Das RemoteObject löst bei erfolgreicher Datenübertragung ein ResultEvent aus. Lief etwas schief wird ein FaultEvent getriggert. Innerhalb der Event Handler können die Ergebnisse des entfernten Methodenaufrufes vielfältiger gehandhabt werden, als mit den Binding Expressions.

 Die MXML Datei verwendet nun Event Handler





import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;

[Bindable]
private var _message:String;

private function handleResult(ev:ResultEvent):void {
_message = ev.result.toString();
}

private function handleFault(ev:FaultEvent):void {
_message = "das ging daneben: "
+ ev.fault.faultCode + " :: "
+ ev.fault.faultDetail + " :: "
+ ev.fault.faultString;
}
]]>


destination="myRemoteObjectService"
result="handleResult(event)"
fault="handleFault(event)"/>






Ein FaultEvent kann leicht ausgelöst werden, indem im click Handler des Buttons auf eine nicht existierende Methode des RemoteObject zugegriffen wird ( click="{myRemoteObject.sayGoodBye()}")
Result Handler Dispatching im RemoteObject
Wie geht man nun mit Service Objekten um, die dem Client eine ganze Reihe von Methoden zur Verfügung stellen. Im RemoteObject wird im oben gezeigten Beispiel nur einen Result Handler defininiert, der für genau eine Methode zuständig ist..
Ein erster, einfacher Ansatz wäre, im Result Handler eine switch-case Anweisung zu schreiben, die anhand des übergebenen Events die aufzurufende Methode erkennt.
Flex bietet eine elegantere Lösung. Innerhalb des RemoteObject können den Service Methoden jeweils unterschiedliche Result Handler zugeordnet werden.

 Dispatching der Events an unterschiedliche Handler





import mx.collections.ArrayCollection;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;

[Bindable]
private var _message:String;
[Bindable]
private var _data:ArrayCollection;

private function handleHelloResult(ev:ResultEvent):void {
_message = ev.result.toString();
}

private function handleDataResult(ev:ResultEvent):void {
_data = ev.result as ArrayCollection;
}

private function handleFault(ev:FaultEvent):void {
_message = "das ging daneben: "
+ ev.fault.faultCode + " :: "
+ ev.fault.faultDetail + " :: "
+ ev.fault.faultString;
}
]]>


destination="myRemoteObjectService" fault="handleFault(event)" >
name="sayHello" result="handleHelloResult(event)" />
name="getTestData" result="handleDataResult(event)" />




click="{myRemoteObject.sayHello()}"/>




click="{myRemoteObject.getTestData()}"/>



Im gezeigtem Beispiel wird für jede Methode des Service Objektes ein eigener Result Handler deklariert, der Fault Handler wird von allen Methoden gemeinsam benutzt. Es ist auch möglich, jeder Methode einen eigenen Fault Handler zuzuweisen.
31. September 2007

» Übergabe von Argumenten

In den meisten Fällen wird von einer Applikation mehr verlangt, als nur einfache Methoden aufzurufen. In der realen Welt müssen Eingaben des Benutzers an den Server weitergeleitet werden und zu einer entsprechenden Response umgesetzt werden. Die Eingaben werden, wie in bei Html auch, oft über Formulare entgegengenommen und dann verarbeitet.
Das RemoteObject muss also auch in der Lage sein, Argumente zu verarbeiten. Im folgendem Beispiel soll das Service Objekt auf dem Server aus zwei übermittelten Strings ein personalisierte Begrüßung bauen.

 Die Java Klasse übernimmt Argumente


public class AnsweringService {

public AnsweringService() {}

public String sayHello(String title, String name) {
return "Hallo " + title +" " + name;
}
}

In der MXML-Datei werden die Argumente innerhalb des <method> Tags deklariert. Hier können statische Werte oder Binding Expressions verwendet werden.
Das Tag erwartet ein Array mit Parametern. Wie diese Parameter benannt werden, ist unwesentlich. Der Konsistenz halber sollten sie aber wie die Argumente der Java Klasse benannt werden. Entscheidend ist die Reihenfolge der Argumente. Das zuerst deklarierte Element wird als erstes Argument an das Objekt auf dem Server übergeben.
Werden Argumente in der beschriebenen Weise übergeben, muss im Click EventHandler die Methode send() an der Remotemethode aufgerufen werden.

 Senden von Argumenten an das Objekt auf dem Tomcat Server





destination="myAnsweringService">


<br /> {title.selectedItem.toString()} <br />

{myName.text}











id="title"
dataProvider="['Frau','Herr','Mrs.','Mr.']"/>


id="myName"/>



click="{myAnsweringObject.sayHello.send()}"/>

Adobe Flex LiveCycle Data Service

» Der Adobe Flex LiveCycle Data Service

adobe flex lifecycle dataservice
Flex Data Service ist jetzt Livecycle Data Service Express
Adobe hat mit der Veröffentlichung des Flexbuilders 3 beta dem Flex Data Service einen neuen Namen gegeben. Die Serverkomponente des Flex Frameworks nennt sich nun Adobe LiveCycle Data Service.
Zu den schon bekannten Komponenten des Flex Data Service gesellen sich nun die Features des LiveCycle Services, wie Dokumenten- und Formularprocessing. LiveCycle war vorher eine eigenständige Software, die hauptsächlich mittlere und große Firmen als Kunden im Visier hatte.
Die Express Version der Software kann kostenlos von der Adobepage heruntergeladen werden. Im folgenden Artikel sollen die Teile des Service vorgestellt werden, die auch schon im Flex Data Service enthalten waren und eben für Flex Entwickler interessant sind.
Adobe nennt die Software abwechselnd "Flex Data Service" oder "LiveCycle Data Service Express". Beide Begriffe werden hier synonym verwendet.
01 Oktober 2007

» Installation und Starten des Adobe LiveCycle Dataservice

Der Flex Dataservice kann unter der URL http://www.adobe.com/cfusion/tdrc/index.cfm?product=livecycle_dataservices für unterschiedliche Betriebssysteme heruntergeladen werden. Für den Download muss man sich einen Account bei Adobe einrichten und anschließend mit Email und Passwort einloggen.
Im Folgenden wird die Installation unter Windows und gängigen JEE Servern beschrieben. Grundsätzlich lassen sich zwei Arten der Installation unterscheiden.
Der Flex Dataservice kann als Komplettpaket installiert werden. Diese Variante enthält JRun als Java Server Runtime. Dieses Paket steht als *.exe-Datei zu Verfügung und installiert eine ready to go Version der Adobe Software.
Für den Einsatz in einer Produktionsumgebung kommt eher die Installation als *.war-File auf einem existierenden JEE-Applicationsserver in Frage, da JRun nur als Entwicklungsumgebung kostenlos zu haben ist.
Installation des vorkonfigurierten Komplettpaketes
Ein Doppelklick auf die ausführbare Datei öffnet einen Wizard der durch die Installation führt. Nach dem Bestätigen der Lizenzbestimmungen wird der Benutzer nach einer Seriennummer gefragt. Für die Installation der Expressversion wird dieses Feld frei gelassen. Die Expressversion des Data Service ist voll funktionsfähig und kann auch für kommerzielle Projekte genutzt werden, ist jedoch auf die Nutzung einer CPU beschränkt. Die genauen Bestimmungen zur Nutzung finden sich auf der Adobe Seite.
Anschließend wird das Installationsverzeichnis gewählt (alle weiteren Angaben im Artikel beziehen sich auf das Standard Installationsverzeichnis c:\lcds). Dann hat der User die Wahl, den Dataservice mit integriertem JRun Servlet Container oder als JEE Applikation zu installieren. Als Entwicklungsumgebung ist JRun ausreichend, als Produktionsserver sollte jedoch einer der Standard JEE Applicationserver zum Einsatz kommen. Es erscheinen noch die üblichen Standardabfragen, dann beginnt die Installation.

JRun Launcher

Nach Beendigung der Installation befindet sich im Verzeichnis c:\lcds ein Unterordner JRun/bin. Wird die im Verzeichniss befindliche jrun.exe ausgeführt, öffnet sich der JRun Launcher, mit der sich der Server starten, restarten und stoppen lässt. Nach Selektieren des default-Eintrages und einem Klick auf den Start Button fährt der Server hoch.
Unter der Adresse http://localhost:8700 kann nun die lokale Instanz von JRun angesprochen werden.
Installation unter einem Java Web Application Server
Die Installation des Flex Data Service unter einem JEE Server ist ebenfalls leicht durchzuführen. Alle *.war Dateien, die sich nach der oben durchgeführten Installation in c:\lcds befinden, laufen ohne Probleme auch in den ensprechenden Deploy Verzeichnissen typischer JEE-Server.
Tomcat: $CATALINA_HOME/webapps
JBoss: $JBOSS_HOME/server/default/deploy
Wird beispielsweise das c:\lcds\samples.war in das webapps Verzeichniss des Tomcat kopiert, ist nach einem restart/redeploy die Applikation unter localhost:8080/samples zu erreichen.
Gleiches gilt für JBoss und andere JEE konforme Applicationserver. Für eigene Entwicklungen sind die mitgelieferten Anwendungen der Standardinstallation also ein guter Ausgangspunkt.

From the scratch
Soll eine Webanwendung, die den Flex Data Service nutzt, von Grund auf entwickelt werden, sind einige Kleinigkeiten zu beachten.
Im WEB-INF Verzeichniss muss ein Unterordner mit dem Namen flex existieren, der sämtliche Konfigurationsdateien des Dataservice enthält. Auch hier empfiehlt es sich, den Ordner aus einer Beispielanwendung zu kopieren.
Im WEB-INF/lib Verzeichniss müssen alle nötigen flex-*.jar Dateien vorhanden sein. Auch diese kopiert man am besten aus einer Beispielanwendung. Dann müssen noch sämtliche Eintragungen der web.xml, die sich im flex/WEB-INF Verszeichnis befindet, in die schon bestehende web.xml übernommen werden.
Ebenfalls eine gute Grundlage für Eigenentwicklungen ist der mit dem Dataservice vorkonfigurierte Tomcat, der auf der Adobe Seite unter http://www.adobe.com/devnet/flex/articles/java_testdrive.html heruntergeladen werden kann.
10. Juli 2007

» Der Proxy Service des Flex Data Service

Der Flash Sandkasten
Jedem Flash und Java Applet Entwickler ist die Thematik der sogenannten Sandkastenumgebung der Standardbrowser bekannt. Applikationen, die über das Internet aufgerufen werden, haben nur eingeschränkte Zugriffsrechte auf dem Clientrechner.
Solche Anwendungen können nicht auf das lokale Dateisystem zugreifen und nur uneingeschränkt auf Resourcen des Servers zugreifen, von dem sie geladen wurden.
Mit der crossdomain.xml kann diese Einschränkung zwar umgangen werden, dafür braucht der Entwickler jedoch Zugriff auf den Server, auf dem die benötigten Resourcen installiert sind. Das ist jedoch in den seltensten Fällen so.
Ohne Proxy Service können die Services mx.rpc.http.HttpService und der mx.rpc.soap.WebService mit dem Parameter url nur Daten von dem Server abrufen, von dem sie selbst geladen wurden.
Mit dem Proxy können die Services auch auf Resourcen anderer Server zugreifen. Die Clientanwendung merkt davon nichts. Der Request wird nach wie vor an den eigenen Server gestellt. Die Proxy Kompenente des LiveCycle Dataservice nimmt die Anfrage entgegen und leitet sie an den entsprechenden Server im Netz weiter. Dafür muss die Eigenschaft useProxy auf true gesetzt werden, nur dann spricht der Proxy Service auch an und liest gegebenenfalls die Eigenschaft destination aus.
Der url Parameter
Im folgenden gehen wir von einer Applikation mit dem Namen myApplication aus, die einen HTTPService enthält. Der Sourcecode sieht vereinfacht so aus:

  




url="data/myDataFile.xml" />



Das Programm lädt die Daten vom eigenem Server, das Verzeichnis "data" befindet sich dabei auf der gleichen Ebene wie das swf-File der Flexapplikation.

Im url Parameter kann auch eine absolute Adresse angegeben werden. Vorausgesetzt die Applikation wird über die URL http://localhost/myApplication aufgerufen, kann auch dieser Code verwendet werden.
url="http://localhost/data/myDataFile.xml" />

Das funktioniert nicht und löst einen Cross Domain Security Error aus!
url="http://127.0.0.1/data/myDataFile.xml" />

Die Default Destination
Unter einer Destination ist der Endpunkt einer Kommunikationskette zu verstehen. Auch in der Webservice Entwicklung wird der Begriff Endpunkt (natürlich in englisch -> endpoint ) verwendet. Damit eine bestimmte Ressource über den Proxy Service angesprochen werden kann, müssen in der proxy-config.xml einige Einstellungen vorgenommen werden. Die proxy-config.xml sieht im Normalfall so aus.

 Die proxy-config.xml




proxy-service"
class="flex.messaging.services.HTTPProxyService"
messageTypes="flex.messaging.messages.HTTPMessage,flex.messaging.messages.SOAPMessage">



100
2




http-proxy"
class="flex.messaging.services.http.HTTPProxyAdapter"
default="true" />
soap-proxy"
class="flex.messaging.services.http.SOAPProxyAdapter" />



my-http" />
my-amf" />


DefaultHTTP">




Standardmäßig ist in der proxy-config.xml bereits ein Eintrag für die Default Destination vorhanden, dieser ist jedoch leer.
Um Proxy Zugriffe über den Flex Data Service zu ermöglichen, muss der Eintrag erweitert werden.

 Ergänzung der Destination


DefaultHTTP">

http://127.0.0.1:8700/*



Der Stern am Ende der URL ermöglicht dem Flex Client auf jeden möglichen Webservice des (scheinbar) entfernten Servers zuzugreifen.

Zum genaueren Verständnis.
Hier im Beispiel stellt der der Server mit der IP 127.0.0.1 den Remoteserver dar. Die Clientanwendung, aufgerufen über http://localhost:8700/myApplication kann im Normalfall nicht auf den den eigenen Server über die URL http://127.0.0.1:8700 zugreifen. Die crossdomain-policy sieht in den Servern mit den URL's http://localhost und http://127.0.0.1 zwei verschiedene Hosts.
Um in einer Entwicklungsumgebung mit dem Proxy Service zu experimentieren eignen sich diese URL's gut, um zwei unterschiedliche Server zu simulieren.

Nun muss noch im HTTPService die useProxy Eigenschaft auf true gesetzt werden.

          

id="myService"
url="http://127.0.0.1/data/myDataFile.xml"
useProxy="true" />


Der HTTPService ist nun in Lage die Resource myDataFile.xml über den Umweg des Proxy Service vom (vermeintlich) entfernten Server abzurufen.

Die Named Destination
Mit der named Destination entscheidet der Client nicht mehr selbst, welche URL, von welchen Remoteserver aufgerufen wird. Dem Client ist lediglich die Id des Services bekannt. Den Proxy Service mit der richtigen URL zu spezifizieren, liegt nun in der Hand der Servers. Dadurch wird die Sicherheit des Systems beachtlich erhöht. Anwendungen auf Clientseite können nicht mal eben verschiedene URL's ausprobieren.

 Der geanderte Eintrag in der proxy-config.xml


id="myProxyService">

http://127.0.0.1:8700/flex/data/myService.xml



Statt einer URL wird im HTTPService jetzt der Parameter destination verwendet. Die Destination, die im HTTPService angegeben wird, muss mit der Destination Id in der proxy-config.xml übereinstimmen.

 Im HTTPService wird die enfernte Ressource uber die Id aufgerufen


id="myService"
destination="myProxyService"
useProxy="true" />

Flex LiveCycle DataManagement Service and Hibernate

» Flex LiveCycle DataManagement Service und Hibernate im Zusammenspiel

Hibernate und Adobe Flex Frontends lassen sich in einfacher Weise mit dem DataManagement Service verbinden. Damit lassen sich in Java entwickelte Klassen eins zu eins in eine Flex Anwendung übernehmen. Alle Änderungen an Objekten im Flex Client werden direkt auf die Java Objekte übertragen.
Wird der DataManagement Service in Verbindung mit Hibernate verwendet, ist es nicht einmal nötig DataAccess Klassen zu entwickeln. Alle Create-, Update- und Delete-Operationen werden direkt auf die Java Objekte angewendet (hinter den Kulissen führt die Klasse flex.data.adapters.JavaAdapter des DataManagement Service die CRUD Operationen aus).
Diese Vorgehensweise vereinfacht den Entwicklungsaufwand enorm. Die Programmierung von DAO's entfällt.
Die Verwendung des DataManagement Service bringt aber auch Nachteile mit sich. Der Service verwendet das Real Time Messaging Protokoll, das im Normalfall Port: 2038 verwendet.
Der Einsatz beschränkt sich deshalb mehr oder weniger auf Intranet Anwendungen. Soll Hibernate in klassischen Internet Applikationen eingesetzt werden, kommt man nicht umhin, Data Access Klassen zu implementieren und deren Interface per WebService im Netz zur Verfügung zu stellen.

Hibernate mit Flex DataManagement Service

Die Studenten-Kurse Anwendung unter Verwendung von Hibernate


Studenten und Seminare, eine m:n Beziehung
Im folgenden Beispiel wird eine Anwendung entwickelt, mit der es möglich ist Studenten und Seminare zu verwalten. Für diese Entities werden zwei entsprechende Klassen, sowohl in Java, als auch in ActionScript erstellt. Für die Persistenz der Objekte ist Hibernate zuständig. Als Datenbank kommt Hypersonic SQL zum Einsatz. Als Webapplication Server wird Tomcat verwendet.
Mit der Flex Anwendung ist es möglich, Create, Update und Delete Operationen für Studenten und Seminare auszuführen.
Der Einfachheit halber wird auf die Funktionalität verzichtet, Studenten bestimmte Seminare zu zuweisen. In der der Hypersonic Datenbank sind jedoch bereits einige Zuweisungen angelegt. Mit der hier entwickelten Applikation können die Seminare nur angezeigt werden, die von einem bestimmten Studenten belegt werden.

Flex Hibernate

Anzeige der Kurse für die ausgewählte Studentin


Da die komplette Anwendung recht umfangreich ist, wird im Artikel nur auf Ausschnitte des Source Code eingegangen. Die kompletten Quellen finden sich in der Box: Source Code im linken Seitenbereich oben.
25, Oktober 2007

» Die Java Klassen und die Hibernate Config-Files

Die Java Klassen
Für die Entities Student und Course werden zwei Java Beans angelegt, deren Aufbau recht simpel ist.

Die Klasse Student besitzt die Eigenschaften und entsprechenden set- und get-Methoden:
studentNumber; studentFirstName; studentLastName
Die Klasse Course besitzt die Eigenschaften und entsprechenden set- und get-Methoden:
courseNumber; courseName; description

Die Java Klasse Student besitzt ein HashSet namens courses. Dieses Set enthält die Kurse, für die sich der Student eingetragen hat.
Ebenso besitzt die Klasse Course ein HashSet students, das alle Studenten enthält, die diesen Kurs belegen.
Im Beispiel handelt es sich also um eine m:n Beziehung.
Ein Student belegt mehrere Kurse.
Ein Kurs wird von mehreren Studenten belegt.

Die Hibernate Config-Files
Die hibernate.cfg.xml enthält allgemeine Einstellungen zur Datenbank-Connection, zum SQL-Dialect usw. auf die hier nicht weiter eingegangen werden soll.
In der StudentCourse.hbm.xml werden die Klassen Student und Course gemappt. Diese Datei wird im folgendem genauer erklärt.
Das Hibernate Mapping File für die Studenten- und die Course Klasse enthält das Root-Tag . Innerhalb dieses Tags werden die Java Klassen auf die entsprechende Tabelle der SQL Datenbank gemappt.
Bei komplexen Anwendungen erhält jede Javaklasse/Sql-Tabelle ein eigenes Mapping-File. Hier im Beispiel werden die Klassen Student und Course der selben Datei eingetragen. Auf das Mapping der Klasse Student soll etwas genauer eingegangen werden. Das Mapping für die Klasse Course ist ähnlich.

 Die gemappte Student Klasse










name="courses"
table="Course_Student"
inverse="true"
lazy="true"
cascade="save-update">







From Student

Im öffnendem Tag wird der Name der Klasse und die entsprechende SQL-Tabelle angegeben.
Im Tag wird der Primary-Key vereinbart. Im Fall der Klasse Student ist das die Eigenschaft studentNumber, die der Spalte student_number der Tabelle Student in der Hypersonic Datenbank entsprechen soll.
Dann werden die Eigenschaften studentFirstName und studentName deklariert. Solange der Name der Eigenschaft mit dem Namen der Tabellenspalte übereinstimmt, müssen hier keine weiteren Einstellungen vorgenommen werden (Hibernate bietet eine Fülle von Möglichkeiten um die Eigenschaften der Properties feiner zu spezifizieren, darauf soll an dieser Stelle jedoch verzichtet werden).

Im Tag wird ein Collection deklariert, die die Kurse enthält, für die sich der Student eingeschrieben hat. Der Name des Set muß dem Namen des Property in der Klasse Student entsprechen. Als table wird die Tabelle angegeben, die die Beziehung zwischen der Klasse Course und der Klasse Student managed.

Die Tabelle Course_Student enthält lediglich die zwei Spalten student_number und course_number, welche die primary keys der Tabellen Student und Course repräsentieren. Im Tag wird Hibernate die Art der Beziehung, die Klasse zu der die Beziehung aufgebaut werden soll und der primary key eben dieser Klasse mitgeteilt.
Wird die Eigenschaft lazy auf true gesetzt, wird die Student Klasse per default mit einem leeren courses-Set instantiiert. Die Eigenschaft cascade gibt an, wann das Set gefüllt werden soll.

Am Ende wird ein HQL-Query Statment definiert, das in der Flex Anwendung dazu dient, eine Collection mit Studenten Objekten zu füllen. Dazu mehr in der Box: Die Flex Applikation weiter unten.
Das Mapping für die Klasse Course ist nahezu identisch aufgebaut.
25, August 2007

» Die Config-Files für den DataManagement Service

Konfiguration des RMTP-Channels und der Destinations
Wie alle Konfigurationdateien für den Adobe LiveCycle Service sind auch die Config-Files für den DataManagement Service unterhalb des [CONTEXT-ROOT]/WEB-INF/flex Verzeichnisses zu finden. Die beiden relevanten Dateien, für die hier vorgestellte Applikation, sind services-config.xml und data-management-config.xml.
In der services-config.xml muss folgender Eintrag (meist schon per default) vorhanden sein.

 Die Definition des RTMP-channels



class="flex.messaging.endpoints.RTMPEndpoint"/>

20
100K
100K



In der data-management-config.xml Datei werden für die entwickelten Java Klassen so genannte destinations deklariert. Im Tag wird eine frei wählbare ID vergeben. Diese ID wird später in der Flex Anwendung benötigt, um den DataService für die entsprechende Klasse anzusprechen. Innerhalb der Destination werden folgende Angaben gemacht:
Hier wird eine Refererenz auf den Adapter angegeben, der die Verbindung zu den Java Objekten aufnehmen soll. In unserem Fall ist das die Adapter Klasse flex.data.adapters.ASObjectAdapter.

Dann folgen eine Reihe von Eigenschaften, die das Zusammenspiel der entwickelten Java Klassen, Hibernate und dem DataManagement Service regeln. Im folgenden wird nur auf die für unsere Anwendung relevanten Properties eingegangen.

Hier wird die Klasse des Hibernate Assemblers eingetragen, eine Klasse des Flex LiveCycle Service, die die Schnittstelle zu Hibernate darstellt.
Einstellung des "Sichtbarkeitsbereiches" der Student Klasse. Möglich sind: application, session und request.
Angabe des primary key der Student Klasse.
Angabe des kompletten Klassepfades zur Student Klasse.
Name der Fill-Methode und Angabe der Collection Klasse, die später die Studenten Objekte in der Flex Anwendung aufnehmen soll.
Hier ist der Eintrag true wichtig. Dieser erlaubt in der Flex Applikation HQL-Queries aufzurufen, die in der StudentCourse.hbm.xml definiert wurden.

 Die Definition der Student destination in der data-management-config.xml



id="hibernate-student">
ref="java-dao" />

true
flex.data.assemblers.HibernateAssembler
application

property="studentNumber"/>


20





org.fleksray.samples.model.Student

fill
java.util.List


false
true






Der Aufbau für die Course Destination ist ähnlich.
25, August 2007

» Die Flex Applikation

Die Student- und die Course Bean in ActionScript
Um erfolgreich mit den Java Objekten auf dem Tomcat kommunizieren zu können, müssen zwei Klassen in ActionScript implementiert werden, die das Gegenstück zu den Java Klassen Student und Course darstellen. Diese Klassen enthalten die gleichen Properties wie die Java Klassen. Die Properties werden als public Variablen deklariert, auf get- und set-Methoden wird hier verzichtet.
Per Definition muss in den ActionScript Klassen ein leerer Konstruktor deklariert werden. Die Klassen werden als Managed deklariert und ein Alias auf die entsprechenden Java Klassen wird gesetzt.

 Die ActionScript Klasse Student



package org.fleksray.samples.model
{
import mx.collections.ArrayCollection;

[Managed]
[RemoteClass(alias="org.fleksray.samples.model.Student")]


public class Student {

public var studentNumber:Number;
public var studentName:String;
public var studentFirstName:String;
public var courses:ArrayCollection;

public function Student(){}
}
}

Die Klasse Course.as hat einen ähnlichen Aufbau.
Der DataService in Flex Anwendung
In der Flex Applikation ist ein DataGrid zuständig für die Anzeige der Eigenschaften der Studenten. Dieses DataGrid verwendet eine ArrayCollection, die mit Objekten vom Typ Student gefüllt wird. Dafür muss in der Anwendung eine Instanz der Klasse Student und eine Instanz der zu füllenden ArrayCollection erzeugt werden.
Im Tag ist für die destination ein Name erforderlich. Dieser Name entspricht genau der Id, die in der data-management-config.xml für die Student destination vereinbart wurde.

 Auszug aus der Flex Application






destination="hibernate-student"
fault="handleFault(event)"
autoCommit="true" />


autoCommit="true"
Hier im Beispiel wird die Eigenschaft autoCommit auf true gesetzt. Damit wird erreicht, dass alle Änderungen, die an der ArrayCollection studentArray direkt auf den Server übertragen werden. Wird also die Eigenschaft editable des DataGrid auf true gesetzt, werden alle vom Anwender vorgenommen Änderungen, auf die von Hibernate verwalteten Objekte übertragen (ohne das ein Submit-Button o.ä. geklickt werden muss). Anwender die ebenfalls mit dem Server verbunden sind, sehen die vorgenommenen Änderungen sofort, ohne einen Reload ausführen zu müssen. Ein entscheidender Vorteil des Real Time Messaging Protokoll.
Füllen der ArrayCollection
Nun muss noch die ArrayCollection, die als DataProvider für das DataGrid dient, gefüllt werden. Dafür wird die Methode fill() am DataService aufgerufen. Diese Methode wurde oben ebenfalls in der data-management-config.xml unter deklariert.
Der fill() Methode werden drei Argumente übergeben. Erstes Argument ist die zu füllende ArrayCollection, dann folgt der Name des HQL-Query, wie er in der Student.hbm.xml vereinbart wurde. Der dritte Parameter wird hier nicht verwendet.

Der dritte Parameter der fill() Methode.
Der dritte Parameter wird verwendet, wenn direkt HQL-Querys aus der Flex Anwendung abgesetzt werden sollen. Das ist sinnvoll, wenn die Abfrage Variablen enthält, deren Wert zur Kompilierzeit nicht bekannt sind. Der dritte Parameter erwartet eine Array. In diesem Array ist der erste Wert der HQL-Query selbst, gefolgt von den dynamischen Parametern für diesen Query:
hibernateStudent.fill(studentArray, "flex:hql", ["from Student s where s.studentFirstName = :firstName", parameterMap]);
Die parameterMap enthält unter dem key "firstname" den Namen des Studenten, nach dem gesucht werden soll.

oder:

hibernateStudent.fill(studentArray, "flex:hql", ["from Student s where s.studentFirstName = ?", parameterArray]);
hier enthält das parameterArray den Namen des Studenten nach dem gesucht wird. Bei mehreren Parametern ist die Reihenfolge der Parameter zu beachten

Die Methode hibernateStudent.fill() wird in einer Mehtode mit dem Namen initialFill() aufgerufen. Diese Methode wiederum wird beim creationComplete() Event der Applikation aufgerufen. Damit wird das DataGrid beim ersten Aufruf der Applikation gefüllt.
Der DataService stellt weiterhin die Methoden deleteItem und createItem zur Verfügung, also die typischen Methoden einer DAO Klasse. Diese Methoden wurden im Beispiel an keiner Stelle definiert. Die Arbeit dafür übernimmt voll und ganz der Flex DataManagement Service.

 Die Methode zum Löschen von Studenten


private function deleteStudent():void {
hibernateStudent.deleteItem(dgStudent.selectedItem as Student);
}


Der Quellcode für die Anzeige, das Löschen und das Erzeugen von Kursen sieht ähnlich aus.

25, August 2007

Monday, July 21, 2008

Flex and Paypal - Adding a payPal “buy now” button in Flex

Adding a payPal “buy now” button in Flex

I’m in the early stages of developing a paypal shopping cart system in Flex. A cursory glance on the web told me that many of you have questions about this topic. I’ve seen many questions from people using thee HTTPService class to try to do this. It seems (although I’ve only been looking at this for a very short time) that HTTPService will not redirect after a “POST”. So for those wanting to crack this open a bit, here’s a method of sending data to paypal with a redirect from a paypal button using flash.net.URL request. Although this example is very basic, and a full shopping cart app integrated with paypal is obviously alot more work, one can see that doing a simple “buy now” is pretty easy. Most of the (not working) examples I saw were making it much harder than it is. After all the HTML is just:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″ />
<title>Untitled Document</title>
</head>

<body>
<form action=”https://www.paypal.com/cgi-bin/webscr” method=”post”>
<input type=”hidden” name=”cmd” value=”_xclick”>
<input type=”hidden” name=”business” value=”you@youremail.com”>
<input type=”hidden” name=”item_name” value=”Item Name”>
<input type=”hidden” name=”currency_code” value=”USD”>
<input type=”hidden” name=”amount” value=”0.00″>
<input type=”image” src=”http://www.paypal.com/en_US/i/btn/x-click-but01.gif” name=”submit” alt=”Make payments with PayPal - it’s fast, free and secure!”>
</form>
</body>
</html>

Here’s the Flex:

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute” >

<mx:Image source=”http://www.paypal.com/en_US/i/btn/x-click-but01.gif” horizontalCenter=”0″ verticalCenter=”0″ click=”makePayment();”/>
<mx:Script>
<![CDATA[
import flash.net.URLRequest
public function makePayment():void{
var url:String = “https://www.paypal.com/cgi-bin/webscr”;
var request:URLRequest = new URLRequest(url);
var variables:URLVariables = new URLVariables();
variables.cmd=”_xclick”;
variables.currency_code=”USD”;
variables.business=”clayton@tetraktysdesign.com”;
variables.item_number = “001″;
variables.item_name = “Donation to Flex Community For This Awesome Code Sample”;
variables.amount= “2.00″;
variables.quantity = 1;
variables.tax = ”;
request.data = variables;
request.method = URLRequestMethod.POST;
navigateToURL(request,”_parent”);
}
]]>
</mx:Script>
</mx:Application>

The first things that come to mind for me are:

1) get your item data from an external xml file and an HTTPService call

2) use the repeater component to create your buttons (and product shots)

and of course, the whole shopping cart situation … I’ll be up for a while.

Hope this helps some of you.

Flex - creating an xml photo gallery

This is a method of creating a photo gallery in Flex with a main photo, and scrolling thumbnails, populated by an external XML file. This is a continuation of the concept in this article: http://blog.flexcommunity.net/?p=24


This shows how easy it is to create things of this nature using the repeater component, and one simple function. I’ll leave out the detailed explanation, as it’s almost identical to the above cited article.

example here

here’s the application code:


<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” xmlns:custom=”custom.*” layout=”absolute” backgroundColor=”#030303″ creationComplete=”imageData.send();”>
<mx:Script>
<![CDATA[

var mySource:String=”http://path/to/the/first/image/to/display/1.jpg”
function setPath(myPath:String):void{
mainImage.source=myPath;}
]]>
</mx:Script>

<mx:HTTPService id=”imageData” url=”images.xml” resultFormat=”e4x”/>
<mx:Image id=”mainImage” source=”{mySource}” width=”500″ height=”400″ verticalCenter=”0″ horizontalCenter=”0″ >

</mx:Image>
<mx:VBox height=”400″ horizontalScrollPolicy=”off” verticalCenter=”0″ horizontalCenter=”325″>
<mx:Repeater id=”imageRepeater” dataProvider=”{imageData.lastResult.img}”>
<mx:Canvas width=”120″ height=”80″ backgroundColor=”#000000″ horizontalScrollPolicy=”off” verticalScrollPolicy=”off” borderStyle=”none”>
<custom:CustomImage path=”{imageRepeater.currentItem.src}” width=”100″ height=”100%” useHandCursor=”true” source=”{imageRepeater.currentItem.thumbnail}” verticalCenter=”0″ left=”0″ click=”setPath(String(event.currentTarget.path));”/>
</mx:Canvas>
</mx:Repeater>

</mx:VBox>
</mx:Application>

here’s the XML structure:

<?xml version=”1.0″ encoding=”utf-8″?>
<gallery>
<img>
<src>http://path/to/your/large/image/1.jpg
</src>

<thumbnail>http://path/to/your/thumbnail/t1.jpg

</thumbnail>
</img></gallery>


here’s the custom image code (file is called CustomImage.as and is kept in a folder called custom)

package custom
{
import mx.controls.Image;

public class CustomImage extends Image

{
public function CustomImage()
{
super();
}
public var path:String = “”;

[Inspectable(category=”General”, defaultValue=”")]

}
}


Sunday, July 20, 2008

Web app to extract torrent files out of Blizzard Downloader

Diablo 3 was announced today and like many thousands of other gamers online right now I’m trying to download the 800mb high def gameplay trailer while putting up with the very clumsy Blizzard Downloader application. For those who don’t know, the Blizzard Downloader is just a mini BitTorrent client with a single torrent file baked in. I’m not a big fan of the downloader because I already have a BitTorrent client that’s much better at bandwidth allocation and my firewall’s already set up for that client. I’d much rather download the movie with my own client instead of Blizzards so I’ve written a little flash app to help facilitate that.


To use this, just point the app at the url of any Blizzard Downloader exe file online (I’m not sure if it’ll work with the .dmg files) and hit the ‘Extract’ button. A link will pop up below that you can click to save the torrent file. The file has no name by default so you’ll have to rename it ‘whatever.torrent’ after it finishes downloading. The resulting torrent will still connect to Blizzards tracker and you’ll download the same file you would be if you were using the Blizzard Downloader app.

This should work with all browsers other then IE 7 and below, since IE doesn’t support the data:URI scheme to create dynamic files.


View Source

Example URLs:
Diablo 3 Gameplay Downloader
Starcraft 2 Gameplay Downloader

More Info:
Blizzard Downloader Wiki


Introducing GUIMark - An RIA benchmark for Flex, Silverlight, HTML and more

If you’re wondering why I’ve been quiet the past few weeks it’s because I’ve been devoting most of my free time to finishing off a new benchmark I’m releasing today called GUIMark. GUIMark is kinda like an Acid3 test on speed that’s geared towards RIA technologies. The goal was to figure out how to implement a reference design in different runtimes and then benchmark how smoothly that design could be animated. So far I have implementations in DHTML, Flex, Java, Silverlight 1 and Silverlight 2. All the results and and implementation details can be found under the GUIMark page.


GUIMark shares alot in common with another RIA benchmark Bubblemark. I’ve written a bit about Bubblemark and why I think an alternative is necessary, but I do believe Bubblemark and GUIMark can coexist while serving 2 different purposes. Alexey Gavrilov stated it best in that he sees Bubblemark as a sortof ‘Hello World’ launchpad into comparing different environments and I agree with him. Bubblemark is a *very* accessible test suite and its easy for any kind of developer to jump in and play around with performance techniques. GUIMark takes a different approach by trying to benchmark the types of UI elements common in our Web 2.0 world. This includes things like vector redraws, alpha transparencies, text reflow, bitmap motion, and 9 scale slicing rules. From there I just fill up the render pipeline until it becomes so over-saturated that it becomes easy to visually distinguish which rendering engines are more efficient then others. As a result, the benchmark is more complicated on a visual level and requires a bit more time then Bubblemark to understand the implementation rules. Lastly with GUIMark I’ve tried to get into some of the lower level details behind how rendering engines work and how that’s affected the creation of this project.

I’m hoping that developers and designers will be able to use this test suite to identify any pros or cons to choosing a particular environment when visual transitions are a key element of the experience. I’m also hoping these benchmarks provide a spotlight for the community that we can turn toward the runtime engineers inside Sun or Adobe or Mozilla to demand better performance.

Go to GUIMark home page

From AS3 to Objective-C: Flex vs iPhone development

Recently I’ve been given the opportunity to work full time on commercial iPhone development at EffectiveUI. The most intriguing thing about the platform for me is having access to non traditional user input mechanisms. When I was playing around with Wii remote integration on the desktop, the potential was exciting, but the ubiquity was limiting. In the same way that pc game companies develop for the keyboard and mouse first and then provide hooks for joysticks after the fact, I knew that serious Wii remote integration in a desktop app was limited. Knowing that I can write software for the iPhone that always has access to multitouch and accelerometer data from the outset really allows for unique gestures as a first class citizen within an app.


After working with some code and spending time with the SDK itself, I couldn’t help but naturally compare UI development on the iPhone with GUI frameworks like Flex or Swing, heres the things that stand out so far.

  1. I’m really spoiled by higher level languages. A good high level language like ECMAScript, Ruby, or Java rides the fine line of “Making things as simple as possible, but no simpler”. I’ve never felt constrained by the language features in these technologies, only by the apis exposed. Stepping *back* into Objective-C certainly provides more power and flexibility in the language, but there’s a loss in productivity for me that I just can’t shake. Some of this loss comes from Objective-C’s design itself, and some of it just comes from XCodes introspection ability. For instance, I’m not sure if I’ll ever get to the point where I can read these lines of Objective-C as effeciently as their ActionScript counterparts would probably look.
    NSString *aString = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
    
    UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];

  2. Closed source UI frameworks suck. Most of what I learned about custom UI development in Flex I learned by inspecting the source code for the bundled controls. Ripping open Containers to see how layout rules are determined, or Lists to see how delegates are passed around, or the Image control to see how different display types are handled provides invaluable gems about implementing Flash apis. It has also helped me optimize the interactions of an app knowing the intentions of the developer who created the UI controls. With the iPhone SDK, you’re given documentation for the visual components, but no source to help determine how they work.

  3. Core graphics and animation is really strong. Between Quartz and the OpenGL layer there’s alot of potential for getting easy access to some of the more complex visual hacks. Although I think 3D user interfaces are prone to usability issues, the iPhone is a much better device to explore them on then a standard keyboard and mouse interface.
  4. Data binding, event listeners, and mxml. The Flash Player and Flex model provide features on top of the ActionScript language that arguably optimize UI needs and keep development more declarative. Cocoa development could really benefit from a ‘gui compiler’ that takes Objective-C to a higher level and bakes in features that support common ui design patterns.
  5. Garbage Collection. Objective-C 2.0 provides a unique system that lets you create objects that will be automatically garbage collected, or you can continue to manually manage object allocation/deallocation yourself. The concept sounds cool, but I can imagine allowing both systems to be mixed within the same project is just begging for trouble.

So far I think that Objective-C has alot of power and some really awesome features that outclass GUI features in Flash, but compared to Flex development as a whole, I’d have to say that XCode and the included visual frameworks are not as sophisticated.

Updated ‘Elastic Racetrack’ for Flash 9 and AVM2

In 2005 Ted Patrick posted a great article on the frame execution model inside the Flash Player that he dubbed the ‘elastic racetrack‘. It’s served as a great reference for me over the years to help understand how code execution and rendering were balanced within the processing of a frame. Since the introduction of Flash Player 9 and the new AVM2, I’ve noticed a few changes to the elastic racetrack model and thought I’d share them. This information is based on research into Flash player internals as well as observations I’ve made playing around with the event and rendering model, but the full model hasn’t been confirmed by Adobe engineers.


The basic premise of the original elastic racetrack is still the same. Given a specific frame rate to operate on, the Flash player will devote the first segment of the frame to execute code, and the second segment to render display objects. Either segment can grow its part of the racetrack to accommodate more processing and effectively extend the duration of the frame.

Flash Player Elastic Racetrack

What changes from the previous model is how those segments look under a microscope and how they come together to form a ‘frame’.

AVM2 is controlled by what I’m going to call the Marshal. The Marshal is responsible for carving out time slices for the Flash Player to operate on. Its important to clarify up front that these time slices are not the same thing as the framerate compiled into a swf, but we’ll see below how the player ultimately synthesizes a framerate from these slices. Running a Flex compiled swf within Firefox under Mac OS X, the Marshal appears to be carving out 19-20 millisecond slices, but this can be different between platforms and browsers based on what I’ve observed as well as Adobe employees have hinted at. This can also change depending on how the swf was compiled, see some of the comments below. For the sake of the article lets assume we’re only talking about a 20 millisecond slice to make the math easy. This means the Marshal will attempt to generate and execute no more then 50 slices each second, and it may be less depending on the elasticity of code execution or rendering. Inside each slice, 5 possible steps are processed in the following order.

  1. Player events are dispatched - This includes events dispatched by the Timer, Mouse, ENTER_FRAMEs, URLLoader, etc…

  2. User code is executed - Any code listening to events dispatched by step 1 are executed at this stage.
  3. RENDER event is dispatched - This special event is dispatched when the user calls stage.invalidate() during normal user code operation.
  4. Final user code is executed - User code listening specifically for step 3 is executed at this point.
  5. Player renders changes to the display list.
p style="text-align: center;">AVM2 Marshalled Slice


The Marshal executes this 20 millisecond slice over and over and decides on the fly which actions to run. The exact actions processed within a slice will ultimately derive the 2 main racetrack segments (code execution and rendering) that constitute a ‘frame’. User actions and Invalidation actions fill up the code segment track, while Render actions fill up the render segment track. Its important to note that actions will only occur at times predetermined by the Marshal, so a if you have a short running User action, the Marshal will still wait a few milliseconds before moving on to the Invalidate and Render actions.


The best way to illustrate which actions are run and how the elastic racetrack is created, is to look at how those slices are processed on a swf running at 5 fps, 25, fps, and 50 fps.



Flash Frame Marshaling Diagram


As you can see, the elastic racetrack performs different actions per frame and requires a different visual illustration depending on the framerate that the player is trying to synthesize. So for a swf running at 5 fps, each frame processed 10 User actions, 1 Invalidation action, and 1 Render action. At 25 fps, each frame processed 2 User actions, 1 Invalidation action, and 1 Render action. At 50 fps, each frame processed 1 User action, 1 Invalidation action, and 1 Render action. Whats important to note in the above chart is that some events are only available in certain slices. For instance, the Event.ENTER_FRAME event will only ever be dispatched in a slice that occurs at the start of a frame.


So what does this all mean? Theres a couple quick ideas to take away from this.



  1. Long running code execution or render segments can extend a given slice beyond 20 milliseconds. Elasticity will be applied to that particular slice and the duration of the frame may or may not be extended as a result. The Marshal may drop the number of slices that constitute a frame in order to keep the active framerate close to the compiled framerate.

  2. A swfs real framerate won’t exceed the Marshals rate defined for the player instance. You can set your compiled framerate at 120fps, but Flash will still only process 50 slices max that generate 50 render calls (more or less depending on the system config).

  3. Code can be executed more often then the compiled framerate. A swf compiled at 1 fps can execute a Timer or Mouse event in every slice, even though it will only render in the last slice. Additionally, if you choose, you can render to the screen sooner then the compiled framerate by calling updateAfterEvent() , but only within a Mouse, Timer, or Keyboard event handler. In this instance though, the Marshal will consider that the end of the frame and start a new frame on the next slice. Lastly, Flash will force an automatic render when mousing over any Sprite that has had its visual properties (x,y,width,height,etc..) changed, naturally this still occurs at the end of the slice and any prerender logic will still run.

  4. Compiling a framerate that isn’t a multiple of the total number of slices per second for your platform will cause irregular rendering as it tries to divide up the slices. If you were to compile in a framerate of 20 on a platform executing 50 slices per second, then the player has to render 2 frames every 5 slices and would follow a 3-2-3-2-3-2 slice-to-render rate.



These 4 facts are moving targets though, since for this article we’re working on a 20 millisecond slice that’s processed 50 times per second. In reality you’ll see time slices as low as 5 milliseconds or as high at 100 milliseconds and some of the math will change as a result.


If you’d like to test this model for yourself, the easiest route is to create a swf running at 1 fps and another at 100 fps both with a Timer object set on a 1 millisecond interval. Inside the Timer event handler change the x property of a display object and hook a bunch of getTimer() traces up to different player events like Mouse, EnterFrame, and Render and watch the carnage unfold in your console. The rest of the information you can’t derive from the results comes from alot of context about the player I’ve learned over the past 2 years and so isn’t as easily visible. If anyone has any information to help add to or correct the above model, please submit it in the comments.


Thanks to several readers who have clarified some of the differences between Flex and Flash as well as how the Flash API is able to change the default behaviors described above.














Why Bubblemark is a poor ui benchmark




A few months ago someone on the Adobe boards asked why the Flex testcase in Bubblemark seemed to act so different in AIR versus in the browser. Yesterday, I saw the same question come up again and I figured I’d finally weigh in on the topic. The simple answer is that the test was created improperly, the complex answer has to do with the inherent limitations of the test itself.



First off, for those who don’t know what the Bubblemark test is, its a simple animation test case implemented in different GUI frameworks, its kinda like an Acid2 test for rendering speed. The charts should ideally give you a base number to understand how well one technology compares against another for rendering. As a GUI developer I’ve been a bit underwhelmed with the whole thing and heres why:



  1. The author doesn’t understand Flash’s rendering engine. The easiest way to illustrate how incorrectly the Flash test was designed, is to download the source and change the compiled framerate to 1 fps. Re-compile and run the test and you’ll notice the benchmark framerate running at ~50 fps. You can clearly see the balls only moving once per second, yet the test thinks its flying along. This is because the testcase makes the incorrect assumptions that changing the properties of a DisplayObject causes it to render right away. The reality is, Flash holds on to all display updates till the next render pass and applies all the latest changes at once. Changing the position of an object every 5 milliseconds is meaningless when Flash is bound by a 33 millisecond render pass (or whatever you’re framerate divided by 1000 happens to be). A correct test case would rely on an ENTER_FRAME handler to change x and y values and get rid of any Timer calls.

  2. Framerate tests above 60 fps are meaningless. Seriously, any GUI benchmark designed to test above 60 fps is bogus. In fact, a pretty simple optimization technique for Adobe or Sun would be to cap the paint requests that get forwarded to OS X or Windows, simply because the majority of computer users these days are on LCD panels which natively run at 60 fps. Some operating systems even go a step further and limit the effective framerate of paint requests it sends to the videocard (see Beam Sync on Mac). So when you see the Java test case fly up to 120 fps on Bubblemark, you can realistically only see 60 of those frames, and there might be a chance the other 60 are never even calculated by Javas layout engine.

  3. The test just moves balls around! This is my biggest beef with the benchmark because it only tests one simple aspect of the rendering engine in these technologies, which is bitmap translation. How do bitmaps moving around the screen tell you anything about the capabilities of the respective technologies? Do the JavaFX guys really think optimizing this usecase will make their technology relevant? The only thing Bubblemark will tell you is which runtimes might best handle bitmap particle emitters….thats about it. Theres a lot more that goes into both the layout engine and the rendering pipeline of these different technologies and its a shame that only the most basic aspect is being tested. The funny thing is, if you open up your task manager while running the tests, you’ll notice that several of them don’t even try to run at full speed, my CPU is sitting as low as 20% in some cases. This means the runtimes don’t even consider the test difficult enough to give it full attention and have opted for using less power over faster motion.



I don’t mean to cut down the developers responsible for Bubblemark because at least they came up with a simple way to help us all compare these different technologies, I just think its a bit misguided to put any meaning behind these numbers. When evaluating your options for a GUI framework in our flashy web 2.0 world, you need to consider how well a technology can handle object scaling, alpha transparencies, rotations, text reflow, along with basic x and y translation and dynamic redraws. Even more realistically, developers need to be aware of the limits in the 25-45 framerate region since this is where you can efficiently balance render complexity with smooth animation. I’ve uploaded a couple quick test cases in Flash, HTML, and Silverlight that I think provide a good foundation for stressing a rendering engine and hopefully I’ll get a chance to expand them more into a full test suite.














Kick starting the garbage collector in Actionscript 3 with AIR




During the final months of my work with eBay Desktop, my sights were set squarely on optimization, both memory and cpu. When it came time to start messing with the garbage collector, my sanity went from bad to worse. What I originally thought was going to be a straightforward way of releasing memory in AIR turned into a 2 month long testcase with some discouraging outcomes.


Memory usage in eBay Desktop was something that always lingered in the back of my mind during the entire development cycle. Because of the shifting nature of our requirements, the issue was only explored near the end, even though we knew in the beginning that memory usage had to go through valleys and peaks in a managed way while users spent time in it throughout the day. We had alerts that would open and close, we had an app that would run in the system tray, and we considered making a ‘lite’ mode that would sit on top of your desktop all day, each of which had different memory requirements. In the beginning we used a well known hack to test garbage collection until part way through the development of AIR and Flex 3 Adobe finally added support for calling the garbage collector directly. We knew at this point we had a viable route for managing memory since Adobe was now making the effort to acknowledge the need. So now all that was required was a simple call to



flash.system.System.gc()

and we were set to go….right?


Well, not exactly. First off we learned that a call to System.gc() only does a mark OR a sweep on any given object, but not both in the same call. So in order to have the effect of releasing memory back to the OS, we needed to call it twice in a row. One call to mark any dereferenced objects and sweep away old marks, and the second to now sweep away marks from the first call.


flash.system.System.gc();

flash.system.System.gc();

Now this seemed to be releasing memory back with pretty basic test cases, but it wasn’t working under production scenarios and we had to turn to Adobe engineers to help with the problem. What we learned was that you have to contend with 2 different kinds of pointers when working in AS3; pointers that exist in bytecode, and pointers that *may* exist in the Flash player itself that you’d never know about. What I started to realize was that the Flash player was never really engineered to be aggressive about memory usage. It was designed to plug memory leaks and manage memory plateaus, but not designed with an assumption that users would be interested in lowering those plateaus. It makes sense because most Flash content is viewed in the browser for a short amount of time before the plugin is destroyed and all memory is released when a user navigates away. With AIR, the rules changed since users are more conscience of discreet application memory usage and applications might not always need the same memory when launched vs after 2 hours of usage.


First up we found that the Flash player was always maintaining a reference to the last Sprite clicked, so if you destroyed an AIR window that the users had interacted with, you couldn’t get garbage collection to work until interacting with another window, which can become a big problem if you’re running in system tray mode and there are no windows to click in. Secondly we learned that you have to push any existing enterframe handler off the call stack by creating a new one. Adobe took care of the first problem, but to handle the second one we had to change our GC call a bit.


private var gcCount:int;

private function startGCCycle():void{
gcCount = 0;
addEventListener(Event.ENTER_FRAME, doGC);
}
private function doGC(evt:Event):void{
flash.system.System.gc();
if(++gcCount > 1){
removeEventListener(Event.ENTER_FRAME, doGC);
}
}

Another facet we hadn’t considered was the affects of the Flex framework on garbage collection. Flex kept some of the same design philosophy as the player itself, mainly that end users were loading applications in the browser and then navigating away when done. Garbage collection was therefore considered on a micro level involving user components, but not at the framework level which could be guaranteed to exist throughout the life of the app. Adobe made strides on patching the framework to work better in discreet Windows, but ultimately some things couldn’t be changed. What we found was that CSS could not be defined in any <mx:Window> component. It had to be defined in the root <mx:WindowedApplication> which would take care of declaring CSS globally for all windows. Also we were forced to clear some global variables ourselves, which caused our code to now look like this.



private var gcCount:int;

private function startGCCycle():void{
ContainerGlobals.focusedContainer = this;
gcCount = 0;
addEventListener(Event.ENTER_FRAME, doGC);
}
private function doGC(evt:Event):void{
flash.system.System.gc();
if(++gcCount > 1){
removeEventListener(Event.ENTER_FRAME, doGC);
}
}

Lastly, not all features in AIR could be unhooked with our enterFrame trick, after another couple days of testing we found components that needed to be unhooked with Timers like the HTML component. One last tweak to our garbage collection cycle and we were home free.


private var gcCount:int;

private function startGCCycle():void{
gcCount = 0;
addEventListener(Event.ENTER_FRAME, doGC);
}
private function doGC(evt:Event):void{
flash.system.System.gc();
if(++gcCount > 1){
removeEventListener(Event.ENTER_FRAME, doGC);
setTimeout(lastGC, 40);
}
}
private function lastGC():void{
flash.system.System.gc();
}

We were now able to successfully garbage collect any objects that have been dereferenced in Flash. We had three things we had to look out for in the app now.



  1. All display objects that added listeners on to model data had to be weakly referenced or they wouldn’t be automatically dereferenced. This is because our architecture kept model data alive while individual window stages were being destroyed. I feel like I should point out that contrary to some beliefs, it is not a good idea to apply weak references by default throughout your entire app. Trust me when I say that its alot easier to debug an application with memory leaks due to strong listeners, then it is to debug an app in which users report random failures because underneath the hood weakly referenced objects are getting accidentally destroyed when the GC kicks in. You can never avoid bugs, so you should program in a way that makes them consistent to find.


  2. All asynchronous events needed to be explicitly shut down. This included Timers, Loaders, File and DB transactions. Setting these to be weakly referenced is not enough as all asyncronous objects in AS3 register themselves to the Flash player while they are running. It is impossible to access objects that have been dereferenced in code but continue to be referenced by the player like a running timer.

  3. No anonymous closures allowed.


After all this was taken care of we began to learn that garbage collecting objects in Flash didn’t translate so easily to releasing memory back to the OS. If you ever look at the memory graph in the Flex debugger and then open up the Task Manger or Activity Monitor to compare memory usage, you’ll notice a huge disparity between the two.


Flex Builder memory profiler

FlexBuilder reports only 15mb of AS3 object data


AIR system memory profile

AIR private memory really takes up 65mb on the system


The difference you’re seeing is Object Memory vs. Rendering Memory and the bulk of all memory used by the Flash player goes toward rendering. Displaying an empty stage in Flash can take up anywhere between 10mb and 20mb depending on the width and height and then it climbs by roughly 4k for each display object attached to the stage. This can add up quickly when using the Flex framework where even a simple button uses several display objects.


What we ultimately found was that even though we could successfully release AS3 objects, we couldn’t reliably get the Flash player to release render data. So an app that started at 20mb would climb to 100mb, and when the entire stage was destroyed, we’d go back down to only 80mb. You can actually test this for yourself by downloading a sample Flex 3 project and observing the effects. What I’ve learned from Adobe is that the player ends up fragmenting memory quite a bit. It probably goes back to the heart of the initial design of the Flash player I described above. All the effort was put into making a killer GUI environment that deferred memory management to whether the browser window was open or not, and as a result the memory system was not optimized for more aggressive use cases. I can only guess the problem comes from the fact that AS3 code is attached to the timeline of the player itself, and managed by the elastic racetrack. As a result both AS3 objects and render data get mixed in to the same memory page, and releasing just the render data doesn’t matter when model data is placed on the same page.



Adobe has assured me they are working on the problem but it realistically won’t make it in until after AIR 2.0, and its unclear whether those fixes will be merged into the the plugin player given that the need isn’t very high for web pages. Until then, you can not count on creating an application in AIR that releases memory back to the OS. The best approach is to reuse the smallest amount of displayobjects possible to achieve the desired workflow. Get used to adding and removing children without destroying them but instead sliding them off into a pool for later reuse, as this helps keep the memory plateau low during use.














Vampire Weekend




Vampire Weekend performed a pretty fun show at the Bluebird last night. People are going crazy over this band and now I see why. Tickets were originally going for $12 which must have sold out immediately cause up until last week people were willing to pay $100 for a pair.


Horrible blurry photo of Vampire Weekend


I still can’t figure out how to best describe their music , but whatever it is, it makes for a great live performance. I definitely recommend going if you can manage to find tickets still.



Blake’s got a new face!














Hacking width and height properties into Flex’s CSS model




As much as I love working with the Flex layout model, in many ways it feels inferior to its HTML cousin. I’ll take Flex’s container components over HTML tables and divs any day, but I’ve always been disappointed with the fairly weak CSS model found in Flex. From an architectural level the framework decisions makes sense and keeps internal logic fast and clean, but from an implementation standpoint, it becomes an annoying roadblock. Heres a quick example of the problem.


<mx:Style>

.navItem {
vertical-align: middle;
corner-radius: 5;
border-style: solid;
border-color: #F3CB19;
background-color: #A87500;
}
</mx:Style>
<mx:HBox styleName="navItem" height="30"/>

<mx:HBox styleName="navItem" height="30"/>
<mx:HBox styleName="navItem" height="30"/>

In this case, since height is a class property, it must be defined on the HBox instance and can’t be moved into CSS. It makes the code less manageable and adds restrictions to changing themes at runtime.


In order to define class properties with CSS we need to break some of the framework rules. Since we can’t have class metadata defining a value as both a CSS and a class property, we need to leave all metadata as-is, and ‘foward’ the css definitions on to the class. In practical terms what this means is that changing the height in css will change the height on the component, but changing the height directly on the component wont update the css definition. The code below illustrates how this plays out inside a custom component.


package com.craftymind.controls

{
import mx.containers.HBox;
import mx.styles.StyleManager;

public class extHBox extends HBox
{
override public function styleChanged(styleProp:String):void{
super.styleChanged(styleProp);
if(!styleProp || styleProp == "styleName"){ //if runtime css swap or direct change of stylename
var classSelector:Object = StyleManager.getStyleDeclaration("." + styleName);
if(classSelector != null){
applyProperties(classSelector, ["width", "height", "percentWidth", "percentHeight", "x", "y", "visible"]);
}
}
}
private function applyProperties(styleObj:Object, arr:Array):void{
for each (var item:String in arr){
var prop:Object = styleObj.getStyle(item);
if(prop != null) this[item] = prop;
}
}
}
}

When the HBox detects that the styleName or runtime definition has changed, it scans the classSelector for width, height, x, y and visible properties to be applied. You can add whatever properties you want in there including text labels or image sources depending on the component being extended. I haven’t fully tested it so I’m not sure if type selectors work, and I know that calling obj.setStyle(”height”, 10); definitely wont work, but your better off calling obj.height = 10 in that case anyway.


Heres a complex menu system controlled completely with css including y positioning, height changes, and header visibility.




View Source



We now have separation of content from style thats alot closer to what HTML offers, and as a bonus, all property-based databinding continues to work on the values passed through CSS.


<cm:extHBox styleName="header">

<mx:Label text="Header Text"/>
</cm:extHBox>
<cm:extHBox id="nav" styleName="navContainer">
<cm:extHBox styleName="navItem">
<mx:Label text="Nav Item 1"/>

</cm:extHBox>
<cm:extHBox styleName="navItem">
<mx:Label text="Nav Item 2"/>
</cm:extHBox>
<cm:extHBox styleName="navItem">
<mx:Label text="Nav Item 3"/>

</cm:extHBox>
</cm:extHBox>
<mx:Button label="Switch CSS" click="switchCSS()" y="{nav.y+nav.height+2}"/>

.header {

background-color: #000000;
border-style: solid;
border-color: #FFFFFF;
border-thickness: 2;
color: #FFFFFF;
x: 0;
y: 0;
percent-width: 100;
height: 20;
visible: true;
}
.navContainer {
background-color: #000000;
border-style: solid;
border-color: #FFFFFF;
border-thickness: 2;
vertical-align: bottom;
horizontal-align: left;
padding-left: 3;
x: 0;
y: 20;
percent-width: 100;
height: 50;
}
.navItem {
vertical-align: middle;
corner-radius: 5;
border-style: solid;
border-sides: "left top right";
border-color: #FFFFFF;
border-thickness: 2;
background-color: #000000;
padding-left: 3;
padding-right: 3;
color: #FFFFFF;
height: 30;
}













Image smoothing in Flex




The Flex Image control doesn’t expose Bitmap smoothing by default but can easily be added in through subclassing the component. Smoothing is a nice feature for removing jaggies from images that have been scaled either up or down, and in practice hasn’t caused any noticable cpu hangups to do the post processing. I’m writing up a patch to submit to the Flex Open Source initiative, but in the meantime, heres a quick and dirty hack to enable it in the Flex 2 and Flex 3 SDK.



Create a new MXML component and name it SmoothImage.mxml, then add the following code.


<?xml version="1.0" encoding="utf-8"?>

<mx:Image xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import flash.display.Bitmap;
override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(content is Bitmap){
var bmp:Bitmap = Bitmap(content);
if(bmp && bmp.smoothing == false){
bmp.smoothing = true;
}
}
}
]]>
</mx:Script>

</mx:Image>

Now just use <local:SmoothImage source=”myimage.jpg”/> the same way you’d use a normal image component and you’re all set. This code will take care of smoothing both dynamically loaded images as well as embedded images in one simple script. It also handles broken images gracefully. Heres a quick sample showing the affects of scaling the Google logo with and without smoothing.






And the code used to create this…



<!-- Top Images -->

<mx:Image source="{googlelogo}" width="60" height="25"/>
<mx:Image source="{googlelogo}" width="200" height="90"/>
<mx:Image source="{googlelogo}" width="400" height="180"/>

<!-- Bottom Images -->
<local:SmoothImage source="{googlelogo}" width="60" height="25"/>
<local:SmoothImage source="{googlelogo}" width="200" height="90"/>
<local:SmoothImage source="{googlelogo}" width="400" height="180"/>














Saving class data to disk in AIR




For eBay Desktop we wrote a simple utility for reading and writing classes directly to disk. Using this method we’re able to load the users existing data from disk, or if its unavailable, create a new class with all the defaults.


First up is the utility class AIRUtils


package com.effectiveui.util

{
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;

public class AIRUtils
{
public static function readFileObject(fil:File):Object{
var amf:Object;
if(fil.exists){
var stream:FileStream = new FileStream();
stream.open(fil, FileMode.READ);
amf = stream.readObject();
stream.close();
}
return amf;
}
public static function writeFileObject(fil:File, obj:Object):Object{
var stream:FileStream = new FileStream();
stream.open(fil, FileMode.WRITE);
stream.writeObject(obj);
stream.close();
return obj;
}
}
}

These 2 static methods act as simple helper wrappers to read and write classes out to disk.


The example class we want to save below looks very similar to the type of class we use inside eBay Desktop.


package com.ebay.model

{
import com.ebay.model.SearchPreferences;

[Bindable]
[RemoteClass(alias="com.ebay.model.UserPreferencesModel")]
public class UserPreferencesModel
{
public static const STANDARD:String = "standard";
public static const SKINNY:String = "skinny";

public var logoutOnClose:Boolean = false;
public var viewState = STANDARD;
public var globalSearchFilters:SearchPreferences = new SearchPreferences();

private var _maxHistoryItems:uint = 1000;
public function set maxHistoryItems(max:uint):void{
_maxHistoryItems = max;
}
public function get maxHistoryItems():uint{
return _maxHistoryItems;
}
}
}


In order to write a class out to disk and read it back in, you have to add RemoteClass metadata to it. It doesn’t matter what the value is it just needs to be unique to the application. This provides Flash with an identifier for linking amf data to class definitions when its loaded back in. It doesn’t matter what value you put in the RemoteClass tag, but the best practice is to use the class name of the model you’re saving. Additionally, in this example we’d need to make sure both UserPreferencesModel and SearchPreferences model have RemoteClass metadata, since caching the UserPrefencesModel will automatically attempt to cache the SearchPreferences as a child model.

Only public variables will be cached to disk, so both the static values and the private var will be thrown out, but the public getter/setters will be cached.


Interacting with the cached data using AIRUtils looks like this.


private var fileRef:File = File.applicationStorageDirectory.resolvePath("UserPreferences.dat");

private var userPrefs:UserPreferencesModel;

private function loadPrefs():void{
userPrefs = AIRUtils.readFileObject(fileRef) as UserPreferencesModel || new UserPreferencesModel();
}
private function savePrefs():void{
AIRUtils.writeFileObject(fileRef, userPrefs);
}

When loadPrefs() is called, the cached class is read in and cast as a UserPreferencesModel. If no file exists in the users cache, we end up creating a new class and the defaults defined in the class will be used. This ensures we have something to work with, all within 1 tidy line of code. To save out the file we just pass the file reference and the class instance to AIRUtils.writeFileObject() and we’re done.