"; */ ?>


19
Aug 09

Erlang ! { me, Hello }.

send hello message to Erlang

Erlang has been around since I was 7, so by this point I had 23 years to say hello to Erlang, but just did not get to it until today.. At 10 I was busy with chess, at 15 with girls, at 20 girlfriends, at 25 I don’t remember (that was a quite frequent condition at that age), and only now at 3 o’clock in the beautiful Wednesday morning, here in one of many Chicago hotels, I can really say it outloud: “Erlang ! { me, Hello }.”, or as we all use to saying it “System.out.println( “Hello to Erlang from me” );”, or using the language of our grandparents: “Me: Hello Erlang!”

I already spent about 30 minutes playing with it – 5 minutes with erl interpreter, 5 minutes coding, and 20 minutes figuring out how the heck I can execute it from command line with passing parameters to functions. So here it goes 30 minute summary in “count yourself” number of sentences…

From “Erlang – Quick Start“, I stole a factorial (fac) function:

-module(test).
-export([fac/1]).
 
fac(0) -> 1;
fac(N) -> N * fac(N-1).

“Compile the program by typing c(test) then run it” said Erlang site, so I did:

3> c(test).
{ok,test}
4> test:fac(20).
2432902008176640000
5> test:fac(40).
815915283247897734345611269596115894272000000000
6>

What I wanted to do now is to have a more useful factorial that can actually take a number parameter and run from a command line. See, Erlang is cool with numbers, because it uses arbitrary-sized integers when it does integer arithmetic, and I wanted to see that 10000.. digit number on my screen, but I wanted to do it from command line…

Hence, reading further the Erlang’s documentation, in Erlang How To FAQ I found “How to run an Erlang program directly from the unix shell:”

        matthias >erl -compile hello
        matthias >erl -noshell -s hello hello_world -s init stop
        hello, world

Great, I thought, let’s run my factorial function then:

$ erl -noshell -s test fac 4 -s init stop
{"init terminating in do_boot",{undef,[{test,'test:fac',[['4']]},{init,start_it,1},{init,start_em,1}]}}
 
Crash dump was written to: erl_crash.dump
init terminating in do_boot ()

I tried many different combinations, prefixes, suffixes, but nothing seemed to work. Google (at this time) did not really help, and I spend another 5-10 minutes by going to actually study the language from multiple online resources I could find. After aggregating the knowledge, here goes a solution:

-module( matematika ).		% module name = file name
-export( [factorial/1] ).		% exporting a factorial function, that takes exactly 1 argument
 
% public, since exported above
factorial( [CommandLineParameter] ) ->
 
	% converting the input parameter to an integer, so we can use it in (private) fac below
	Number = list_to_integer( atom_to_list( CommandLineParameter ) ),
	FactorialResult = fac( Number ),
 
	io:format( "~w! = ~w~n" ,[Number, FactorialResult] ),			% pretty much like printf in C
	init:stop().											% need to explicitly stop it
 
% private, since not exported
fac( 0 ) -> 1;					% if 0, then return 1
fac( N ) -> N * fac( N - 1 ).			% else return fac of N minus 1

(I put %comments above for myself, so I can make sense of it tomorrow)

Let’s run it now:

$ erl -noshell -s matematika factorial 10

10! = 3628800

Awesome! My first stolen and adapted Erlang creation! Let’s see that factorial of .. let’s say 2500 :)

$ erl -noshell -s matematika factorial 2500


