Adobe: Official Maven support is coming

11 10 2011

I recently spent a lot of time at AdobeMAX hassling the Flashbuilder team on what the deal is with Flex and Maven, and we’ve finally been given the word: support is coming – we just don’t yet know what form it’s going to take.

Step One: Hosting the framework artifacts

The first step towards Maven support is for Adobe to start hosting their releases in a Maven-friendly way. They have admitted that this is on the cards for them, but steered away from specifics. They have two real options here – either they submit their artifacts to Maven Central or they set up and deploy to their own public Nexus. Many of us in the community would like to see the former before the latter. Having AS3/Flex/AIR projects build out of the box without requiring any external repository would be a great start (Maven Central is referenced in every execution via the super POM). Currently while the Flexmojos plugin now lives in Maven Central, we’re still reliant on the community (specifically @velobr) to deploy the latest JARs, SWCs and RSLs to Sonatype.

Nevertheless, if Adobe were to host a Flash artifact repository, it could become the central repository for the community to deploy their own open source libraries. This could include tools such as unit testing libraries (FlexUnit, ASUnit), mocking tools (Mockolate, Fluint), micro-architectures (Robotlegs, Parsley), utilities (as3corelib, AS3Signals, RxAS), etc. This would then be the go-to for all Flash developers new to Maven. And, we could finally answer the question plaguing all Maven/Flash newbies: Where are my dependencies???

Step Two: Either sponsor, fork or replace Flexmojos

The next step is for Adobe to decide what to do with Flexmojos – the open source Maven plugin that compiles Flash artifacts. Because it’s open source, they don’t want to usurp the hard work of the community and completely take it over as-is. As I see it, they can either fork it in its current state, sponsor it with funding and their own development team, or start again from the ground up and target Spark and above. In its current state, Flexmojos 4 (4.0-RC2 is the latest) is well equipped to deal with the needs of Flash projects up to and including Flash Player 10.3 (albeit with some bugs). Going forward however, we have no assurance that Flex 4.6 or AIR 3 will be supported out of the box, and I have doubts that the community alone will keep the pace.

Moreover, many of us Flash/Maven advocates are in enterprise development and find it hard enough to convince our customers to rely on an open source initiative that isn’t maintained by Adobe, let alone officially supported or sponsored. If Adobe get behind a Maven plug-in and put their stamp on it, we’ll have a much easier time advocating it to our clients.

Step Three: Integrate with Flashbuilder

Last but not least, is Flashbuilder (FB) integration. The current situation is fairly dismal. Flexmojos 3.9 was the last to officially support the flexbuilder/flashbuilder goal – the process which generated the project structure in Eclipse from your POM (creating and configuring .project and .actionScriptProperties among others). It’s been removed from Flexmojos 4 and there is currently no robust way to keep FB abreast of the latest changes in your POM. You can run the old 3.9 goal for partial results in FB 4.5, but it’s more hassle than it’s worth. Keeping large teams in sync across a complex project is cumbersome at best (and don’t get me started on checking in .project files).

While m2eclipse – the Maven-Eclipse plugin – provides the functionality required to run Maven within Flashbuilder, it is not integrated with the Flexmojos plugin. Put simply, m2eclipse is a lot less powerful with Flashbuilder than it is with typical Java projects in Eclipse. Updated your POM with a different Flex SDK, added some dependencies or a new runtime module? Fine, just make sure to tell all the developers to update their workspaces manually – otherwise either switch to IntelliJ or wait for Flashbuilder 5 (we hope).

Looking forward

The first step in a long process has begun. Adobe are taking the plunge into Maven compatibility and it seems the Flashbuilder team are our best hope for the future of the union. We know support is coming, but how exactly it will pan out is still up for debate. Hopefully we’ll have an answer before the end of the year, but I won’t be holding my breath.

The latest

Want to keep abreast of the latest developments, here’s a list of people to follow:





Adobe Community Professional in 2011

28 01 2011

I’ve just been accepted into the Adobe Community Professional program for 2011. Having just moved to the US, this is going to take some work – but I’m certainly looking forward to it.

Thanks Adobe.





