self halt

May 26, 2009

Getting started with Glare-DataServices

Filed under: Smalltalk, flex — Ernest Micklei @ 7:30 pm
Tags: , , , , ,

Glare-DataServices is a framework for building Flex Remoting services in VisualWorks Smalltalk. In this post, I will guide you through the steps for creating a small application that demonstrates the use of the framework.

Install the bundle

First, you have to connect to the Cincom Public Store Repository. Then open the list of Published Items and load the bundle GlareDataServices. It includes the Glare bundle and Glare-DataServices packages. The required dependencies AT MetaNumerics and Opentalk are automatically loaded if not present.

Start the server

Class GlareServer has a singleton instance that will dispatch messages sent from a Flex application to Smalltalk services. To start the server, evaluate:

GlareServer current start

Now, you can visit http://localhost:8888 to see the current class registrations. You can change the portNumber on which the server is listening. For more settings and run actions, see the GlareServer class methods.

Create Smalltalk class: MethodFinderService

In this example, we are going to create a small AIR application called MethodFinder. Its GUI will have a search box and a list of method names that match the search criteria. The search itself will be performed by a Smalltalk service called MethodFinderService.

These are the steps for creating the service:

  1. New Package: MethodFinder
  2. New Class: MethodFinderService with superclass Glare.RemoteObject
  3. Add instance method category operations
  4. Define the method getSelectorsMatching