2500!=162888842416926354689668105747439663365399942834366593333
761170598517395953006666015681181171091114301822189949967063775
407379642957266480360849144773982699565766503949953039081536069
313589385624248687168633365117877728319632346514905978458047074
520807127737619451831790023662437656379915366899692425817099473
955735537991551620610205879561628364536090561091825520933523438
440298824173752468219542814600203368965255916069562338913433294
969546310263930229454748650689662592679638050717072642347493989
468072742236518740460239946352245451040613097756653973305720645
026457997934905356924399618617581860376174835804874205168542257
467008667252720784248969925977883224857503131037675382806351903
130554386521130700598953600694590165036980214021274304347037205
774546036842214862077129715702791830982471445806697511922924126
875707763824427831458131252725129871400134654305773736954160374
386043307314954277237484986013167770729137200202006247592856875
946971039429028314584331171481048021391502558449541563727025722
429319793486407721042419353225446943557177410280427218310573933
839468119502298621190184926686015339505156759957938618691111894
105137524428488796590017749394464101657140531047449031317150211
285312051145217906000448322292856476064080179041772517805638616
704522178956984018390162683438304694297727727823412207694734265
878202872900194730775246958252155279043555763913056000888393253
937210136778443737969895720575345197710315491879632577212080296
732791524306529332768002582234532193839787438122696823349137174
760687670811121707247122877205618078452290605963728534389393406
703483582596248272104119965697657195713053485619074455216492879
719763758474871783557654928157780691218383646855409834599921063
373144702996594627688077741944550267192758309026313016206320680
530057452746436412708183108931890404685083431502083760663324657
349706015263327982666486689576849283883469142513936741022368381
903094157650249629927012864342540407330646247523995884057015184
717062826800920338962166558742062917836339935141477580556616102
759761599188076139416375666490347795870693771994555537476372358
925544445791134700553339780029989334462364486499563386435498770
970697902521176942715439141796399164240719914064566047833333979
658667979051009689054775584486605430424545544714920455985028492
775158386405002083658607397637102066859718496781089357617987825
390662781413816362946370821897681257991937027979675382384665624
733872791767882787048074812304136442761397202291044563080832580
377638267813956876382413025080202917826793584257121650412123520
8825054296165661030756208371742686402825404804558501327839670
731298809850930719924452525141301863810787127140637580161952796
470931012669932742565234239616031337114081022694921413641260386
424388652301371711255153268827616495293442715781089495795404683
744579676459521729702016200147034375778237008585095355232063710
088291957991216310837002831440396924100323429063456827045895594
917126433490705797776990807538192111396635158758664846773837413
564155213989495350785689041240261464178518418465026963508203252
038246166655605208324074965984192733197462771017672726300923288
607540014472757890113403434211921496288437000162551272645252320
615215716654175248938850328046313070690361405371373329623736166
731299101093298365654056037733083226277004269609573104069448790
684864546219098996171110998911324197479806896470305987119560932
856582719643423019817880041224237194274668604715496198407207355
809431389490372488422206677783166941973289816036063374723748298
696836902300888969044824525828910570687623075008425420179724412
174632013134752558921448609478176626573353890791801685222886849
990731518133839408072332112603244018982882369997032825586118714
392208201914776888366261219130250913546151105147763080829651928
290074106631605007724254431488105804572887069328232683043301900
466160052172383665181738152989844063638391709547589900409420631
7468376377314153856018840069377218558903334939371343395777264
426365318130887683599836088345497158322556553595094840894654614
406383376396868199531042942079405403474627428650274595771829568
255995466465003325664472293654101201924430539079190443194487046
380416281749159026300696294947812447714612418298771332692848211
154125929312681287195951419960699391722211424311898584816200565
373258799897110855302098610980845978364362685231061369005215230
788471798866541648729889538439509890111560301062943923923769988
997147648363950708508382034563798637202146673551309938897540440
786998003118907883241416258343188784000679367284896011745823289
734561911522255979545433492376668285434347783001266108600121473
498779217963921384546755156766188951735866744108093964636023471
349527019498920540070752394649104708510770999131507315610483632
330982876174119389012968417760250231722884408641474340374893362
833795392300949100935853949419952854923937872507275773843355108
735204114864752466565493366395162830913421138498633186453324268
762572668445390770903011717202242312950408723851830364004678106
656009078222984968635868416766693788940980240045058068275614302
839043567118028698385054274108921811298084233976240006277809181
325997330000786683674194376654268377368369949823431206244095885
960702059149846318232687179678572748082487793549844548187548311
400556064744050666472476457947299489568330636742840865513804654
776149494225932236964194164784786218640251626514525549920894810
545056499250214652147224638246034892251401029945773476251196919
612592752826016419187902895630887737745713281219681141023586882
321633118519558748181198803719862314967759867112077291645583600
510531017148754676649505951293767894337326791942862414631993126
449392270145239108425380056269282654566300820253116701666036949
374826952156733286262700190206665725355635411559887439781283350
874285109852181238143636938256407098028863909426094536431398247
852543854757537942646791855344906017659039384905122375234004320
416026882823286655632286053156546748028668750196973803337027786
891236116711910780819707846081218679760982625290715984522150204
916425232591826590887410401320568045430558979943145617193692059
705465421939829497586908594951642657711985208269462425640322372
314303330475772671495014049400654155619566942191085558759378416
790160458835621823599743742665152596726797511419955382867531134
959437002011587472231152746047820309830039699792147174883667855
760287780241438038062954704157981072533480950728570115662921849
376586317866043009133972729549191452640224225320222817060812601
144385749818368781373067888827129923654130858902252804622762751
192618314790547633755929057344102888830740499275949997990026813
425216747458578654838647236496508876074530642629714199563056483
975900965902520059913821418901761372054615449749487163282905699
188377895083782877246773269374715942460000414707728522199826307
191493572953655749106244370767768017669677808468909623091993519
298870943235516530358122980923396832082235382703392292864000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000