Silverlight, HTML5 and the state of RIAs

4 11 2010

So you’ve obviously heard about these statements regarding Silverlight – insinuating that Microsoft is going to abandon it in favour of HTML5 due to revelations at PDC2010. If you haven’t, here are the main links in this debacle:

One issue I have with this hype about MS abandoning Silverlight is that most of it is based on the following statement from MS, in an interview by ZDNet (see first link):

Silverlight will continue to be a cross-platform solution, working on a variety of operating system/browser platforms, going forward, he said. “But HTML is the only true cross platform solution for everything, including (Apple’s) iOS platform,” Muglia said.

Inferring from this that MS is pulling the plug on SL is pure hype. I daresay MS haven’t helped their cause by being more tight-lipped that usual over the issue, but PR has never been their strong suit.

Unfortunately, it tends to be people like MG (the TechCrunch article author) who jump on the sensationalist bandwagon. It may turn out that MS will eventually abandon Silverlight, but I seriously have my doubts. I honestly believe that they logically see their original goal of true “reach” severely hampered; what with iOS and Android now thrown into the mix since conception. Adobe haven’t done much differently – except that when they announce their HTML5 strategy (as they did last week at MAX), it’s to thunderous applause; they’re obviously much better at crowd-control.

Both of the big boys seem to understand that they cannot expect their platforms to be a presence on every single device, and they need a complementary strategy to remain viable to us developers – enter “HTML5”.

I can understand the apprehension amongst the RIA community – the religious connotations that permeate most of the Flex/Silverlight debate (RIA evangelists anyone?), would make one think we’re arguing about our very souls, rather than simply a career choice. Even if both Flash and Silverlight died tomorrow, we’d be in a pretty comfortable position to shift allegiances to any other rich client technology out there.

Let’s face it – RIAs are not going anywhere. The users have spoken.

 





AIR multiple file uploads: drag n drop to client zip to server upload and unzip

25 03 2009

The aim of this post is to get an AIR application to take a collection of files dragged n dropped onto it, zip them up on the client, and send them off to the server (ASP.NET). 

There are a few things to note here:

  • Flash officially supports files of up to 100MB, trying to ZIP anything larger and you WILL run into server memory issues; Flash will crash. You can use File.upload() for files > 100MB, but trying to ZIP them will cause the crash.
  • ZIPping on the client takes time, 50MB could take from 15s to a minute. The code supplied performs it sync (not async). 
  • client software FZip, server zip : ISharpZipLib 
  • uploading manually (using URLLoader instead of File.upload means in you cannot track the Upload’s progress – as of AIR 1.5).

 

Step 1. The Drag & Drop in AIR

This is quite trivial. Allowing the user to drag and drop as many files/folders onto your application.

Client (AIR) code:

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

	nativeDragEnter="onDragEnter(event)"
	nativeDragDrop="onDragDrop(event)"

	layout="absolute" 

	xmlns:mx="http://www.adobe.com/2006/mxml" >

	<mx:Script>
		<![CDATA[

			import mx.managers.DragManager;
			import mx.events.DragEvent;

			private function onDragEnter(evt:NativeDragEvent):void
			{
				//ensure clipboard contains files
				if (evt.clipboard.hasFormat(ClipboardFormats.FILE_LIST_FORMAT))
				{
					NativeDragManager.acceptDragDrop(this);
				}
			}

			private var _filesToUpload:Array;

			private function onDragDrop(evt:NativeDragEvent):void
			{
				_filesToUpload = evt.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
			}

		]]>
	</mx:Script>

</mx:WindowedApplication>

 

Step 2. Zipping on the client

The nicest solution I could find for compressing files in AIR to ZIP is FZip.

I tried another library, but ISharpLib didn’t like it, it was giving me EOF file header issues in the ZIP decompression.

So the solution is to take the ZIP byteArray and to send it via the lower level URLLoader class.

NOTE: this uses the FileStream.open is sync mode. You could use FileStream.openAsAsync though it would obviously require listening and handling the corresponding events.

Client (AIR) code [URLLoader.load() solution]:

var request:URLRequest = new URLRequest("http://example.com/Handlers/UploadHandler.ashx");

request.method = URLRequestMethod.POST;
request.contentType = "application/octet-stream";

var loader:URLLoader = new URLLoader();

loader.dataFormat =  URLLoaderDataFormat.BINARY;

loader.addEventListener(Event.OPEN, onFileUploadStart,false,0,true);

//no point listening for progress, because it doesn't work for URLLoader uploads, only downloads
//loader.addEventListener(ProgressEvent.PROGRESS, onFileUploadProgress,false,0,true);

loader.addEventListener(Event.COMPLETE,onFileUploadComplete,false,0,true);

var fzip:FZip = new FZip();

for each (var file:File in model.filesToUpload)
{
	var fs:FileStream = new FileStream();
	fs.open(file, FileMode.READ);
	var data:ByteArray = new ByteArray();
	fs.readBytes(data);
	fs.close();

	fzip.addFile(file.name, data);
}

var bytes:ByteArray = new ByteArray();
fzip.serialize(bytes);

request.data = bytes;

loader.load(request);

 

What about sending extra parameters?

Client (AIR) code:
var request:URLRequest = new URLRequest("http://example.com/Handlers/UploadHandler.ashx?someVariable=" + someVariable);

What about the upload progress bar? 

If you need the progress bar, then you’re best option is writing this zip file to the client and uploading that. 

This also means that if you have optional parameters, you don’t have to append them to the URL but can send them in the data.

This changes the client code to use File.upload().

Client (AIR) code – [File.upload() solution]:

var params:URLVariables = new URLVariables();

params.someVariable = someVariable;
//add other variables here

var request:URLRequest = new URLRequest(model.UPLOAD_URL);

request.method = URLRequestMethod.POST;
request.data = params;

var fzip:FZip = new FZip();

for each (var file:File in model.filesToUpload)
{
	var fs:FileStream = new FileStream();
	fs.open(file, FileMode.READ);
	var data:ByteArray = new ByteArray();
	fs.readBytes(data);
	fs.close();

	fzip.addFile(file.name, data);
}

//get the zip as a byte array
var bytes:ByteArray = new ByteArray();
fzip.serialize(bytes);

//write the zip to a local file
var fsW:FileStream = new FileStream();
//change "tmp.zip" to a better name :)
var wFile:File = File.applicationStorageDirectory.resolvePath("tmp.zip");

fsW.open(wFile, FileMode.WRITE);
fsW.writeBytes(bytes);
fsW.close();

//listen to upload events
wFile.addEventListener(Event.OPEN, onFileUploadStart,false,0,true);
wFile.addEventListener(ProgressEvent.PROGRESS, onFileUploadProgress,false,0,true);
wFile.addEventListener(Event.COMPLETE,onFileUploadComplete,false,0,true);

//start the upload
wFile.upload(request);

 

Step 3. Unzipping on the server

Now, I use SharpZipLib in .NET because it’s Open Source, and because it’s also bundled with WebORB .NET, the remoting gateway that I often use.

If you use the URLLoader.load() option above (from Step 2) – then you must use Request.InputStream to access the parameters