getSelectorsMatching

  ^(self function: #getSelectorsMatching)
    argument: #pattern type: String
    ; returns: SortedCollection
    ; body:[ :pattern |
		| sortedMatches |
		sortedMatches := SortedCollection new.
		"to keep things simple, we enumerate all symbols"
		Symbol allSymbolsDo:[ :e | (pattern match: e) ifTrue:[sortedMatches add: e]].
		sortedMatches]

Registration of this service to the GlareServer is required and done by evaluating:

MethodFinderService install

Create Flex application: MethodFinder

Now that the Smalltalk service is up and running, it is time to build the client application. Using the Adobe Flex/Flash Builder, create a new Flex AIR project called GlareMethodFinder. Open the GlareMethodFinder application component and paint a List (id=methods), a TextInput (id=pattern) and some Labels. On every change of the pattern, a new search will be requested.

Glare Method Finder

Glare Method Finder

Your MXML file may look like this.

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="344" height="508">
	<mx:TextInput id="pattern" x="63" y="40" width="246" change="doSearch()"/>
	<mx:List id="methods" x="10" y="70" width="299" height="403"></mx:List>
	<mx:Label x="10" y="10" text="Glare Method Finder" fontSize="18"/>
</mx:WindowedApplication>

Configure Flex Remoting

The Flex compiler of the application needs to known about which AMF channels and destinations are going to be used. For this, two configuration files must be added. In the folder src of the project, add the file services-config.xml with:

<?xml version="1.0" encoding="UTF-8"?>
<services-config>
    <services>
        <service-include file-path="remoting-config.xml" />
    </services>
    <channels>
        <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint uri="http://localhost:8888/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>
    </channels>
</services-config>

In the same folder (src) add the file remoting-config.xml with:

<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service"
    class="flex.messaging.services.RemotingService"
    messageTypes="flex.messaging.messages.RemotingMessage">
    <default-channels>
        <channel ref="my-amf"/>
    </default-channels>
    <destination id="MethodFinderService" />
</service>

Now that we have the configuration files in place, we need to add a Flex compiler option. Open the Project properties and select “Flex Compiler” in the list. Change the options to the following line. (Windows developers need to change the path separator)

-locale en_US  -services ${DOCUMENTS}/GlareMethodFinder/src/services-config.xml

From Button click to Service call

Add the following script (using mx:Script) that implements the doSearch function. It creates a RemoteObject that will bind to the Smalltalk MethodFinderService. Using this remoteObject, you can send it the message getSelectorsMatching with the pattern argument.

private function doSearch():void {
	if (pattern.text.length == 0) return
	var service:RemoteObject = new RemoteObject("MethodFinderService")
	service.addEventListener(ResultEvent.RESULT, handleSearchResult)
	service.getSelectorsMatching(pattern.text + '*')
}
private function handleSearchResult(event:ResultEvent):void {
	methods.dataProvider = event.result as Array
}

Now the application is ready to find some methods. Run the application and start entering a pattern.

For this application to be really useful, we can add two buttons “Browse Implementors” and “Browse Senders”. We want these to open Smalltalk browsers in our running image. For this to work we can add two more operations to the MethodFinderService like browseImplementorsOf and browseSendersOf.

As can be expected, this exercise is left to reader.

Flex source code of this example can be found on glare.googlecode.com. The Smalltalk source code is available in the Cincom Public Store Repository in the package Glare-Examples-MethodFinder.

April 5, 2009

Executable operation specifcations in Glare-DataServices

Filed under: Smalltalk, flex — Ernest Micklei @ 9:51 pm
Tags: , , , , ,

Glare is a Flex Remoting and Messaging server written in VisualWorks Smalltalk by Philipp Bunge. I am extending his work with Glare-DataServices which basically provides a HttpServlet that dispatches operation invocations send from a AMF client (Flex,AIR) to Smalltalk objects.

To work with Glare-DataServices, you need Smalltalk classes that implement operations and ActionScript classes that have corresponding methods in which these operations are invoked remotely. Because both classes (client and server-side) must have the same signature, it is clear that code generation can be very helpful.

One of the requirements, also applied to the Pocogese framework (Flex on Rails), is that methods of each Service class must have metadata such as function name and argument types. Using the metadata of each operation, a code generation tool is able to generate ActionScript classes with the correct signature.

For Glare-DataServices, I am exploring a different approach that combines both the specification and implementation of each operation using a Block. Let me illustrate using a simple example:


SampleService>>computeSum
  " Answer a RemoteMethod that both specifies and implements the sum computation"

  ^( self function: 'computeSum' )
         comment: 'Returns the sum of two numbers'
       ; argument: 'left' type: Number
       ; argument: 'right' type: Number
       ; returns: Number
       ; body: [ :left :right |  left + right ]

You will notice that sending the message “computeSum” to an instance of this service will not perform the operation but instead returns a RemoteMethod with a body.

Having the operation metadata, a RemoteMethod can easily be translated to the ActionScript function implementation:

public function computeSum ( left : Number, right : Number , resultHandler : Function ) : void {
    var ro:RemoteObject = new RemoteObject ( "SampleService" )
    ro.computeSum.addEventHandler(ResultEvent.RESULT,resultHandler)
    ro.computeSum(left,right)
}

When Glare-DataServices receives a request from Flash (running ActionScript), it will lookup the RemoteMethod using the name of the function and evaluate the body of that method like this:

serviceOperation: functionName withArguments: aCollection
    " Find the registered RemoteMethod and evaluates its body using the arguments."

    ^ (self lookUp: functionName) body valueWithArguments: aCollection asArray

March 15, 2009

Flex Remoting ignores class mapping

Filed under: flex — Ernest Micklei @ 9:33 am
Tags: , , ,

if your application does not yet actually use that client Class.  In my application, the result of a remote invocation kept returning a dynamic Object instead of the intended ValueObject class “Slot” although I specified the mapping and the RemoteClass metadata:
weborb-config.xml

   <classMapping>
     <clientClass>com.cae.planning.models.Slot</clientClass>
     <serverClass>Slot</serverClass>
     <source>Slot</source>
   </classMapping>

Slot.as

    [Bindable]
    [RemoteClass(alias="com.cae.planning.models.Slot")]
    public class Slot { ... }

So merely including the “import com.cae.planning.models.Slot;” in my application does not instruct the compiler to actually include that Class and therefore knows about the class mapping. Obviously, this can only happen if you work on new client classes that you are not yet using anywhere in your application.

March 14, 2009

Tiny, single-purpose class: ResultToFunctionAdaptor

Filed under: design, flex — Ernest Micklei @ 8:06 pm
Tags: ,

Every now and then I need a small piece of functionality that perfectly fits into a single, minimal-behavior thus single-purpose class. This time I am developping a Adobe Flex application that uses the RemoteObject facilities. Before invoking a method on a RemoteObject, you have to add two event handlers that will be called with a ResultEvent or a FaultEvent respectively. Typically in the “onResult(event:ResultEvent)” function, one takes the result of the event and calls another function or update a view.

In my application, this pattern had been applied at numerous locations until I decided to introduce a simple but effective helper class.  A ResultToFunctionAdaptor is a helper class that has an event handler for a ResultEvent and calls another handler with the result of that event.

public class ResultToFunctionAdaptor
{
	private var _handler:Function;

	public function ResultToFunctionAdaptor(handler:Function) {
			this._handler = handler
	}
	public function onResult(event:ResultEvent):void {
			_handler.call(this,event.result);
	}
}

Using a ResultToFunctionAdaptor I can now encapsulate the event handling and work with Functions only. For example, my (Time)SlotService can be used like this:

...
new SlotService().getAllSlots(fromDate,toDate,showSlots);
...
public function showSlots(slots:Array):void {
    ...
}

and the implementation of SlotService>>getAllSlots(start:Date,stop:Date,callback:Function) contains:

aRemoteObject.getAllSlots.addEventListener("result", new ResultToFunctionAdaptor(callback).onResult);

This class has been added to the Dunelox library which is a collection of ActionScript classes that provides a micro application framework for Adobe Flex applications.

April 23, 2008

Sorting XMLListCollection by attribute

Filed under: flex — Ernest Micklei @ 8:14 pm
Tags: ,

Just want to share the result of a small puzzle I had about sorting elements of an XMLListCollection by one of the attributes of such an element. At first, I tried sorting the elements of the XMLList I had, but the API does not provide any methods to do that. Bruce Phillips wrote a snippet that pointed me to right direction. So, here it is:

var doc:XML = <root>
<item name="C"/>
<item name="B"/>
<item name="A"/>
</root>
var collection:XMLListCollection = doc.item
var sort:Sort = new Sort()
sort.fields = [ new SortField("@name", true) ]
collection.sort = sort
collection.refresh()

As expected, the collection will show:

<item name="A"/>
<item name="B"/>
<item name="C"/>

The XMLHelper class in the Dunelox library has been extended with a sort function to encapsulate this.

September 6, 2007

Flex Project version and buildnumber

Filed under: flex, ruby — Ernest Micklei @ 3:32 pm
Tags: , ,

I wanted to associate version and build information with every compilation of a Flex project. Such information is useful when deploying to different staging environments (e.g. are you sure you uploaded the correct SWF ?) and helps tracking feedback (e.g. bugs) from users using a particular build.

First, I added a simple resource version.xml to store version and build info:

<?xml version='1.0' encoding='UTF-8'?>
<version name='0.1' build='124'/>

Then I defined a component Version.mxml to show that information in plain text:

<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" horizontalGap="0">
<mx:XML id="version" source="/version.xml" />
<mx:Label text="Version:"/>
<mx:Label text="{version.@name}"/>
<mx:Label text="Build:"/>
<mx:Label text="{version.@build}"/>
</mx:HBox>

So far nothing to get exited about. What is left to do is get this information updated automatically for every Flex compilation (no I am not using Ant or Maven for Flex at this time).

I am using Eclipse for all my Java, Ruby and Flex projects. Eclipse uses Builders to fire all kinds of project tasks. So I added a custom builder (see Project Properties) that runs a simple Ruby script (as an External Program) that reads, changes and writes the version.xml resource. Make sure this builder is the first one to run.

#!/usr/bin/ruby

# This script updates the version.xml file by incrementing the build number

require 'rexml/document'
file = File.new("version.xml")
root = REXML::Document.new(file).root
root.attributes['build'] = root.attributes['build'].to_i + 1
File.open("version.xml",'w') do |f| f << root.parent end

August 2, 2007

Deploying Flex using Capistrano

Filed under: capistrano, flex, rails — Ernest Micklei @ 8:21 pm
Tags: , ,

Capistrano is a deployment tool initially created to support the remote installation of Rails applications. One of the assumptions Capistrano makes is that the application (source) can be pulled out of a source code management system such as Subversion.

In case of Adobe Flex applications, compiled sources (SWF,HTML,…) need to be deployed to the Web server. So instead of pulling sources from a repository, I needed to push compiled code to the server.

The script below overrides the update_code task of the standard recipe and defines the steps to secure copy the compiled sources to the release location. To make this also work on the Windows platform, you need to install pscp

Now, just as any other Rails application, you can say:

cap deploy

and the application will be deployed to a new release location on the Web server.

Capistrano Flex

Get the source of this Capfile from my public S3 bucket.

Note: the version shown here will not work for deploying on multiple web servers. This is on my big TODO list…

July 17, 2007

Flex Bindable Hash

Filed under: flex — Ernest Micklei @ 9:58 am
Tags: , ,

For the Dunelox library, I needed a simplified Flex version of the Spring ApplicationContext which is a generic Hash object containing model objects accessed by a key (String). Visual components that are wired to these models objects need to be updated automatically using the standard event mechanism in Flex.

So, I had a look at the standard ArrayCollection to find out how it notifies components that are wired to elements by index. This gave me the idea to implement the HashCollection as a extension to this class.

If you need to wire a value by key in a component such as:

<mx:TextInput text=”{hash.get(’somekey’)}” />

And you declare the variable hash as a HashCollection like this:

[Bindable]
public var hash:HashCollection = new HashCollection()

Then your component is updated if you change the value associated to that key:

hash.put(’somekey’, ‘changed the value of somekey’ )

——–
Update: have a look at the source code

Blog at WordPress.com.