Now, THAT is cool!


26
Jul 09

Apache Chain with Spring

“A popular technique for organizing the execution of complex processing flows is the “Chain of Responsibility” pattern, as described (among many other places) in the classic “Gang of Four” design patterns book. Although the fundamental API contracts required to implement this design patten are extremely simple, it is useful to have a base API that facilitates using the pattern, and (more importantly) encouraging composition of command implementations from multiple diverse sources.”

That is what Apache has to say as an intro to its Commons Chain API

It is no brainer, really, but Apache APIs do make it simpler to configure, implement and execute multiple Chains of Responsibilities. One thing, however, that feels “off”, when (if) implementing “Commons Chain” side by side with Spring, is there is no flexible, consistent (with Spring) way to setup Command objects: inject Command properties / refer to a single Command class as a bean, instead of duplicating the class name in Apache Chains, and Spring configuration, if Command object needs to be reused, etc…

Here is a simple way to utilize all the power that Apache offers + make it Spring friendly. Five components will be used in this example – 1 core class, 2 command classes, 1 test (driver) and Spring configuration file. Let’s see if you can figure out which is which :):

apache commons chain on spring: components

As you can see we are going to play an ultra short session of table tennis, or how it is sometimes called “Ping Pong”. It is going to be quite short, because we have two command objects: Ping and Pong, which are going to be chained, and run (by ChainRunner) once each: “Ping -> Pong”.

First, instead of relying on Apache way to configure chains, to make it consistent with all other application beans (classes) we’ll keep chain(s) configuration in Spring:

chain-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.5.xsd">
 
	<bean name="pingPongChain" class="org.apache.commons.chain.impl.ChainBase">
		<constructor-arg>
			<util:list>
				<ref bean="pingCommand" />
				<ref bean="pongCommand" />
			</util:list>
		</constructor-arg>
	</bean>
 
	<bean name="pingCommand" class="org.dotkam.samples.chain.command.PingCommand">
		<constructor-arg value="ping"/>
	</bean>
 
	<bean name="pongCommand" class="org.dotkam.samples.chain.command.PongCommand">
		<constructor-arg value="pong"/>
	</bean>
 
	<bean id="chainRunner" class="org.dotkam.samples.chain.ChainRunner"/>
 
</beans>

A “pingPongChain” is configured as “org.apache.commons.chain.impl.ChainBase”, and have two Commad classes, that implement “org.apache.commons.chain.Command” interface, wired in.

NOTE: The best practice is to keep Commands either stateless, or, if they have to have a state – immutable. If this practice is followed, these Commands can be safely reused throughout many chains (or even as stand alone utilities). That is the reason, in configuration above, parameters are injected at Command’s creation time via constructor injection.

In this example Commands are ultra simple for clarity:

PingCommand.java:

package org.dotkam.samples.chain.command;
 
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
 
public class PingCommand implements Command {
 
