The Space For App Developers

Beyond Plain Old HTML Objects

Archive for February, 2010

Interview with me on TestAndTry.com

without comments

An interview with me was published on Marcin Zręda’s TestAndTry.com blog. Anyone interested in my predictions for the RIA scene in 2010 should have a look here ;)

Written by Piotr Walczyszyn

February 10th, 2010 at 8:40 pm

Posted in News

Adobe AIR 2.0 Beta 2 released!

with 6 comments

Adobe AIR 2.0 Beta 2 was just released; it is available here on Adobe Labs!

New features:

  • Enhanced Printer Interaction: New printing support allows finer control of the way content is printed from an AIR application, including the choice of printer, paper size, and number of copies. New APIs allow a developer to retrieve additional printing information, such as printable area, whether the printer will print in color, and whether the print job is currently active. It is also possible to print without displaying the print dialog.
  • Support for TLS/SSL socket communication: You can now connect to a server that requires TLSv1 or SSLv3 for socket communications.
  • IME API and IME Text Input Enhancement: There are several new features added in this release to support better text input handling with IME software. The new API enhancements are designed for use with the new Flash Text Engine (FTE).

You can find updated sample applications here.

IMPORTANT: Applications built against Adobe AIR 2 Beta 1 will not run using the AIR 2 beta 2 runtime. In order for an AIR 2 Beta 1 application to run on the AIR 2 Beta 2 runtime, the namespace of the Beta 1 application descriptor file must first be updated to “2.0beta2″ and the application must be recompiled using the AIR 2 Beta 2 SDK.

Written by Piotr Walczyszyn

February 2nd, 2010 at 6:31 pm

Posted in News,Releases

Tagged with

Java-AS3 serialization with AMF

with 9 comments

A few weeks ago I published Flerry project a Flex-Java bridge for AIR 2.0. In this post I wanted to explain how it works and what I used on the Java side to do AS3/Java AMF de/serialization. First of all Flerry uses the new NativeProcess API that comes with AIR 2.0. This new API allows communication between AIR application and any native application running on a user’s machine with standard input, output or error streams. Almost any type of data can be transferred over those streams, ranging from simple strings, numbers, Booleans, bytes and byte arrays to AMF serialized AS3 objects. Of course if AMF serialized AS3 objects are streamed then receiving side of the communication needs to understand this format. In the case of Flerry, the receiving side is Java and obviously it doesn’t have a built-in AMF deserializer. In order to enable AMF on the Java side I decided to investigate Adobe’s Open Source BlazeDS project (BlazeDS is the server-based Java remoting and web messaging technology that enables developers to easily connect to back-end distributed data and push data in real-time to Adobe® Flex® and Adobe AIR™ applications for more responsive rich Internet application (RIA) experiences). As BlazeDS is designed to work by default inside of JEE containers it must have had it already implemented.

After a short investigation it turned out that I was right and BlazeDS comes with very simple to use AMF de/serializer. What you actually need to make it work are two jar files: flex-messaging-common.jar and flex-messaging-core.jar, which are in the BlazeDS package available for download from here. In those jars I found two classes Amf3Input and Am3Output that allowed me to send and receive AMF serialized AS3/Java objects over input/output/error streams.

So how does it all work?

On the AS3 side I used the NativeProcess.standardInput.writeObject(message) function where the message object is of the type flex.messaging.messages.RemotingMessage that maps to equivalent flex.messaging.messages.RemotingMessage on the Java side with the proper RemoteClass metadata. Of course any POAO (Plain Old ActionScript Object) could be used instead of RemotingMessage. In my case I just wanted to reuse standard classes out of the Flex SDK that wrap transferred content and add properties required for asynchronous communication.

Below is actual code from Flerry that writes AMF serialized AS3 objects to the standard input stream (source code of NativeObject.as class is available here):

protected function call(method:NativeMethod, ... args):AsyncToken
{
	if (!nativeProcess)
		initialize();
 
	var message:RemotingMessage = new RemotingMessage();
	message.operation = method.name;
	message.source = source;
	message.headers = {SINGLETON_HEADER:singleton};
 
	if (args.length == 1)
		message.body = args[0];
 
	nativeProcess.standardInput.writeObject(message);
 
	var token:AsyncToken = new AsyncToken(message);
	tokens[message.messageId] = token;
 
	return token;
}

On the Java side I used the Amf3Input class to deserialize received data from the input stream (System.in) into proper Java objects (source code of NativeObject.java class is available here):

public void init()
{
	Amf3Input amf3Input = new Amf3Input(SerializationContext.getSerializationContext());
	amf3Input.setInputStream(System.in);
	try
	{
		Object object;
		while ((object = amf3Input.readObject()) != null)
		{
			if (object instanceof RemotingMessage)
			{
				RemotingMessage message = (RemotingMessage) object;
				try
				{
					if (message.getSource() != null)
					{
						Object sourceObject = null;
						if (singleton)
							sourceObject = singletonObject;
						if (sourceObject == null)
						{
							sourceObject = sourceClass.newInstance();
							if (singleton)
								singletonObject = sourceObject;
						}
 
						Object[] params = (Object[]) message.getBody();
						Class[] paramsTypes = new Class[params.length];
						for (int i = 0; i < paramsTypes.length; i++)
						{
							paramsTypes[i] = params[i].getClass();
						}
 
						Object result = sourceObject.getClass().getMethod(message.getOperation(), paramsTypes).invoke(sourceObject, params);
						respond(result, message.getMessageId());
					}
					else
					{
						Boolean stopProcess = (Boolean) message.getHeader(NativeObject.STOP_PROCESS_HEADER);
						if (stopProcess != null && stopProcess)
						{
							break;
						}
					}
				}
				catch(Exception e)
				{
					handleException(e, message.getMessageId());
				}
			}
			else
			{
				handleException(new Exception(
						"Received object is not RemotingMessage type!"), null);
			}
		}
	}
	catch (Exception e)
	{
		handleException(e, null);
	}
	finally
	{
		try
		{
			amf3Input.close();
		}
		catch (IOException e)
		{
			handleException(e, null);
		}
	}
}

To send data back to AIR I used the Amf3Output class. With a little help from ByteArrayOutputStream Java objects are serialized to AMF format and written back to System.out.

protected void respond(Object object, String correlationId)
{
	try
	{
		Amf3Output amf3Output = new Amf3Output(SerializationContext.getSerializationContext());
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		amf3Output.setOutputStream(baos);
 
		AcknowledgeMessage message = new AcknowledgeMessage();
		message.setBody(object);
 
		message.setCorrelationId(correlationId);
		amf3Output.writeObject(message);
		System.out.write(baos.toByteArray());
 
		amf3Output.close();
	}
	catch (Exception e)
	{
		handleException(e, correlationId);
	}
}

Written by Piotr Walczyszyn

February 1st, 2010 at 5:11 pm

Posted in Examples

Tagged with , ,