Server (ASP.NET C# Handler – ashx) code: (SharpZipLib extraction)

using ICSharpCodeInternal.SharpZipLib.Zip; 
   public class UploadHandler : IHttpHandler {

        public void ProcessRequest (HttpContext context)
        {
            String someVariable = context.Request["someVariable"];

            ZipInputStream zipStream = new ZipInputStream(context.Request.InputStream);
            ZipEntry zipEntry;

            while (true)
            {
                zipEntry = zipStream.GetNextEntry();

                if (zipEntry == null)
                {
                    break;
                }

                //choose location to extract files to
                string serverFolder = context.Server.MapPath("~/Uploads/");

                FileStream streamWriter = File.Create(( serverFolder + zipEntry.Name));

                int size = 2048;

                byte[] data = new byte[2048];

                while (true)
                {
                    size = zipStream.Read(data, 0, data.Length);

                    if (size > 0)
                    {
                        streamWriter.Write(data, 0, size);
                    }
                    else
                    {
                        break;
                    }
                }

                streamWriter.Close();

            }

            zipStream.Close();
        }
    }

 

 

If you are using File.upload() on the client 

You’re Handler in ASP.NET now will be looking in the context.Request.Files array for the attached ZIP.

Modified Server (ASP.NET C# Handler – ashx) code:

ZipInputStream zipStream = new ZipInputStream(context.Request.Files[0].InputStream);

 

If you need folder structures

To do ZIP folders, you simply add the folder name before the file when you ZIP:

Modified Client (AIR) code:

fzip.addFile(folderName + "/" + file.name, data);

 

And then in the server code, you need to create directories if required:

Modified Server (ASP.NET C# Handler – ashx) code:

//existing code
...
string serverFolder = context.Server.MapPath("~/Uploads/");
string dir = Path.GetDirectoryName(serverFolder + zipEntry.Name);

if (!Directory.Exists(dir))
{
    Directory.CreateDirectory(dir);
}                

//existing code
FileStream streamWriter = File.Create(( serverFolder + ze.Name));

...





Flex: understanding databinding: oneway and twoway

17 02 2009

Something that isn’t that well talked about in the Flex world is two way databinding, and it’s implications. 

I was working with an MVC project recently and I came up to an interesting problem with an ArrayCollection somewhere in the View that was bound oneway from the Model. When I changed a property of the object in the View, it changed in the Model. Huh? I didn’t use two-way databinding so why would this happen?

I realised this was due to the fact that while one-way databinding doesn’t change the source when the destination object changes, it DOES ensure that both objects have the same reference. The implication here is that if you change a property of the destination object, it will change in the source as well. They are the same object reference after all.

Let’s prove this with examples. Simple databinding in Flex is trivial. 

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" backgroundColor="white">

<mx:Script>
<![CDATA[

[Bindable]
public var someName:String;

]]>
</mx:Script>

<mx:TextInput text="{someName}" />

<mx:Label text="This is the local obj 'someName': {someName}" />

</mx:Application>

That’s all well and good but what if we want to change the someName variable back? We insert a Binding tag to bind back – two way binding.

<mx:Binding source="textInput.text" destination="someName" />

OK great. But something is happening here that needs to be discussed.  The binding is REPLACING the reference of “someName” to that of a new String. So it may be logical to assume that we need two-way binding when updating the destination of some binding to reflect the changes in the source. But, hang on:

Say I have this Model: 

package
{

	[Bindable]
	public class TestModel
	{
		public static var obj:TestObject = new TestObject("test via model","me via model");
	}

}

And say I have some Object: (TestObject.as)

package
{
	[Bindable]
	public class TestObject
	{

		public var name:String;

		public var desc:String;

		public function TestObject(n:String, d:String)
		{
			this.name = n;
			this.desc = d;
		}

	}
}

And this is my Application:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" backgroundColor="white">

	<mx:Script>
		<![CDATA[

			[Bindable]
			public var someObj:TestObject;

		]]>
	</mx:Script>

	<mx:Binding source="TestModel.obj" destination="this.someObj" />

	<mx:Binding source="textInput.text" destination="someObj.name" />

	<mx:Label id="someLabel" text="From the MODEL: {TestModel.obj.name}" />

	<mx:TextInput id="textInput"  />

	<mx:Label text="This is the name locally: {someObj.name}" />

</mx:Application>

I’m simply binding the Model to the local “someObj” (one-way) and then ensuring that changing the TextInput will change the name property of “someObj”. What happens? Try it. 

testbinding

Notice how my Model is also changing? So, you can see that one-way binding actually ensures that both the source and the destination point to the same object reference. You use two-way binding if you need to change the entire destination object completely and want this to be reflected in the source.

Let’s have a look at the final example:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" backgroundColor="white">

	<mx:Script>
		<![CDATA[

			[Bindable]
			public var someObj:TestObject;

			private function onEnter():void
			{
				someObj = new TestObject("created locally","local");
			}

		]]>
	</mx:Script>

	<mx:Binding source="TestModel.obj" destination="this.someObj" />

	<mx:Binding source="textInput.text" destination="someObj.name" />

	<mx:Label id="someLabel" text="From the MODEL: {TestModel.obj.name}" />

	<mx:TextInput id="textInput" enter="onEnter()"  />

	<mx:Label text="This is the name locally: {someObj.name}" />

</mx:Application>

Now, when you hit “ENTER” on your keyboard aftering entering some text, you’ll see the local object now points to a new object instance. And, you can see the Model doesn’t change from this point on, because it still points to the original instance. If you wanted the Model to update from this change, you would add:

<mx:Binding source="someObj" destination="TestModel.obj" />

 

Although you’d be careful to insert it AFTER the Binding tag that assigns someObj as the destination and TestModel as the source. Otherwise you’ll set the Model to null before you begin!

Make sense?





Silverlight vs Flex

16 02 2009

The Silverlight vs Flex argument is hillarious!

We’ve got a statement from Adobe’s CFO here on Silverlight. Personally I think that the CFO wasn’t the best person to comment on Silverlight, but hey, maybe we got an insight into Adobe’s non-censored attitude to Silverlight. 

We’ve got a response from Tim Sneath, a Silverlight evangilist from Microsoft.

We’ve got a debate with an MS evangilist vs an Adobe evangilist. (To be fair to Silverlight, the MS guy seems like he’s a fish out of water. He starts off with a great argument about competition making us better developers, and ends up floundering).

If you ask me, Adobe needs to fix the perception that most developers have that Flash simply sux. 

The problem is, that for years, the Flash platform was only accessible to those freaks who understood and lived in the four dimensional world of Flash. Trying to code on multiple layers with inherited objects in respect to time and still understanding  scope was, and still is, a nightmare

 I think many web developers have poked their noses into Flash – and many developed a natural distaste for it. Those that tended towards design sometimes learned to love it (and we learned to hate them for polluting the web with horrendous Flash websites that were inaccessible and useless). Then came Flex, at a time when web apps and Web 2.0 was the wave of the future. Macromedia released an SDK that finally made the power of Flash available  (“leveragable” in biz speak) to developers who wanted to use it.

Microsoft, on the other hand, have wowed developers ever since they took Java made .NET.  Managed code – with the ever evolving C# – allows us  developers to write pure object oriented code from web sites to windows applications. And thank god. I mean, I don’t have much interest in OS programming or the kernel. I’ll let others specialise in that. I’m interested in engaging, interactive applications, in whichever form they take.

Let’s get back to basics. Adobe specialises in cross platform solutions. Microsoft have a vested interest in Windows. 

Adobe has flash advocates (I’m using this term from now on) who were pre Flex (ewww), and post Flex (like me). Microsoft has .NET evangilists. Actually, I’m a good example, cause I’m both. I trained in Computer Science at university. I worked mainly with Java on Solaris machines. When I finished uni, I wanted to write software that people would use. I started with the web because of it’s reach, and have been focused on it ever since.  So now I write Flex and AIR apps that interface with .NET, and I’m happy to look at other RIA technologies as long as they

  • Compile (I’m sorry, but I like the portability of compiled code); 
  • Allow for OO programming (Yes, AS3 is OO – close enough anyhow); and
  • Are portable; and
  • Are accessible.

I think the issue between Flash & Silverlight is all this use of “Company X” evangilist business. Too many religious connotations. No wonder there’s so much passion in this argument. Everyone’s drawing lines in the sand. WTF? Anyone heard of software architecture? The goal is to understand as many technologies as possible to create the best solution for the client – whoever they may be. The platform is just a means to an end. We’ve got to constantly weigh up the options from all sides to create the right system at the right time.  

I’m giving myself a task. Over the coming months, I’m going to investigate Silverlight further, now that v2 allows me to code the frontend in C#, and because .NET 4.0 is looking to integrate the client and server within the single code base. As I go through it, I’m going to post my findings here, for those who want the quasi-objective truth.





what’s the big deal with Flash 10

13 02 2009

Rather than explaining what makes Flash 10 so impressive, here are a few links:

Things are just starting to get interesting.