	private String message;
 
	public PingCommand( String message ) {
		this.message = message;
	}
 
	public boolean execute( Context context ) throws Exception {
 
		System.err.println( message );
		return false;
	}
}

and PongCommand.java:

package org.dotkam.samples.chain.command;
 
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
 
public class PongCommand implements Command {
 
	private String message;
 
	public PongCommand( String message ) {
		this.message = message;
	}
 
	public boolean execute( Context context ) throws Exception {
 
		System.err.println( message );
		return false;
	}
}

Now let’s look at the heart of the “Spring Chainer” – the “ChainRunner.java”:

package org.dotkam.samples.chain;
 
import org.apache.commons.chain.impl.ChainBase;
import org.apache.commons.chain.impl.ContextBase;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
 
public class ChainRunner implements BeanFactoryAware {
 
	private BeanFactory beanFactory;
 
	public void runChain( String chainName ) {
		try {
			createChain ( chainName ).execute( new ContextBase() );
		}
		catch ( Exception exc ) {
			throw new RuntimeException(
					"Chain \"" + chainName + "\": Execution failed.", exc );
		}
	}
 
	public void setBeanFactory( BeanFactory beanFactory ) throws BeansException {
		this.beanFactory = beanFactory;
	}
 
	protected ChainBase createChain( String chainName ) {
		return ( ChainBase ) this.beanFactory.getBean( chainName );
	}
}

It only does a couple of things, really.

By implementing Spring’s “BeanFactoryAware” interface, at runtime ChainRunner will have a reference to a “beanFactory” which it is going to use to obtain a reference to the requested chain via “createChain” method.

“ChainRunner” has an entry point which is a “runChain” method, that executes a chain by chain name (bean name in configuration file). For example, in the configuration shown above “pingPongChain” name can be provided.

It would ideally need to use a couple of custom runtime exceptions: e.g. ChainNotFoundException, IsNotChainException and ChainExecutionException, but we’ll keep it short here for clarity.

Alternatively, to strong type chains a bit, “ChainRunner” could take a Map of chains with keys as chain names, and corresponding “ChainBase” chain objects as values.

“ChainRunner” is pretty much everything that is needed in order to configure an Apache chain in Spring. We can run it by creating a JUnit (not really a test, just a driver):

ChainTest.java:

package org.dotkam.samples.chain;
 
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( locations={ "/conf/chain-config.xml"} )
public class ChainTest {
 
	@Resource
	ChainRunner chainRunner;
 
	@Test
	public void driveTheChain() {
		System.out.println("Starting up...      [Ok]");
		chainRunner.runChain( "pingPongChain" );
		System.out.println("Finised...          [Ok]");
	}
}

And here is the test/driver result:

apache commons chain on spring: results

Good start! Now it is time to sign up and see your name at the top of The International Table Tennis Federation (ITTF) World Ranking. Good Luck! :)


20
Jul 09

Blue Grails and not so Bluehost

Groovy on GrailsSomething pretty funny happened to me today. I went to the Bluehost website, just because I have one of my Rails applications deployed there, and without doing much of a research (did not spend 4 seconds googling), using their online chat, I decided to ask Bluehost support team about their Java support.

Our dialogue was quite short, and very amusing (“first time sales” is me):

Blue Host Support:                           Welcome to our real-time sales chat. How can I help you today?
 
FIRST TIME SALES QUESTION:        hello
Blue Host Support:                           how can I help you today?
FIRST TIME SALES QUESTION:        hi Bluehost
                                                         can you guys host a Grails app?
 
Blue Host Support:                           what requirements does it have?
FIRST TIME SALES QUESTION:        what do you mean?
                                                         we have a couple of Grails apps and looking for hosting
 
Blue Host Support:                            what is grails?
                                                         a programming language I assume
                                                         what is it based on?
 
FIRST TIME SALES QUESTION:        http://www.grails.org/
                                                         Groovy
 
Blue Host Support:                            looks like it is used with Java
                                                         we don't run Java
                                                         that isn't possible on our servers

It is hard to hold your smile when one of the biggest hosting companies comes up with phrases like “What is Grails?” and “Java? That isn’t possible on our servers“. Still smiling…


24
Jun 09

What is The Best Java Web Framework?

What is the best Java web framework

No, really, what is it? Are you one of those people who ever wondered why there is actually more than one? Or you work with Struts for 5 years in a row, and think it is the best, just because you know all the nasty hooks you have to implement to make it do what you actually need?

Are you one of those die hard Rails fans, who (as most of Rails developers) does not really know Java, but already has a lot to say how bad it is?

Do you work in C++, and feel absolutely confident, that the framework, your company had developed for the last 25 years, that build web pages via socket programming is the best, and the most efficient one out there?

Is your company big enough, so it has a mature team of software (what they call themselves) architects, that take open source frameworks, and write their own single wrapper framework around it that, as they think (since they wrote it), is the 8th wonder of the (ancient) world?

You, see, I am a consultant – I know many of you, since I met “you” before :)

This one will be a very short article about my experiences with several Java Web Frameworks out there. Here we go:

Spring MVC Would be a good choice for the most of your needs

(I’ll give a short controller example below)

Wicket Interesting to look at – no XML, no JSP (JSTL), just Java and HTML. Can mimic a flow in a WebPage object. Better separation of concerns than, for example, in GWT (e.g. no Javish CSS, etc.). Good Community

The only thing that is off is your dynamic HTML elements are done in Java

Spring Webflow Yes – it is a separate beast. It mostly is good, and makes sense, however, in practice, once you need to do something a bit more complex that a shopping cart or a hotel booking app (hint, hint), you can run into problems. “Back button” and “Double click” are not very well handled by the framework, may get an exception while bookmarking (there is a magic recipe, but far from being simple, and intuitive), sharing data across the flow, last resort error handling are not simple, etc.
Stripes Good / simple (no XML – conventions), but not very actively maintained – hence not as mature. (good community though) Worth to look at for simple projects.
Struts Just architected wrong from the very beginning: Validation (XML – why? What about minimum search criteria, what about several, what about nested OO validators!?) / 0 for NULLs / Multi Action Forms / Testing (without StrutsTestcase) / etc. ) Improved a bit since WebWork merging, but still lots of “code smells”.
JSF Quite hard to keep up with all these JSF based JSP tags + integration with security is not simple + full JSF solutions are usually Frankensteins with many pieces from different vendors.
Tapestry Not bad, actually make sense, when you get it. But have you ever looked and tried to follow the Tapestry code? – Very complex implementation, if ever need to look inside the code + Tapestry does take time to learn, so forget about a new off-shore team, or fresh out of college not so geeky grads, taking it on.

And here is why I like Spring MVC:

  • Binding / Validation is done just right – clean, testable, reusable
  • Multiple View options ( PDF, XML, Excel, Atom, etc… ) done easy [AbstractExcelView, AbstractFeedView, AbstractJExcelView, AbstractPdfView, AbstractUrlBasedView, AbstractXsltView ]
  • Annotation based – no XML madness, and very clear when looking at the code – check the Pet Clinic in Spring 3.0 M3
  • Integrates with Spring JS very nicely ( in case needed )
  • Handing requests and parameters with ( Spring ) expression language – quite flexible
  • In Spring 3, MVC is actually REST aware (GET, POST, PUT, DELETE)

You can download Spring STS, import sample projects, and see many examples on how to use it, but here is a very simple controller example from Spring’s Pet Clinic:

@Controller                                                 // it’s a controller
public class ClinicController {
 
      @RequestMapping("/welcome.do")           // that all there is to mapping
      public void welcomeHandler() {
      }
 
      /** @return a ModelMap with the model attributes for the view
                                 uses org.springframework.core.Conventions */
      @RequestMapping("/vets.do")
      public ModelMap vetsHandler() {
            return new ModelMap(this.clinic.getVets());
      }
 
      @RequestMapping("/owner.do")
      public ModelMap ownerHandler(@RequestParam("ownerId") int ownerId) {  // parameters are passed in easily
            return new ModelMap(this.clinic.loadOwner(ownerId));
      }
}

It all depends on project’s requirements / timeline / resources / requirements / technologies already in place / etc… But having a choice, I do choose Spring MVC – it just makes sense: easy implementaion with Spring Roo / integration with Spring’s back end / support / community / releases / etc… I also like where Wicket is going, but it feels like “it is still going…”

In any case – good luck, and remember – if it does not have to be Java, but you still like to “stay close”, I would definitely give Grails a shot.


29
Mar 09

Adobe Flex in Ubuntu: Develop, Compile and Run

Flex on UbuntuRecently, browsing InfoQ I stumbled upon a very visual and interesting presentation by Christophe Coenraets “Rich Internet Applications with Flex and AIR“.

This presentation took place during QCon London 2008, where Christophe Coenraets, a Senior Technical Evangelist at Adobe, presented Flex and AIR, two technologies from Adobe used to create, deploy and run Rich Internet Applications.

I have not had any experience with Flex in the past, and, naturally, right after the presentation, I decided to give it a try – to develop, compile, and run an ultra simple Flex application. After some research, I found that there are two choices that are out there for Flex developers:

Adobe® Flex® Builder™ – software is a highly productive Eclipse™ based development tool enabling intelligent coding, interactive step-through debugging, and visual design of the user interface layout, appearance, and behavior of rich Internet applications (RIAs).

OR

Adobe® Flex™ 3 Software Development Kit (SDK) – includes the Flex framework (component class library) and Flex compiler, enabling you to freely develop and deploy Flex applications using an IDE of your choice.

While Adobe® Flex® Builder™ is an appealing option, it is not free. It starts from $300, and goes up to $700 for a professional edition. Whereas Flex SDK is open source and free – which is “a bit” cheaper than $300. The biggest difference between the two is that with just SDK, I will have to use my own IDE / text editor to write Flex applications, which is totally fine by me.

Step 1. Download Flex SDK.

Go to download Flex SDK, and check the box with “I have read the Adobe Flex SDK License, and by downloading the software listed below I agree to the terms of the agreement.”, you should see the “Download the Flex SDK for all Platforms” link to a Flex SDK zip file. Download it.

Unzip it to any directory that you like (in my case it is /opt/flex-sdk)

unzip flex_sdk_3.3.0.4589.zip

Step 2. Create an alias to compile MXML, ActionScript, etc. Flex applications.

Make sure java 6 is installed:

sudo apt-get install sun-java6-jdk

I need to have JAVA_HOME pointed to java 5 (JAVA_HOME=/usr/lib/jvm/java-1.5.0-sun), so I’ll hardcode the path to java 6 into flex compiler alias:

in ~/.bashrc:

# flex SDK home
export FLEX_SDK_HOME=/opt/flex-sdk
alias mxmlc='/usr/lib/jvm/java-6-sun/bin/java -jar "$FLEX_SDK_HOME/lib/mxmlc.jar" +flexlib="$FLEX_SDK_HOME/frameworks" "$@"'

re-login to the terminal (open a new terminal session). Now you can execute:

mxmlc youFlexApp.mxml

to compile an MXML file into an executable “youFlexApp.swf”

Step 3. Write a simple MXML application and compile it with Flex SDK.

Create a simple MXML file “flexTest.mxml”, that would create a button:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
        <mx:Button label="I am a simple flexy button" x="10" y="10" />
</mx:Application>

Compile it:

$ mxmlc flexTest.mxml
Loading configuration file /opt/flex-sdk/frameworks/flex-config.xml
/path/to/flexTest.swf (172884 bytes)

Now you should see a new SWF once the compiler is done:

$ ls -l
total 180
-rw-r--r-- 1 user group    217 2009-03-29 02:38 flexTest.mxml
-rw-r--r-- 1 user group 172884 2009-03-29 02:40 flexTest.swf

Step 4. Run compiled Flex application.

Open it with Firefox (make sure you have Adobe Flash Player plugin installed. If not, install it):

$ firefox flexTest.swf &

Now you should see that flexy button:

a simple button written in MXML and compiled by flex SDK

It is quite simple, really. Good Luck Flexing!