<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>JavaWorld's Daily Brew</title>
  <subtitle>Starting conversations in the Java developer community</subtitle>
  <link rel="alternate" type="text/html" href="http://www.javaworld.com/community"/>
  <link rel="self" type="application/atom+xml" href="http://www.javaworld.com/community/atom/feed"/>
  <id>http://www.javaworld.com/community/atom/feed</id>
  <updated>2008-12-31T18:46:04-05:00</updated>
  <entry>
    <title>From F3 to JavaFX 1.0 - Effects</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2202" />
    <id>http://www.javaworld.com/community/node/2202</id>
    <published>2009-01-05T10:45:53-05:00</published>
    <updated>2009-01-05T10:57:08-05:00</updated>
    <author>
      <name>Chris Oliver</name>
    </author>
    <category term="/JavaFX" />
    <category term="chrisoliver" />
    <category term="effects" />
    <category term="f3" />
    <category term="javafx" />
    <summary type="html"><![CDATA[<p>An important and impressive innovation between F3 and JavaFX is the <em>Effects</em> framework created by <a href="http://weblogs.java.net/blog/campbell/archive/2009/01/effects_in_java.html">Chris Campbell</a>.</p>
<p>
F3 had a simple system of software pixel filters, which could be applied to any Node or group of Nodes in a scene.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>An important and impressive innovation between F3 and JavaFX is the <em>Effects</em> framework created by <a href="http://weblogs.java.net/blog/campbell/archive/2009/01/effects_in_java.html">Chris Campbell</a>.</p>
<p>
F3 had a simple system of software pixel filters, which could be applied to any Node or group of Nodes in a scene. However, thanks to Chris, JavaFX 1.0 includes a much more complete set of effects, and a sophisticated framework that enables GPU hardware acceleration where available.</p>
<p>
Underlying the simple declarative expression of effects at the JavaFX script level, effect implementations are described in a GPU-shader-like procedural language, which Chris created, called JSL. Chris's JSL compiler then compiles to various targets, either GPU-based (GLSL/HLSL), or CPU-based (Java/Native).</p>
    ]]></content>
  </entry>
  <entry>
    <title>The Agile Rules in HP&#039;s Original Garage</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2199" />
    <id>http://www.javaworld.com/community/node/2199</id>
    <published>2009-01-05T04:09:42-05:00</published>
    <updated>2009-01-05T04:56:54-05:00</updated>
    <author>
      <name>Andrew Binstock</name>
    </author>
    <category term="agile. HP." />
    <summary type="html"><![CDATA[<p>According to a recent HP poster, these were the rules in Bill Hewett and Dave's Packard famous garage:</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>According to a recent HP poster, these were the rules in Bill Hewett and Dave's Packard famous garage:
<li>Believe you can change the world.</li>
<li>Work quickly, keep the tools unlocked, work whenever.</li>
<li>Know when to work alone and when to work together.</li>
<li>Share tools, ideas. Trust your colleagues.</li>
<li>No Politics. No bureaucracy. (These are ridiculous in a garage).</li>
<li>The customer defines a job well done.</li>
<li>Radical ideas are not bad ideas.</li>
<li>Invent different ways of working.</li>
<li>Make a contribution every day. If it doesn’t contribute, it doesn’t leave the garage.</li>
<li>Believe that together we can do anything.</li>
<li>Invent.</li>
<p>Curiously, it sounds like something the agile guys might have written (had they not written the manifesto). I prefer this wording because of its greater applicability and more dynamic presentation.</p>
    ]]></content>
  </entry>
  <entry>
    <title>&quot;Pragmatic Architecture&quot;, in book form</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2197" />
    <id>http://www.javaworld.com/community/node/2197</id>
    <published>2009-01-04T21:30:53-05:00</published>
    <updated>2009-01-05T02:57:08-05:00</updated>
    <author>
      <name>Ted Neward</name>
    </author>
    <summary type="html"><![CDATA[<p>
For a couple of years now, I've been going around the world and giving a talk entitled<br />
"Pragmatic Architecture", talking both about what architecture is (and what architects<br />
really do), and ending the talk with my own "catalog" of architectural elements and<br />
ideas, in an attempt to take some of the mystery and "cloud" nature of architecture<br />
out of the discussion. If you've read <em>Effective Enterprise Java</em>, then you've<br />
read the first version of that discussion, where Pragmatic Architecture was a second-generation<br />
thought process.
</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>
For a couple of years now, I've been going around the world and giving a talk entitled<br />
"Pragmatic Architecture", talking both about what architecture is (and what architects<br />
really do), and ending the talk with my own "catalog" of architectural elements and<br />
ideas, in an attempt to take some of the mystery and "cloud" nature of architecture<br />
out of the discussion. If you've read <em>Effective Enterprise Java</em>, then you've<br />
read the first version of that discussion, where Pragmatic Architecture was a second-generation<br />
thought process.
</p>
<p>
Recently, the patterns &amp; practices group at Microsoft went back and refined their <a href="http://www.codeplex.com/AppArchGuide">Application<br />
Architecture Guide</a>, and while there's a lot about it that I wish they'd done differently<br />
(less of a Microsoft-centric focus, for one), I think it's a great book for Microsoft-centric<br />
architects to pick up and have nearby. In a lot of ways, this is something similar<br />
to what I had in mind when I thought about the architectural catalog, though I'll<br />
admit that I'd prefer to go one level "deeper" and find more of the "atoms" that make<br />
up an architecture.
</p>
<p>
Nevertheless, I think this is a good PDF to pull down and put somewhere on your reference<br />
list.
</p>
<p>
Notes and caveats: Firstly, this is a book for solution architects; if you're the<br />
VP or CTO, don't bother with it, just hand it to somebody further on down the food<br />
chain. Secondly, if you're not an architect, this is <em>not</em> the book to pick<br />
up to learn how to be one. It's more in the way of a reference guide for existing<br />
architects. In fact, my vision is that an architect faced with a new project (that<br />
is, a new architecture to create) will think about the problem, sketch out a rough<br />
solution in his head, then look at the book to find both potential alternatives (to<br />
see if they fit better or worse than the one s/he has in her/his head), and potential<br />
consequences (to the one s/he has in her/his head). Thirdly, even if you're a Java<br />
or Ruby architect, <em>most</em> of the book is pretty technology-neutral. Just take<br />
a black Sharpie to the parts that have the Microsoft trademark around them, and you'll<br />
find it a pretty decent reference, too. Fourthly, in the spirit of full disclosure,<br />
the p&amp;p guys brought me in for a day of discussion on the Guide, so I can't say<br />
that I'm completely unbiased, but I can honestly say that I didn't write any of it,<br />
just offered critique (in case that matters to any potential readers).
</p>
<p></p>
<p>Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.<br />
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact<br />
me for details</a>.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Keep the build clean</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2196" />
    <id>http://www.javaworld.com/community/node/2196</id>
    <published>2009-01-04T10:57:13-05:00</published>
    <updated>2009-01-04T10:57:13-05:00</updated>
    <author>
      <name>jhannes</name>
    </author>
    <category term="java" />
    <category term="Software Development" />
    <summary type="html"><![CDATA[<p>Have you ever looked at a list of compiler warnings the length of an essay on bad coding and thought to yourself: &#8220;You know, I really should do something about that&#8230; but I don&#8217;t have time just now&#8221;? On the other hand, have you ever looked at a lone warning that just appeared in a compilation and just fixed it?</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>Have you ever looked at a list of compiler warnings the length of an essay on bad coding and thought to yourself: &#8220;You know, I really should do something about that&#8230; but I don&#8217;t have time just now&#8221;? On the other hand, have you ever looked at a lone warning that just appeared in a compilation and just fixed it?</p>
<p>When I start a new project from scratch, there are no warnings, no clutter, no problems. But, as the code base grows, if I don&#8217;t pay attention, the clutter, cruft, warnings, and problems can start piling up. When there&#8217;s a lot of noise, it&#8217;s much harder to find the real warning that I really wanted to read among the hundreds of warnings I didn&#8217;t care about.</p>
<p>To make warnings useful again, I use a zero-tolerance policy about warnings from the build. Even if the warning isn&#8217;t important, I deal with it. If it&#8217;s relevant, but not critical, I still fix it. If the compiler warns about a potential null-pointer exception, I fix the cause, even if I &#8220;know&#8221; the problem will never show up in production. If the embedded documentation (Javadoc or similar) refers to parameters that have been removed or renamed, I clean up the documentation.</p>
<p>If it&#8217;s something I really don&#8217;t care about and that really doesn&#8217;t matter, I ask the team if we can change our warning policy. For example, I find that documenting the parameters and return value of a method in many cases doesn&#8217;t add any value, so it shouldn&#8217;t be a warning if they are missing. Or, upgrading to a new version of the programming language may make previously okay code now emit warnings. For example, when Java 1.5 introduced generics, all the old code that didn&#8217;t specify the generic type parameter would give a warning. This is a sort of warning I don&#8217;t want to be nagged about (at least, not yet). Having a set of warnings that are out of step with reality does not serve anyone.</p>
<p><a href="http://www.flickr.com/photos/53843534@N00/2961939850/" title="21/10/2008 by brodwall, on Flickr"></a></p>
<p>By making sure that the build is always clean, I will not have to decide that a warning is irrelevant every time I encounter it. Ignoring things is mental work, and I need to get rid of all the unnecessary mental work I can. Having a clean build also makes it easier for someone else to take over my work. If I leave the warnings, someone else will have to wade through what is relevant and what is not. Or more likely, just ignore all the warnings, including the significant ones.</p>
<p>Warnings from your build are useful. You just need to get rid of the noise to start noticing them. Don&#8217;t wait for a big clean-up. When something appears that you don&#8217;t want to see, deal with it right away. Either fix the source of the warning, suppress this warning or fix the warning policies of your tool. Keeping the build clean is not just about keeping it free of compilation errors or test failures, warnings are an important and critical part of code hygiene.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Phishing attacks know no boundaries... or limits</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2195" />
    <id>http://www.javaworld.com/community/node/2195</id>
    <published>2009-01-03T20:22:38-05:00</published>
    <updated>2009-01-05T02:57:08-05:00</updated>
    <author>
      <name>Ted Neward</name>
    </author>
    <summary type="html"><![CDATA[<p>
People are used to the idea of phishing attacks showing up in their email, but in<br />
glowing testament to the creativity of potential attackers, Twitter recently has seen<br />
a rash of phishing attacks through Twitter's "direct messaging" feature.
</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>
People are used to the idea of phishing attacks showing up in their email, but in<br />
glowing testament to the creativity of potential attackers, Twitter recently has seen<br />
a rash of phishing attacks through Twitter's "direct messaging" feature.
</p>
<p>
The attack plays out like this: someone on your Twitter followers list sends you a<br />
direct message saying, "hey! check out this funny blog about you... " with a hyperlink<br />
to a website, "http://jannawalitax.blogspot.com/" . Clicking on the hyperlink takes<br />
you to a website that redirects to a webpage containing what <em>looks</em> like the<br />
Twitter login page. This is an attempt to get you to fill in your username, and more<br />
importantly, your password.
</p>
<p>
Needless to say, I'd avoid it. If you do get suckered in (hey, I admit it, I did),<br />
make sure to change your password immediately after.
</p>
<p>
What I find fascinating about this attack is that the direct messages come from people<br />
that are on my followers list--unless Twitter somehow has a hole in it that allows<br />
non-followers to direct-message you, it means that this is a classic security Ponzi<br />
scheme: I use the attack to gather the credentials for the people that I'm following<br />
directly, then log in and use those credentials to attack their followers, then use<br />
those gathered credentials to attack their followers, and so on. Fixing this is also<br />
going to be a pain--literally, everybody on Twitter has to change their password,<br />
or the scheme can continue with the credentials of those who didn't. (Assuming Twitter<br />
doesn't somehow lop the attack off at the knees, for example, by disallowing hyperlinks<br />
or something equally draconian.)
</p>
<p>
We won't even stop to consider what damage might be done if a Twitter-user uses the<br />
same password and login name for their Twitter account as they do for other accounts<br />
(such as email, banking websites, and so on). If you're one of those folks, you seriously<br />
might want to reconsider the strategy of using the same password for all your websites,<br />
unless you don't care if they get spoofed.
</p>
<p>
There's two lessons to be learned here.
</p>
<p>
One, that as a user of a service--<em>any</em> service--you have to be careful about<br />
when and how you're entering your credentials. It's easy to simply get into the habit<br />
of offering them up every time you see something that looks familiar, and if supposed<br />
"computer experts" (as most of the Twitterverse can be described) can be fooled, then<br />
how about the casual user?
</p>
<p>
Two, and perhaps the more important lesson for those of us who build software, that<br />
any time you build a system that enables people to communicate, even when you put<br />
a lot of energy into making sure that the system is secure, there's always an angle<br />
that attackers will find that will expose a vulnerability, even if it's just a partial<br />
one (such as the gathering of credentials here). If you don't need to allow hyperlinks,<br />
don't. If you don't need to allow Javascript, don't. Start from the bare minimum that<br />
people need to make your system work, and only add new capabilities after they've<br />
been scrutinized in a variety of ways. (YAGNI sometimes works to our advantage in<br />
more ways than one, it turns out.)
</p>
<p>
Kudos, by the way, to the Twitter-keepers, who had a message describing the direct-message<br />
phishing attack on the Twitter Home page within hours.
</p>
<p></p>
<p>Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.<br />
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact<br />
me for details</a>.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Easy Java-Based REST Testing Tools</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2193" />
    <id>http://www.javaworld.com/community/node/2193</id>
    <published>2009-01-03T12:41:00-05:00</published>
    <updated>2009-01-05T21:56:59-05:00</updated>
    <author>
      <name>dmarx</name>
    </author>
    <category term="Dustin" />
    <category term="Java (General)" />
    <category term="JW blogs" />
    <category term="rest" />
    <summary type="html"><![CDATA[<p>As I've been putting a paper together for <a href="http://www.teamycc.com/RMOUG_2009_Conference/presenters.html#Marxbio">my</a> <a href="http://rmoug.org/">Rocky Mountain Oracle Users Group</a> (RMOUG) <a href="http://www.teamycc.com/RMOUG_2009_Conference/presentations.htm">Training Days 2009</a> presentation <a href="http://www.teamycc.com/RMOUG_2009_Conference/presentations.htm#Marx">REST from Web Services Frustrations</a>, I have been wanting a very simple HTTP client and a very simple HTTP server to use to demonstrate both sides of using a REST-based web service.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>As I've been putting a paper together for <a href="http://www.teamycc.com/RMOUG_2009_Conference/presenters.html#Marxbio">my</a> <a href="http://rmoug.org/">Rocky Mountain Oracle Users Group</a> (RMOUG) <a href="http://www.teamycc.com/RMOUG_2009_Conference/presentations.htm">Training Days 2009</a> presentation <a href="http://www.teamycc.com/RMOUG_2009_Conference/presentations.htm#Marx">REST from Web Services Frustrations</a>, I have been wanting a very simple HTTP client and a very simple HTTP server to use to demonstrate both sides of using a REST-based web service.  More specifically, I want to demonstrate the various <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html">HTTP methods</a> being invoked from both the client perspective and from the server perspective.  In this blog posting, I will look quickly at the two <a href="http://java.sun.com/docs/books/tutorial/">Java</a>-based approaches I am currently planning on using for this presentation.</p>
<p><strong>RESTClient (rest-client)</strong></p>
<p>RESTClient is hosted on <a href="http://code.google.com/">Google Code</a> as the <a href="http://code.google.com/p/rest-client/">rest-client project</a> (not to be confused with the <a href="http://www.python.org/">Python</a>-based <a href="http://restclient.org/">RESTClient</a> project or even with the Google Code-hosted <a href="http://code.google.com/p/python-rest-client/">python-rest-client</a>).  <a href="http://code.google.com/p/rest-client/downloads/list">RESTClient 2.2</a> is currently available and there is an article called <a href="http://java.dzone.com/announcements/wiztoolsorg-restclient-21-rele">RESTClient 2.1 - Getting Started</a> that provides a nice introduction to RESTClient.  A large set of screen snapshots of RESTClient can be found at <a href="http://flickr.com/photos/subwiz/tags/restclient/">http://flickr.com/photos/subwiz/tags/restclient/</a>.</p>
<p>I like RESTClient because it is very simple (I was able to start using it quickly and without reading any instructions) and because it is Java <a href="http://java.sun.com/docs/books/tutorial/uiswing/">Swing</a>-based.  The RESTClient download is an executable JAR that is less than 5 MB in size.  Once downloaded, it does not need to be uncompressed, but can instead be directly executed with the command (for RESTClient 2.2):</p>
<p>     java -jar restclient-2.2-jar-with-dependencies.jar</p>
<p>When RESTClient is started as shown above, the Swing-based GUI comes up as shown in the next screen snapshot.</p>
<p><a href="http://4.bp.blogspot.com/_sDOe5HxTdMk/SV-vhvbM40I/AAAAAAAAA80/8ZJuuvO3J14/s1600-h/startingUpRestClient.png"></a></p>
<p>This screen snapshot demonstrates how self-explanatory this tool is to use.  One simply enters the URL of interest in the obviously named "URL" field and then selects the HTTP method to be used in the radio buttons underneath the again obviously named "HTTP Methods" header.  The bottom of this simple GUI has tabs for looking at headers and at the response body and has a large field for displaying response status information.  I will demonstrate some of this functionality toward the end of this blog posting.</p>
<p><strong>The Sun-Provided HTTPServer</strong></p>
<p>The RESTClient product described above, as its name suggests, covers my need for a simple REST client.  For a simple REST server, I had thought about using a <a href="http://java.sun.com/products/servlet/">Java servlet</a> with the appropriate methods corresponding to HTTP methods (<a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.html#doGet(javax.servlet.http.HttpServletRequest,%20javax.servlet.http.HttpServletResponse)">doGet()</a>, <a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.html#doPost(javax.servlet.http.HttpServletRequest,%20javax.servlet.http.HttpServletResponse)">doPost()</a>, <a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.html#doPut(javax.servlet.http.HttpServletRequest,%20javax.servlet.http.HttpServletResponse)">doPut()</a>, <a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.html#doDelete(javax.servlet.http.HttpServletRequest,%20javax.servlet.http.HttpServletResponse)">doDelete()</a>, <a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.html#doHead(javax.servlet.http.HttpServletRequest,%20javax.servlet.http.HttpServletResponse)">doHead()</a>, <a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.html#doOptions(javax.servlet.http.HttpServletRequest,%20javax.servlet.http.HttpServletResponse)">doOptions()</a>, and <a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.html#doTrace(javax.servlet.http.HttpServletRequest,%20javax.servlet.http.HttpServletResponse)">doTrace()</a>) overridden for my use.  However, I was really looking for the simplest solution that covered my needs and realized that the Sun-provided <a href="http://blogs.sun.com/michaelmcm/entry/http_server_api_in_java">HTTPServer</a> would work well here.</p>
<p>I have <a href="http://marxsoftware.blogspot.com/2008/03/suns-java-http-server.html">previously blogged about the HTTP Server</a> and adapted the example I provided in that blog posting to a slightly more sophisticated (but still extremely basic) tool to tell me, from a server perspective, what a potential HTTP/REST client has requested.  While I may tweak this a bit before the actual conference, I include its current state here.  The first class shown, <code>DustinHttpHandler</code>, is the class that implements <a href="http://java.sun.com/javase/6/docs/jre/api/net/httpserver/spec/com/sun/net/httpserver/HttpHandler.html">HttpHandler</a>.</p>
<p><strong>DustinHttpHandler.java</strong></p>
<p>package dustin.rest;</p>
<p>import com.sun.net.httpserver.Headers;<br />import com.sun.net.httpserver.HttpExchange;<br />import com.sun.net.httpserver.HttpHandler;<br />import java.io.IOException;<br />import java.io.OutputStream;<br />import java.net.HttpURLConnection;<br />import java.util.List;</p>
<p>/**<br /> * Simple HTTP-receiving server based on the Sun-provided HTTP Server.  Written<br /> * primarily to be with clients designed for interaction with REST-based<br /> * web services.  In other words, this simple HTTP Server implementation can be<br /> * used as a REST-based web services simulator.<br /> * <br /> * @author Dustin<br /> */<br />public class DustinHttpHandler implements HttpHandler<br />{<br />   /**<br />    * Only method prescribed by the HttpHandler interface.<br />    *  <br />    * @param httpExchange Encapsulation of HTTP request and response.<br />    * @throws java.io.IOException<br />    */<br />   public void handle(HttpExchange httpExchange) throws IOException<br />   {<br />      final String requestMethod = httpExchange.getRequestMethod();<br />      final String response = buildResponse(httpExchange);<br />      System.out.println("*** HTTP Request Method: " + requestMethod + "***");<br />      httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.length());<br />      final OutputStream os = httpExchange.getResponseBody();<br />      os.write(response.getBytes());<br />      os.close(); <br />   }</p>
<p>   /**<br />    * Build up the response String.<br />    * <br />    * @param httpExchange HTTP method associated with request.<br />    * @return Response String.<br />    */<br />   private String buildResponse(final HttpExchange httpExchange)<br />   {<br />      final StringBuffer buffer = new StringBuffer();<br />      buffer.append("&lt;html&gt;&lt;head&gt;&lt;title&gt;Dustin's Simple Example&lt;/title&gt;&lt;/head&gt;");<br />      buffer.append("&lt;body&gt;&lt;table border='1'&gt;");<br />      appendHtmlTableRow(buffer, httpExchange.getRequestMethod(), "HTTP Method");<br />      appendHtmlTableRow(buffer, httpExchange.getProtocol(), "Protocol");<br />      appendApplicationState(buffer, httpExchange, "Application State");<br />      appendRequestHeadersPortion(buffer, httpExchange.getRequestHeaders());<br />      buffer.append("&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;");<br />      return buffer.toString();<br />   }</p>
<p>   /**<br />    * Append the application state (query parameters provided in the URL provided<br />    * by the client) to the provided StringBuffer.<br />    * <br />    * @param buffer StringBuffer to which to append the client-provided<br />    *    application state.<br />    * @param httpExchange Provides the handle to the client-provided state.<br />    * @param label Label for the HTML table.<br />    */<br />   private void appendApplicationState(<br />      final StringBuffer buffer,<br />      final HttpExchange httpExchange,<br />      final String label)<br />   {<br />      appendHtmlTableRow(buffer, httpExchange.getRequestURI().getQuery(), label);<br />   }</p>
<p>   /**<br />    * Append provided headers to the provided buffer.<br />    * <br />    * @param buffer Buffer to which headers information will be appended.<br />    * @param headers Headers whose information needs to be appended to buffer.<br />    */<br />   private void appendRequestHeadersPortion(<br />      final StringBuffer buffer, final Headers headers)<br />   {<br />      appendHtmlTableWithHeaders(buffer, "Request Headers", headers);<br />   }</p>
<p>   /**<br />    * Append provided HTTP response headers to provided StringBuffer.<br />    * <br />    * @param buffer Buffer to which to append the response headers information.<br />    * @param headers Response headers to be appended to StringBuffer.<br />    */<br />   private void appendResponseHeadersPortion(<br />      final StringBuffer buffer, final Headers headers)<br />   {<br />      appendHtmlTableWithHeaders(buffer, "Response Headers", headers);<br />   }</p>
<p>   /**<br />    * Append an HTML table row with potentially multiple headers.<br />    * <br />    * @param buffer Buffer to which to append the new HTML table row.<br />    * @param headerLabel The highlighted label for the left column.<br />    * @param headers The headers to be appended to the provided buffer.<br />    */<br />   private void appendHtmlTableWithHeaders(<br />      final StringBuffer buffer,<br />      final String headerLabel,<br />      final Headers headers)<br />   {<br />      appendSingleHeaderRow(buffer, headerLabel);<br />      for (final Headers.Entry&lt;String,List&lt;String&gt;&gt; header : headers.entrySet())<br />      {<br />         appendHtmlTableRowMultipleValues(buffer, header.getValue(), header.getKey());<br />      }<br />   }</p>
<p>   /**<br />    * Build a two-column row for an HTML table with the elementString value<br />    * being placed in the right column and the elementLabel being placed in<br />    * the left column with heading emphasis.<br />    * <br />    * @param bufferToAppend Buffer to which to append HTML table row.<br />    * @param elementString Normal table data element (right column) value.<br />    * @param elementLabel Highlighted table header element (left column) value.<br />    */<br />   private void appendHtmlTableRow(<br />      final StringBuffer bufferToAppend,<br />      final String elementString,<br />      final String elementLabel)<br />   {<br />      bufferToAppend.append(<br />         "&lt;tr&gt;&lt;th&gt;" + elementLabel + "&lt;/th&gt;&lt;td&gt;" + elementString + "&lt;/td&gt;&lt;/tr&gt;");<br />   }</p>
<p>   /**<br />    * Append to buffer with an HTML table row that has potentially multiple<br />    * values for a single value column (multiple values per header column).<br />    * <br />    * @param bufferToAppend Buffer to which to append HTML table row.<br />    * @param elementStrings Multiple values to be appended in single values column.<br />    * @param elementLabel Header label for left column of row.<br />    */<br />   private void appendHtmlTableRowMultipleValues(<br />      final StringBuffer bufferToAppend,<br />      final List&lt;String&gt; elementStrings,<br />      final String elementLabel)<br />   {<br />      bufferToAppend.append("&lt;tr&gt;&lt;th&gt;" + elementLabel + "&lt;/th&gt;&lt;td&gt;");<br />      for (final String value : elementStrings)<br />      {<br />         bufferToAppend.append(value + "\n");<br />      }<br />      bufferToAppend.append("&lt;/td&gt;&lt;/tr&gt;");<br />   }</p>
<p>   /**<br />    * Append a single-cell row for HTML table section headers.<br />    * <br />    * @param bufferToAppend Buffer to which to append the single-cell header row.<br />    * @param value String to place in the single-cell header row; the section<br />    *    title.<br />    */<br />   private void appendSingleHeaderRow(<br />      final StringBuffer bufferToAppend,<br />      final String value)<br />   {<br />      bufferToAppend.append("&lt;tr&gt;&lt;th colspan='2'&gt;");<br />      bufferToAppend.append(value);<br />      bufferToAppend.append("&lt;/th&gt;&lt;/tr&gt;");<br />   }<br />}</p>
<p>The Main class that instantiates and uses the <a href="http://java.sun.com/javase/6/docs/jre/api/net/httpserver/spec/com/sun/net/httpserver/HttpHandler.html">HttpHandler</a> described above is called <code>Main</code> and its code listing is shown next:</p>
<p><strong>Main.java</strong></p>
<p>package dustin.rest;</p>
<p>import com.sun.net.httpserver.HttpServer;  <br />import java.io.IOException;  <br />import java.net.InetAddress;<br />import java.net.InetSocketAddress;  </p>
<p>/** <br /> * Simple executable to start HttpServer for HTTP request/response interaction.<br /> * <br /> * Run this class with a command line this:<br /> *      java -cp RESTfulJava.jar dustin.rest.Main<br /> * <br /> * The URL for connecting to this HTTPServer instance from a client will be<br /> *      <a href="http://localhost:8000/dustin" title="http://localhost:8000/dustin">http://localhost:8000/dustin</a><br /> */  <br />public class Main  <br />{  <br />   public static final int PORT = 8000;  <br />   public static final int BACKLOG = 0;   // none  <br />   public static final String DEFAULT_URL_CONTEXT = "/dustin";  </p>
<p>   /** <br />    * Main executable to run Sun's built-in JVM HTTP server. <br />    *  <br />    * @param arguments The command line arguments; single argument for URL<br />    *    context expected.<br />    */  <br />   public static void main(final String[] arguments) throws IOException  <br />   {  <br />      final String hostName = InetAddress.getLocalHost().getCanonicalHostName();<br />      final String urlContext = obtainUrlContext(arguments);<br />      final HttpServer server =  <br />         HttpServer.create(new InetSocketAddress(PORT), BACKLOG);<br />      server.createContext(urlContext, new DustinHttpHandler());  <br />      server.setExecutor(null); // allow default executor to be created<br />      System.out.println("\n\nSimple HTTP Server is running.  Use URL\n");<br />      System.out.println("    http://" + hostName + ":" + PORT + urlContext);<br />      System.out.println("\nto access this server.");<br />      server.start();  <br />   }</p>
<p>   /**<br />    * Extract the URL Context from the command-line or use a default if no<br />    * argument was provided on the command-line.<br />    * <br />    * @param commandLineArguments Command-line arguments.<br />    * @return URL context.<br />    */<br />   private static String obtainUrlContext(final String[] commandLineArguments)<br />   {<br />      String urlContext = DEFAULT_URL_CONTEXT;<br />      final int numCmdLineArgs = commandLineArguments.length;<br />      if (numCmdLineArgs &gt; 0)<br />      {<br />         final String cmdProvidedContext = commandLineArguments[0];<br />         urlContext = (cmdProvidedContext.startsWith("/"))<br />                     ? cmdProvidedContext<br />                     : "/" + cmdProvidedContext;<br />      }<br />      return urlContext;<br />   }<br />}  </p>
<p>I intentionally have the code print the URL to call to access the HttpServer to make it easier for clients to connect.  Note also that a command-line argument can be specified to override the context.  This is effectively the <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_2_1_1">resource representation</a> portion in <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm">REST parlance</a>.</p>
<p>It is easy to run this application to take advantage of the Sun-provided HttpServer.  I built the JAR to be executable as shown in the <code>Main-Class</code> entry in the META-INF/MANIFEST.MF file shown below:</p>
<p><strong>MANIFEST.MF of JAR file</strong></p>
<p>Manifest-Version: 1.0<br />Ant-Version: Apache Ant 1.7.0<br />Created-By: 11.0-b15 (Sun Microsystems Inc.)<br />Main-Class: dustin.rest.Main</p>
<p>With the JAR declared as an executable JAR (<code>RestServer.jar</code>), it is simple to run the application:</p>
<p>     java -jar RestServer.jar</p>
<p><strong>Leveraging the RESTClient with the Sun-Provided HTTP Server</strong></p>
<p>In most cases, I plan to use the RESTClient with "real" REST-based web services and use the HTTP Server approach with "real" clients of REST-based web services.  In that way, I have easy approaches to testing pieces of the REST interaction.  However, it can still be interesting to use the two together and I intend to do so in my presentation to provide some background on HTTP methods and terminology.</p>
<p>When I run the HTTP Server-based RestServer with a command-line argument of "rest/example/name", it looks like this:</p>
<p>     java -jar RestServer.jar rest/example/name</p>
<p>When running the above, I see the following expected output (with your own host of course and with a context different than "rest/example/name" if provided as a command-line argument):</p>
<p>Simple HTTP Server is running.  Use URL</p>
<p>      <a href="http://gandalf.marx.net:8000/rest/example/name" title="http://gandalf.marx.net:8000/rest/example/name">http://gandalf.marx.net:8000/rest/example/name</a></p>
<p>to access this server.</p>
<p>This means the simple HTTP Server is running and I can use CTRL-C to break it when I'm finished.</p>
<p>Running the RESTClient is really easy as discussed above:</p>
<p>     java -jar restclient-2.2-jar-with-dependencies.jar</p>
<p>I can enter the URL provided by the standard output of the HTTP Server in the URL field of the RESTClient GUI, select an HTTP method with the radio button, and click on the green greater-than signs/arrows pointing right.  When using POST method, and changing the tab at the bottom to "Body," the response body is shown as indicated in the following screen snapshot.</p>
<p><a href="http://3.bp.blogspot.com/_sDOe5HxTdMk/SV_o65-KlvI/AAAAAAAAA88/TfOztRBoMQ8/s1600-h/restClientPostResponseBody-httpServerExample.png"></a></p>
<p>If I change the HTTP method to a different method type, the body returned looks the same, but with the different method indicated.  The one exception is the HEAD method.  As expected, there is no response body shown for the HEAD method because "the HEAD method is identical to GET except that the server MUST NOT return a message-body in the response" (<a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4">http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4</a>).  The HEAD example is shown in the next screen snapshot.</p>
<p><a href="http://4.bp.blogspot.com/_sDOe5HxTdMk/SV_qlUVZsLI/AAAAAAAAA9E/PfpGArjfI_g/s1600-h/restClientHeadResponseBody-httpServerExample.png"></a></p>
<p>One can also use a web browser to see the returned body (which is conveniently in HTML thanks to my simple implementation of the HttpHander).  By default, the browser uses GET as shown in the following screen snapshot.  I also have added an id parameter to the URL for this example to indicate how application state can be passed by the client to the server and how the server in the HTTPServer example can provide an indication of the query parameters received.</p>
<p><a href="http://2.bp.blogspot.com/_sDOe5HxTdMk/SV_qzGFMKyI/AAAAAAAAA9M/ljvnFM7eNnk/s1600-h/restWebBrowserResponseBody-httpServer.png"></a></p>
<p><strong>Conclusion</strong></p>
<p>There are many tools that can be used in REST development and more are coming all the time.  Because I often find myself preferring the simplest tool for the job, it is difficult to beat RESTClient and the HTTP Server that comes with the Sun-provided JVM for simple testing and simple demonstration of REST principles and implementations.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Performance matters - 25x for JavaFX script over Groovy and JRuby</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2191" />
    <id>http://www.javaworld.com/community/node/2191</id>
    <published>2009-01-02T20:21:47-05:00</published>
    <updated>2009-01-02T20:57:12-05:00</updated>
    <author>
      <name>Chris Oliver</name>
    </author>
    <category term="/JavaFX" />
    <category term="chrisoliver" />
    <summary type="html"><![CDATA[<p>JavaFX script</p>
<p>function tak(x:Number, y:Number, z:Number): Number {<br />
    if (y &gt;= x) z else tak(tak(x-1, y, z),<br />
                           tak(y-1, z, x),<br />
                           tak(z-1, x, y));<br />
}</p>
<p>for (i in [1..1000]) {<br />
    tak(24, 16, 8);<br />
}</p>
<p>time javafx -server -cp . Tak</p>
<p>real    0m10.724s<br />
user    0m10.105s<br />
sys     0m0.173s</p>
<p>Groovy</p>
<p>def tak(double x, double y, double z) {<br />
    return y &gt;= x ?</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>JavaFX script</p>
<p>function tak(x:Number, y:Number, z:Number): Number {<br />
    if (y &gt;= x) z else tak(tak(x-1, y, z),<br />
                           tak(y-1, z, x),<br />
                           tak(z-1, x, y));<br />
}</p>
<p>for (i in [1..1000]) {<br />
    tak(24, 16, 8);<br />
}</p>
<p>time javafx -server -cp . Tak</p>
<p>real    0m10.724s<br />
user    0m10.105s<br />
sys     0m0.173s</p>
<p>Groovy</p>
<p>def tak(double x, double y, double z) {<br />
    return y &gt;= x ? z : tak(tak(x-1, y, z),<br />
                            tak(y-1, z, x),<br />
                            tak(z-1, x, y));<br />
}</p>
<p>int i = 0;<br />
while (i++ &lt; 1000) {<br />
    tak(24, 16, 8);<br />
}</p>
<p>time java -Djava.ext.dirs=./groovy-1.6-RC-1/lib -server groovy.lang.GroovyShell tak.groovy</p>
<p>real    4m36.674s<br />
user    4m29.272s<br />
sys     0m3.842s</p>
<p>
JRuby</p>
<p>def tak x, y, z<br />
  unless y &lt; x<br />
    z<br />
  else<br />
    tak( tak(x-1, y, z),<br />
         tak(y-1, z, x),<br />
         tak(z-1, x, y))<br />
  end<br />
end</p>
<p>i = 0<br />
while i&lt;1000<br />
        tak(24, 16, 8)<br />
        i+=1<br />
end</p>
<p>time ./jruby-1.1.6RC1/bin/jruby -J-server tak.rb</p>
<p>real    4m24.735s<br />
user    4m22.203s<br />
sys     0m1.069s</p>
<p>
Summary</p>
<p>
For this benchmark, as you can see both JRuby and Groovy are around 25x slower than JavaFX script.</p>
    ]]></content>
  </entry>
  <entry>
    <title>SSL under attack</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2188" />
    <id>http://www.javaworld.com/community/node/2188</id>
    <published>2009-01-02T15:09:55-05:00</published>
    <updated>2009-01-02T15:15:11-05:00</updated>
    <author>
      <name>Oleg Mikheev</name>
    </author>
    <category term="ssl md5 cert" />
    <summary type="html"><![CDATA[<p>Great news -- now you can't trust SSL certificates anymore. On the day before the New Year a successful generation of a rogue certificate was <a href="http://hackaday.com/2008/12/30/25c3-hackers-completely-break-ssl-using-200-ps3s/" title="yes">demonstrated</a> in Berlin. A group of game maniacs set up a cluster of 200 Sony PlayStation 3s -- that was enough to accomplish it :)</p>
<p>It's not about SSL as a whole, it's just about MD5 signatures that some SSL certificates are signed with.</p>
<p>What would it mean to Java developers?</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>Great news -- now you can't trust SSL certificates anymore. On the day before the New Year a successful generation of a rogue certificate was <a href="http://hackaday.com/2008/12/30/25c3-hackers-completely-break-ssl-using-200-ps3s/" title="yes">demonstrated</a> in Berlin. A group of game maniacs set up a cluster of 200 Sony PlayStation 3s -- that was enough to accomplish it :)</p>
<p>It's not about SSL as a whole, it's just about MD5 signatures that some SSL certificates are signed with.</p>
<p>What would it mean to Java developers?<br />
1. Double-check that certificates you rely on are not signed with MD5. Firefox lists this info in certificate details as Certificate Signature Algorythm.<br />
2. Leave MD5 in year 2008 and start using sha1. Just start typing sha1sum instead of md5sum :)</p>
<p>Also, this is not the first time when rogue certificates get generated. Advanced Windows viruses are using false Microsoft certificates for quite some time already.</p>
<p>Beware!</p>
    ]]></content>
  </entry>
  <entry>
    <title>Happy Java New Year!</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2186" />
    <id>http://www.javaworld.com/community/node/2186</id>
    <published>2009-01-02T13:41:48-05:00</published>
    <updated>2009-01-02T13:41:48-05:00</updated>
    <author>
      <name>Josh Fruhlinger</name>
    </author>
    <category term="2008" />
    <category term="java 7" />
    <summary type="html"><![CDATA[<!--paging_filter--><p>It's the end of the World's Slowest News Week here in Java land, which also happens to be simultaneously the last week of 2008 and the first of 2009.    ]]></summary>
    <content type="html"><![CDATA[<!--paging_filter--><p>It's the end of the World's Slowest News Week here in Java land, which also happens to be simultaneously the last week of 2008 and the first of 2009.  The biggest news stories over the last year or so, I would submit, were the <a href="http://www.javaworld.com/community/node/1887" target="_blank">slow but steady rise of SpringSource</a>, the <a href="http://www.javaworld.com/community/taxonomy/term/260" target="_blank">real live birth of JavaFX</a>, the <a href="http://www.javaworld.com/community/taxonomy/term/371" target="_blank">proliferating number of JVM languages</a>, and the downward spiral of Sun's financial situation, with its <a href="http://www.javaworld.com/community/node/1876" target="_blank">possible impact on Java</a>.</p>

<p>So I put it to you: what will be exercising the minds of Java developers in the coming 12 months? My #1 guess is something off the 2008 list, the fate of Sun -- there's a good chance that there will be a merger, massive restructuring, or other similar crisis.  This will have an impact on what should be the other big story: the development of Java 7, set for release in early 2010, but no doubt largely solidifying this year.  Nothing about it is settled yet (good lord, people are <a href="http://www.infoq.com/news/2009/01/java7-updated" target="_blank">still worked up about closures, or the lack thereof</a>) and <em>if</em> Sun is busy selling itself off for parts or being absorbed by IBM/Fujitsu/the Sheinhardt Wig Corporation, the handling of the Java 7 transition may be rocky; it will definitely be a big test of the Java community's ability to manage a true open source project.</p>

<p>Any guesses as to what I'll be wrapping up come early 2010?  Chime in in the comments!</p>    ]]></content>
  </entry>
  <entry>
    <title>G1 contacts import</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2184" />
    <id>http://www.javaworld.com/community/node/2184</id>
    <published>2009-01-02T09:01:20-05:00</published>
    <updated>2009-01-02T09:01:20-05:00</updated>
    <author>
      <name>Oleg Mikheev</name>
    </author>
    <category term="Android" />
    <summary type="html"><![CDATA[<p>This is a mini how-to for people wondering how their contacts can be imported into their G1 phones. There seem to be a lot of people who <a href="http://www.symbian-freak.com/news/008/12/android_g1_sync_review.htm" title="suffer">suffer</a> from G1 poor contacts management.</p>
<p>The official way of importing contacts is to keep them all in Gmail. For a number of reasons this is not very convenient, for one -- Gmail can import your contacts from CSV file only, it gives no other options.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>This is a mini how-to for people wondering how their contacts can be imported into their G1 phones. There seem to be a lot of people who <a href="http://www.symbian-freak.com/news/008/12/android_g1_sync_review.htm" title="suffer">suffer</a> from G1 poor contacts management.</p>
<p>The official way of importing contacts is to keep them all in Gmail. For a number of reasons this is not very convenient, for one -- Gmail can import your contacts from CSV file only, it gives no other options.</p>
<p>The standard way for contacts exchange is via Vcard files/format. So, I created a Java Android application that helped me to import all my contacts to G1. The Import Contacts app is published on Andappstore and is downloadable from <a href="http://andappstore.com/AndroidPhoneApplications/apps/27435" title="here">here</a>. Just point your G1 browser there.</p>
<p>In my case I had all my contacts in Nokia N70 in sync with Outlook (win) and Evolution (linux). In Evolution I exported all contacts to a single Vcard file, uploaded it to G1 microSD card, and imported the file using my app.</p>
<p>Of course this is a workaround to the real and yet unresolved problem, but Android SyncML and OBEX implementation is not something that I'm going to do in the near future.</p>
<p>And also it was fun to know that it was impossible to delete all contacts from G1 at once. If you want to clean your address book you must clean Gmail contacts and synchronize it with G1 then -- awkward. So I added this 'Wipe all contacts' functionality to Import Contacts too.</p>
<p>Enjoy!</p>
    ]]></content>
  </entry>
  <entry>
    <title>Android Market: pay to work</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2180" />
    <id>http://www.javaworld.com/community/node/2180</id>
    <published>2009-01-01T20:28:43-05:00</published>
    <updated>2009-01-01T20:28:43-05:00</updated>
    <author>
      <name>Oleg Mikheev</name>
    </author>
    <category term="Android" />
    <summary type="html"><![CDATA[<p>Just a small notice about the interesting situation that Android Market is putting its developers in.<br />
Currently it accepts freeware apps only, but at the same time it requires a paid registration to put an app there.<br />
This basically means that you have to pay TO work, a very innovative approach in the world where people get paid FOR their work :)<br />
However there exists a free third-party Android app store - andappstore.com, which I will use for my free apps.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>Just a small notice about the interesting situation that Android Market is putting its developers in.<br />
Currently it accepts freeware apps only, but at the same time it requires a paid registration to put an app there.<br />
This basically means that you have to pay TO work, a very innovative approach in the world where people get paid FOR their work :)<br />
However there exists a free third-party Android app store - andappstore.com, which I will use for my free apps.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Bare Bones BlazeDS Object Remoting</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2181" />
    <id>http://www.javaworld.com/community/node/2181</id>
    <published>2009-01-01T15:07:00-05:00</published>
    <updated>2009-01-05T21:56:59-05:00</updated>
    <author>
      <name>dmarx</name>
    </author>
    <category term="ActionScript" />
    <category term="BlazeDS" />
    <category term="Dustin" />
    <category term="Flex" />
    <category term="Java (General)" />
    <category term="JW blogs" />
    <summary type="html"><![CDATA[<p>In this blog posting, I will demonstrate using <a href="http://opensource.adobe.com/wiki/display/blazeds/BlazeDS/">BlazeDS</a> for <a href="http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&amp;productId=2&amp;postId=7766">object remoting</a> between a <a href="http://www.adobe.com/devnet/flex/">Flex</a> client and a <a href="http://java.sun.com/javaee/">Java EE</a>-based server.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>In this blog posting, I will demonstrate using <a href="http://opensource.adobe.com/wiki/display/blazeds/BlazeDS/">BlazeDS</a> for <a href="http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&amp;productId=2&amp;postId=7766">object remoting</a> between a <a href="http://www.adobe.com/devnet/flex/">Flex</a> client and a <a href="http://java.sun.com/javaee/">Java EE</a>-based server.  There are several good blog postings and <a href="http://www.infoq.com/articles/blazeds-intro">articles</a> on <a href="http://www.flexlive.net/?p=92">BlazeDS remoting</a> out there already (see Additional Resources section below), but most of them either don't provide a complete example or apply FlexBuilder for some of the "magic."  In this post, I will not use FlexBuilder and any IDE or text editor can be used.  This allows one to see all the underlying details directly.</p>
<p><strong>Tools Used in these Examples</strong></p>
<p>For the examples in this blog posting, I will be using the following tools:
<ul>
<li><a href="http://opensource.adobe.com/wiki/display/blazeds/download+blazeds+3">BlazeDS</a> - I am using BlazeDS 3.2 and I am using the binary distribution (not Turnkey that includes <a href="http://tomcat.apache.org/">Tomcat</a>) to be more "bare bones."</li>
<p>
<li><a href="http://opensource.adobe.com/wiki/display/flexsdk/Flex+SDK">Flex 3 SDK</a> - I am using Flex 3.2.  For convenience, I have set an environment variable <code>FLEX_HOME</code> to point to the main directory of my Flex 3 installation (where I unzipped it) and I have included <code>%FLEX_HOME%</code>\bin (or <code>$FLEX_HOME</code>/bin) on my <code>PATH</code>.</li>
<p>
<li><a href="http://java.sun.com/">Java</a> SE SDK - I am using <a href="http://java.sun.com/javase/6/">Java SE 6</a> Update 10, but a newer or older version of Java SE should be fine as long as you are using at least <a href="http://java.sun.com/j2se/1.5.0/">J2SE 5</a>.</li>
<p>
<li><a href="http://java.sun.com/javaee/">Java EE</a> web implementation - The BlazeDS Turnkey includes Tomcat, but I am using <a href="https://glassfish.dev.java.net/">GlassFish</a> for my examples.  In theory, it should not matter which Java EE-compliant web server you use.</li>
<p>
<li><a href="http://ant.apache.org/">Ant</a> (optional) - I provide a <code>build.xml</code> Ant build file in this posting that will build the Flex clients and will build the BlazeDS/JEE-powered server.  However, these operations can be done individually as well.  While I build a WAR file with my Ant build for the server-side deployment, one could simply edit directories and files in one's favorite server's deployment directory for the same effect.  Similarly, one could build the Flex clients individually on the command line with the <a href="http://livedocs.adobe.com/flex/3/html/compilers_13.html">mxmlc</a> command rather than using the <code>build.xml</code> file to do this.  I am using Ant 1.7, but I am not aware of any features I am using specific to that version.  Finally, I have my <code>ANT_HOME</code> environment variable set to my installation of Ant and have <code>%ANT_HOME%/bin</code> in my path for convenience in building.</li>
<p>
<li><a href="http://en.wikipedia.org/wiki/List_of_text_editors">Text Editor</a> or <a href="http://en.wikipedia.org/wiki/Comparison_of_integrated_development_environments">IDE</a> - You could use <a href="http://www.adobe.com/products/flex/features/flex_builder/">FlexBuilder</a>, but do not need to for the examples in this posting.  Other choices include <a href="http://www.netbeans.org/">NetBeans</a>, <a href="http://www.eclipse.org/">Eclipse</a>, <a href="http://www.oracle.com/technology/products/jdev/index.html">JDeveloper</a>, <a href="http://www.jetbrains.com/idea/">IDEA</a>, <a href="http://www.jedit.org/">JEdit</a>, <a href="http://spket.com/">SpketIDE</a>, <a href="http://www.vim.org/">vim</a>, <a href="http://www.gnu.org/software/emacs/">emacs</a>, and even <a href="http://en.wikipedia.org/wiki/Notepad">Notepad</a>/<a href="http://www.computerhope.com/jargon/w/wordpad.htm">Wordpad</a>.  If you do choose to use an IDE that supports XML, you can make things a little easier for yourself by associating MXML with XML as I demonstrate with <a href="http://marxsoftware.blogspot.com/2008/04/flex-and-openlaszlo-in-netbeans-61beta.html">NetBeans here</a> and with <a href="http://marxsoftware.blogspot.com/2008/03/using-jedit-with-openlaszlo-and-flex.html">JEdit here</a>.  Also, there are plug-ins for Flex for IDEs such as <a href="http://sourceforge.net/projects/flexbean">FlexBean for NetBeans</a>.  Also, it is my <a href="http://www.infoq.com/news/2008/04/intellij-idea-supports-flex">understanding</a> that <a href="http://blogs.jetbrains.com/idea/2008/02/creating-flex-applications-with-intellij-idea/">IDEA has built-in Flex support</a>.</li>
<p></ul>
<p>The following screen snapshot demonstrates the versions of these tools used as described above.</p>
<p><a href="http://1.bp.blogspot.com/_sDOe5HxTdMk/SV1Ft-dWX4I/AAAAAAAAA7c/OAd2RnnfE8I/s1600-h/blazesDS-remoting-tools-versions.png"></a></p>
<p><strong>Setting Up BlazeDS for the Application</strong></p>
<p>I won't go into any greater detail regarding installation of the Flex SDK, of the Java SDK, of a Java EE-compliant web server, of Ant, or of an IDE or text editor than that provided above.  However, I will briefly look a little closer at <a href="http://opensource.adobe.com/wiki/display/blazeds/Installation+Guide">installation of BlazeDS</a>.</p>
<p>BlazeDS is open source and its source can be downloaded <a href="http://opensource.adobe.com/wiki/display/blazeds/Source">here</a>, but the source code for BlazeDS is not needed for any of the examples in this blog posting.</p>
<p>The <a href="http://opensource.adobe.com/wiki/display/blazeds/Downloads">BlazeDS download page</a> includes <a href="http://opensource.adobe.com/wiki/display/blazeds/Release+Builds">release builds</a> and <a href="http://opensource.adobe.com/wiki/display/blazeds/download+blazeds+3">nightly builds</a>.  I am using a release build for the examples here.  BlazeDS 3.2 Release Build 3978 is available as of this writing and I am using BlazeDS 3.2 Release Build 3978 for these examples.</p>
<p>An advantage of using the Turnkey download is that Tomcat web server is included with it.  However, I intentionally want the examples in this posting to be "bare bones" and so will use a separate JEE implementation.  With the non-Turnkey binary BlazeDS release downloaded (it will be called something like <code>blazeds-bin-3.2.0.3978.zip</code>), "installation" simply involves unzipping the ZIP file and extracting the WAR file (<code>blazeds.war</code>) from it.  The next screen snapshot shows the contents of this binary BlazeDS download, including the WAR file just mentioned.</p>
<p><a href="http://3.bp.blogspot.com/_sDOe5HxTdMk/SV1NNK-rKhI/AAAAAAAAA7k/4-wsTjhC2NQ/s1600-h/blazeDS-downloadedZIP-contents.png"></a></p>
<p>With access to the <code>blazeds.war</code> file, we now need to expand the <code>blazeds.war</code>'s contents.  We have two choices here.  One popular choice is to expand this WAR file's contents in a web server's deployment directory.  Many web servers will then automatically deploy the contents of that expanded directory.  However, I will be taking the second approach here and will rebuild the WAR file for deployment with an Ant script.  This provides greater portability between web servers and allows me to show better what needs to be included in the server-side BlazeDS-powered WAR file via the <code>build.xml</code> file.  You should be able to use the direct deployment of expanded directory approach and not need Ant for the server-side if you prefer that approach.</p>
<p>The next screen snapshot shows the contents of the <code>blazeds.war</code> file that needs to be expanded.</p>
<p><a href="http://4.bp.blogspot.com/_sDOe5HxTdMk/SV1RYAXMegI/AAAAAAAAA7s/ZdMhdufSPFY/s1600-h/blazeDS-war-contents.png"></a></p>
<p>For my examples, I will be expanding the <code>blazeds.war</code> file's contents into the <code>C:\blazeDSRemotingExample</code>) directory.  I typically remove the META-INF directory and its contents from the expanded directory, so that it looks something like that shown in the next two screen snapshots.  Note that the red lines through directories in the first screen snapshot are intentional because the entries that they cross out will eventually be built up, but will not be there when <code>blazeds.war</code> is initially expanded (in other words, your newly expanded directory should only have the WEB-INF directory if you deleted the META-INF directory as I did).</p>
<p><a href="http://2.bp.blogspot.com/_sDOe5HxTdMk/SV1SAOM2IUI/AAAAAAAAA70/qDkF2gbHGAA/s1600-h/blazeDS-expanded-app-directory-edited-for-initial-appearance.png"></a></p>
<p><a href="http://3.bp.blogspot.com/_sDOe5HxTdMk/SV1UQlut0cI/AAAAAAAAA78/pHVZRm86t2c/s1600-h/blazeDS-expanded-webinf-contents-edited-original.png"></a></p>
<p>As the immediately preceding image shows, the expanded <code>blazeds.war</code> contents include some expected subdirectories beneath <code>WEB-INF</code> including <code>classes</code> and <code>lib</code>.  Because we will rebuild our server's WAR file with this same expanded directory structure, we already have the necessary directories we need for the web application's classpath.</p>
<p><strong>Tailoring BlazeDS Web Descriptor Configuration for Custom Application</strong></p>
<p>Up until now, we've merely unzipped the downloaded binary BlazeDS file and then expanded the <code>blazeds.war</code> file into a directory.  Now it is time to begin tweaking the configuration files included with the <code>blazeds.war</code> file to accommodate our application.</p>
<p>One of the first things I like to do when customizing my own BlazeDS-based application based on the provided <code>blazeds.war</code> file is to upgrade the web application descriptor file (<code>web.xml</code>) to reflect <a href="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">Servlet 2.5</a> rather than <a href="http://java.sun.com/dtd/web-app_2_3.dtd">Servlet 2.3</a>.  I provide more detail on this process in my blog entry on <a href="http://marxsoftware.blogspot.com/2007/10/openlaszlo-with-java-servlets-25-and.html">OpenLaszlo with Java Servlets 2.5</a> (<a href="http://www.openlaszlo.org/">OpenLaszlo</a> also provides an older <code>web.xml</code> file).  The most important changes to note are that the <a href="http://xmlfiles.com/dtd/dtd_intro.asp">DTD</a>-described file becomes <a href="http://www.w3.org/XML/Schema">W3C XML Schema</a> described instead, the version attribute is obviously updated from <a href="http://jcp.org/aboutJava/communityprocess/first/jsr053/index.html">2.3</a> to <a href="http://www.javaworld.com/javaworld/jw-01-2006/jw-0102-servlet.html">2.5</a>, and the <code>&amp;lt;display-name&amp;gt;</code> element is removed as a nested element under the <code>&amp;lt;servlet&amp;gt;</code> element.  This particular change of versions of the <code>web.xml</code> file is probably not absolutely necessary in this case because I'm not using Java EE 5 annotations, but I make the change every time anyway.</p>
<p>The less important changes that I make to the provided <code>web.xml</code> file include removal of commented out section specifically intended for <a href="http://www-01.ibm.com/software/websphere/">WebSphere</a> (which I'm not using here) and other comments.  The other change I make is to change the text for the high-level <code>&amp;lt;display-name&amp;gt;</code> and <code>&amp;lt;description&amp;gt;</code> elements.  Indeed, when I have completed the transformation, the new <code>web.xml</code> file still looks very similar to the one provided with the <code>blazeds.war</code> file.  Several of these changes are depicted in the next screen snapshot taken of a diff run against the two versions of <code>web.xml</code> using the <a href="http://www.prestosoft.com/ps.asp?page=edp_examdiff">ExamDiff</a> tool.</p>
<p><a href="http://1.bp.blogspot.com/_sDOe5HxTdMk/SV1YrH_JjqI/AAAAAAAAA8E/-XtWe9Hdp2E/s1600-h/blazeDS-web_xml-diff-top.png"></a></p>
<p>The new and customized <code>web.xml</code> file is shown next.</p>
<p><strong>New and Customized web.xml File</strong></p>
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"<br />         version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"&gt;<br />    &lt;display-name&gt;Dustin's BlazeDS Hello World Example&lt;/display-name&gt;<br />    &lt;description&gt;An extremely simple BlazeDS Remoting Application&lt;/description&gt;</p>
<p>    &lt;!-- Http Flex Session attribute and binding listener support --&gt;<br />    &lt;listener&gt;<br />        &lt;listener-class&gt;flex.messaging.HttpFlexSession&lt;/listener-class&gt;<br />    &lt;/listener&gt;</p>
<p>    &lt;!-- MessageBroker Servlet --&gt;<br />    &lt;servlet&gt;<br />        &lt;servlet-name&gt;MessageBrokerServlet&lt;/servlet-name&gt;<br />        &lt;servlet-class&gt;flex.messaging.MessageBrokerServlet&lt;/servlet-class&gt;<br />        &lt;init-param&gt;<br />            &lt;param-name&gt;services.configuration.file&lt;/param-name&gt;<br />            &lt;param-value&gt;/WEB-INF/flex/services-config.xml&lt;/param-value&gt;<br />       &lt;/init-param&gt;<br />        &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />    &lt;/servlet&gt;</p>
<p>    &lt;servlet-mapping&gt;<br />        &lt;servlet-name&gt;MessageBrokerServlet&lt;/servlet-name&gt;<br />        &lt;url-pattern&gt;/messagebroker/*&lt;/url-pattern&gt;<br />    &lt;/servlet-mapping&gt;</p>
<p>    &lt;welcome-file-list&gt;<br />        &lt;welcome-file&gt;index.html&lt;/welcome-file&gt;<br />        &lt;welcome-file&gt;index.htm&lt;/welcome-file&gt;<br />    &lt;/welcome-file-list&gt;</p>
<p>&lt;/web-app&gt;</p>
<p><strong>Customizing Other BlazeDS Configuration Files</strong></p>
<p>Besides the <code>classes</code> and <code>lib</code> subdirectories contained under <code>WEB-INF</code> in the directory expanded from the <code>blazeds.war</code> file, we also have subdirectories called <code>src</code> and <code>flex</code>.  We will not customize a couple XML files inside the <code>flex</code> directory to tailor BlazeDS for our application's use.</p>
<p>The first file we'll look at is called <code>services-config.xml</code>.  This file is central to all BlazeDS-based applications whether they are based on <a href="http://livedocs.adobe.com/blazeds/1/blazeds_devguide/help.html?content=Part_RPC_1.html">RPC</a> or <a href="http://livedocs.adobe.com/blazeds/1/blazeds_devguide/Part_Flex_Messaging_1.html">messaging</a>.  In fact, among other things, this file usually imports additional configuration files for things that are specific to proxying, to remoting, and to messaging.</p>
<p>I use the same approach with <code>services-config.xml</code> that I used with <code>web.xml</code>: I adapt the version provided by <code>blazeds.war</code> to work for the custom application.  However, there is a twist in this one case.  I want to have a slightly different version of this file for my Flex client than I have for my WAR that gets deployed on the server.  Keeping the <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY principle</a> in mind, my approach here is to create a <code>services-config-template.xml</code> file and use Ant's <a href="http://www.javalobby.org/articles/ant-preprocessor/">text substitution functionality</a> to automatically generate the <code>services-config.xml</code> file to be used by both the Flex client and by the WAR that is deployed to the server.  The next code listing shows the template file, which I placed in a newly created directory creatively called "templates".</p>
<p><strong>templates/services-config-template.xml</strong></p>
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;services-config&gt;</p>
<p>    &lt;services&gt;<br />        &lt;service-include file-path="remoting-config.xml" /&gt;<br />        &lt;service-include file-path="proxy-config.xml" /&gt;<br />        &lt;service-include file-path="messaging-config.xml" /&gt;        <br />    &lt;/services&gt;</p>
<p>    &lt;security&gt;<br />        &lt;login-command class="flex.messaging.security.TomcatLoginCommand" server="Tomcat"/&gt;<br />    &lt;/security&gt;</p>
<p>    &lt;channels&gt;<br />        &lt;channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel"&gt;<br />            &lt;endpoint url="http://@host@:@port@/{context.root}/messagebroker/amf"<br />                      class="flex.messaging.endpoints.AMFEndpoint"/&gt;<br />        &lt;/channel-definition&gt;<br />        &lt;channel-definition id="my-secure-amf" class="mx.messaging.channels.SecureAMFChannel"&gt;<br />            &lt;endpoint url="https://@host@:@port@/{context.root}/messagebroker/amfsecure"<br />                      class="flex.messaging.endpoints.SecureAMFEndpoint"/&gt;<br />            &lt;properties&gt;<br />                &lt;add-no-cache-headers&gt;false&lt;/add-no-cache-headers&gt;<br />            &lt;/properties&gt;<br />        &lt;/channel-definition&gt;</p>
<p>        &lt;channel-definition id="my-polling-amf" class="mx.messaging.channels.AMFChannel"&gt;<br />            &lt;endpoint url="http://@host@:@port@/{context.root}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/&gt;<br />            &lt;properties&gt;<br />                &lt;polling-enabled&gt;true&lt;/polling-enabled&gt;<br />                &lt;polling-interval-seconds&gt;4&lt;/polling-interval-seconds&gt;<br />            &lt;/properties&gt;<br />        &lt;/channel-definition&gt;<br />    &lt;/channels&gt;</p>
<p>    &lt;logging&gt;<br />        &lt;target class="flex.messaging.log.ConsoleTarget" level="Error"&gt;<br />            &lt;properties&gt;<br />                &lt;prefix&gt;[BlazeDS] &lt;/prefix&gt;<br />                &lt;includeDate&gt;false&lt;/includeDate&gt;<br />                &lt;includeTime&gt;false&lt;/includeTime&gt;<br />                &lt;includeLevel&gt;false&lt;/includeLevel&gt;<br />                &lt;includeCategory&gt;false&lt;/includeCategory&gt;<br />            &lt;/properties&gt;<br />            &lt;filters&gt;<br />                &lt;pattern&gt;Endpoint.*&lt;/pattern&gt;<br />                &lt;pattern&gt;Service.*&lt;/pattern&gt;<br />                &lt;pattern&gt;Configuration&lt;/pattern&gt;<br />            &lt;/filters&gt;<br />        &lt;/target&gt;<br />    &lt;/logging&gt;</p>
<p>    &lt;system&gt;<br />        &lt;redeploy&gt;<br />            &lt;enabled&gt;false&lt;/enabled&gt;<br />        &lt;/redeploy&gt;<br />    &lt;/system&gt;</p>
<p>&lt;/services-config&gt;</p>
<p>The code for the template version of <code>services-config-template.xml</code> shown immediately above includes Ant token markers (<code>@host@</code> and <code>@port@</code>) that will be replaced by Ant with an actual host name and a port number <em>for the client's version of <code>services-config.xml</code>)</em>.  These same tokens will be replaced with BlazeDS-recognized tokens <code>{server.name}</code> and <code>{server.port}</code> for the server-side version of <code>services-config.xml</code>.  Note that I was able to leave the BlazeDS template <code>{context.root}</code> in the template for the client-side version of <code>services-config.xml</code> because the <a href="http://livedocs.adobe.com/blazeds/1/blazeds_devguide/build_apps_4.html#169258">mxmlc compiler</a> allows me to specify its value for the client as an option.</p>
<p>I left the reference in <code>services-config.xml</code> to all three previously referenced files (<code>remoting-config.xml</code>, <code>proxy-config.xml</code>, and <code>messaging-config.xml</code>), but really only need the reference to <code>remoting-config.xml</code> for this blog post examples.  As with the <code>web.xml</code> file, my approach to creation of that referenced <code>remoting-config.xml</code> file is to simply adapt the one provided with the expanded <code>blazeds.war</code> file.  The only necessary change is to specify the Java classes that will be used on the server side.  We haven't looked at this Java class yet, but the <code>remoting-config.xml</code> file shown in the next code listing tips us off that it will be a class named <code>HelloWorldRemotingServer</code> in a package named <code>dustin</code>.</p>
<p><strong>remoting-config.xml</strong></p>
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;service id="remoting-service" <br />         class="flex.messaging.services.RemotingService"&gt;</p>
<p>    &lt;adapters&gt;<br />        &lt;adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/&gt;<br />    &lt;/adapters&gt;</p>
<p>    &lt;default-channels&gt;<br />        &lt;channel ref="my-amf"/&gt;<br />    &lt;/default-channels&gt;</p>
<p>   &lt;destination id="HelloWorld"&gt;<br />      &lt;properties&gt;<br />         &lt;source&gt;dustin.HelloWorldRemotingServer&lt;/source&gt;<br />      &lt;/properties&gt;<br />   &lt;/destination&gt;<br />&lt;/service&gt;</p>
<p>The above <code>remoting-config.xml</code> file specifies that the <a href="http://livedocs.adobe.com/blazeds/1/blazeds_devguide/rpc_remoteobject_3.html">destination</a> associated with this Java class on the server side can be referenced as "HelloWorld" (the 'id' attribute of the <code>destination</code> element).</p>
<p>Whew!  That wraps up the BlazeDS configuration modifications.  If you have not looked into this before, it looks worse than it really is.  Most of the final content shown in the code listings above was already provided by the <code>blazeds.war</code> that we expanded.  I only made some relatively small modifications to the <code>web.xml</code> and <code>remoting-config.xml</code> files.  The <code>services-config.xml</code> file likewise only required some minor changes, but the more significant issue there was that I needed to prepare a different version of this file for the client than for the server.  The server version of <code>services-config.xml</code> can resolve the BlazeDS tokens <code>{host.name}</code> and <code>{host.port}</code> based on the web server settings, but I specify a hard-coded host name and port for the client version of <code>services-config.xml</code>.</p>
<p><strong>The Java Class</strong></p>
<p>The contents of the <code>remoting-config.xml</code> file provided us with a sneak peek at some details about the Java class on the server.  The definition of this simple Java class is shown next.  Note that this file is placed in a subdirectory called <code>dustin</code> (because it is in the "dustin" Java package) under the <code>src</code> subdirectory under <code>WEB-INF</code> in our expanded directory.</p>
<p><strong>HelloWorldRemotingServer.java (1st Version)</strong></p>
<p>package dustin;</p>
<p>/**<br /> * Simple "Hello World" example meant for use in BlazeDS remoting example.<br /> * This is the server-side POJO that will be exposed to a Flex client via<br /> * BlazeDS remoting.<br /> * <br /> * @author Dustin<br /> */<br />public class HelloWorldRemotingServer<br />{<br />   /** No-arguments constructor. */<br />   public HelloWorldRemotingServer() {}</p>
<p>   /**<br />    * Accept a String representing a name and return that name as part of a<br />    * Hello message.<br />    *<br />    * @param nameToSayHelloTo Name to which Hello will be addressed.<br />    * @return Hello address to provided name.<br />    */<br />   public String processHello(final String nameToSayHelloTo)<br />   {<br />      return "Hello, " + nameToSayHelloTo + "!";<br />   }<br />}</p>
<p>The important thing to note from the code listing for the Java class immediately above is that it is a <a href="http://www.martinfowler.com/bliki/POJO.html">regular Java class</a> with no knowledge of Flex or <a href="http://www.adobe.com/devnet/actionscript/">ActionScript</a>.</p>
<p><strong>The Flex Client (Hello World Client)</strong></p>
<p>The Java class we just looked at returns a provided String surrounded with a <a href="http://www.javacoffeebreak.com/java101/java101.html">Hello World</a> prefix and exclamation point.  We'll now look at the Flex MXML code that can be used to invoke this Java object and this <code>processHello(String)</code> method via BlazeDS.</p>
<p><strong>HelloWorldRemotingClient.mxml</strong></p>
<p>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br />&lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"<br />                width="1100" height="700"&gt;</p>
<p>   &lt;!-- Associate client with BlazeDS destination via RemoteObject. --&gt;<br />   &lt;mx:RemoteObject id="remoteObject" destination="HelloWorld" /&gt;</p>
<p>   &lt;mx:Panel id="mainPanel" title="Simple BlazeDS Remoting Example - Hello World"&gt;<br />      &lt;mx:Form&gt;<br />         &lt;mx:FormItem label="Provide Your Name"&gt;<br />            &lt;mx:TextInput id="textInput"<br />                          change="remoteObject.processHello(textInput.text)"/&gt;<br />         &lt;/mx:FormItem&gt;<br />         &lt;mx:FormItem label="Server's Response"&gt;<br />            &lt;mx:Label text="{remoteObject.processHello.lastResult}"/&gt;<br />         &lt;/mx:FormItem&gt;<br />      &lt;/mx:Form&gt;<br />   &lt;/mx:Panel&gt;<br />&lt;/mx:Application&gt;</p>
<p>The MXML code above is very simple.  The <a href="http://livedocs.adobe.com/blazeds/1/blazeds_devguide/rpc_remoteobject_2.html">RemoteObject</a> <a href="http://livedocs.adobe.com/flex/3/langref/mx/rpc/remoting/mxml/RemoteObject.html">element</a> (with an 'id' of "remoteObject") specifies a <a href="http://livedocs.adobe.com/blazeds/1/blazeds_devguide/rpc_remoteobject_3.html">destination</a> (via the 'destination' attribute) of "HelloWorld" (defined above in the <code>remoting-config.xml</code> file).</p>
<p>If you plan to use the <code>build.xml</code> file provided in this blog posting, this MXML file should be placed at parallel to the <code>WEB-INF</code> directory (as opposed to in the <code>WEB-INF</code> directory like the Java class and configuration files previously discussed).</p>
<p><strong>Building it All</strong></p>
<p>Even though I still need to show another Flex client, an ActionScript class, and another Java class whose instantiation is bound to the ActionScript class's instantiation, I am including the entire Ant <code>build.xml</code> file here for convenience.  Some of the targets defined in this file will not work until the remaining classes discussed later in this blog posting are included.</p>
<p><strong>build.xml (Ant)</strong></p>
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;project name="HelloWorldBlazeDSRemotingExample" default="all" basedir="."&gt;<br />   &lt;description&gt;Builds, tests, and runs the Dustin's Hello World BlazeDS Remoting Example.&lt;/description&gt;</p>
<p>   &lt;!-- NOTE TO USERS: At least three properties set below may need to be<br />                       set for this build file to work with different deployment<br />                       environments.  The three minimum properties to examine<br />                       are client.host, client.port, and app.dir.<br />   --&gt;</p>
<p>   &lt;!-- GENERAL PROPERTIES --&gt;<br />   &lt;!--<br />        *********************************************************************<br />        Change server's host name and port (determined by web server<br />        deployment of server side of code).<br />        *********************************************************************<br />   --&gt;<br />   &lt;property name="client.host" value="localhost" /&gt;<br />   &lt;property name="client.port" value="8080" /&gt;<br />   &lt;!--<br />        *********************************************************************<br />        Change definition of app.dir if necessary (to where blazeds.war<br />               has been uncompressed).<br />        *********************************************************************<br />   --&gt;<br />   &lt;property name="app.dir" value="C:\\blazeDSRemotingExample" /&gt;<br />   &lt;property name="web.inf.dir" value="${app.dir}/WEB-INF" /&gt;<br />   &lt;property name="templates.dir" value="${app.dir}/templates" /&gt;<br />   &lt;property name="context.name" value="HelloWorldRemotingServer" /&gt;</p>
<p>   &lt;!-- GENERAL JAVA PORTION PROPERTIES --&gt;<br />   &lt;property name="src.dir" value="${web.inf.dir}/src" /&gt;<br />   &lt;property name="classes.dir" value="${web.inf.dir}/classes" /&gt;<br />   &lt;property name="lib.dir" value="lib" /&gt;<br />   &lt;property name="dist.dir" value="${app.dir}/dist" /&gt;<br />   &lt;property name="javadoc.dir" value="${dist.dir}/javadoc" /&gt;<br />   &lt;property name="serverside.war" value="${context.name}.war" /&gt;</p>
<p>   &lt;!-- Nothing special needed for classpath! --&gt;<br />   &lt;path id="classpath" /&gt;</p>
<p>   &lt;!-- BLAZEDS RELATED PROPERTIES --&gt;<br />   &lt;property name="services.config.server.name"<br />             value="services-config.xml" /&gt;<br />   &lt;property name="services.config.client.name"<br />             value="services-config-client.xml" /&gt;<br />   &lt;property name="services.config.template"<br />             value="services-config-template.xml" /&gt;</p>
<p>   &lt;!-- GENERAL FLEX PORTION PROPERTIES (FLEX CLIENT) --&gt;<br />   &lt;property name="app.flex.dir" value="${web.inf.dir}/flex" /&gt;<br />   &lt;property name="flex.debug" value="true" /&gt;<br />   &lt;property name="flex.warnings" value="true" /&gt;<br />   &lt;property name="flex.context.root" value="${context.name}" /&gt;<br />   &lt;property name="flex.services"<br />             value="${app.flex.dir}/${services.config.client.name}" /&gt;<br />   &lt;property name="flex.source.path" value="${web.inf.dir}" /&gt;<br />   &lt;property name="flex.publisher" value="Dustin" /&gt;<br />   &lt;property name="flex.title"<br />             value="'Hello World BlazeDS Remoting Example'" /&gt;<br />   &lt;property name="flex.description"<br />             value="'Simple client for BlazeDS Remoting example'" /&gt;<br />   &lt;property name="flex.verbose.stacktraces" value="true" /&gt;<br />   &lt;property name="flex.actionscript.warnings" value="true" /&gt;<br />   &lt;property name="flex.app.helloworld.name.root"<br />             value="HelloWorldRemotingClient" /&gt;<br />   &lt;property name="flex.app.helloworld.name.source"<br />             value="${flex.app.helloworld.name.root}.mxml" /&gt;<br />   &lt;property name="flex.app.helloworld.name.swf"<br />             value="${flex.app.helloworld.name.root}.swf" /&gt;<br />   &lt;property name="flex.app.complexobject.name.root"<br />             value="ComplexObjectRemotingClient" /&gt;<br />   &lt;property name="flex.app.complexobject.name.source"<br />             value="${flex.app.complexobject.name.root}.mxml" /&gt;<br />   &lt;property name="flex.app.complexobject.name.swf"<br />             value="${flex.app.complexobject.name.root}.swf" /&gt;</p>
<p>   &lt;target name="-init"&gt;<br />      &lt;mkdir dir="${dist.dir}" /&gt;<br />      &lt;mkdir dir="${javadoc.dir}" /&gt;<br />   &lt;/target&gt;</p>
<p>   &lt;target name="-copy-respective-services-config-files"<br />           depends="-clean-generated-blazeds-config-files"&gt;<br />      &lt;copy file="${templates.dir}/${services.config.template}"<br />            tofile="${app.flex.dir}/${services.config.server.name}" &gt;<br />         &lt;filterchain&gt;<br />            &lt;replacetokens&gt;<br />               &lt;token key="host" value="{server.name}"/&gt;<br />               &lt;token key="port" value="{server.port}"/&gt;<br />            &lt;/replacetokens&gt;<br />         &lt;/filterchain&gt;<br />      &lt;/copy&gt;<br />      &lt;copy file="${templates.dir}/${services.config.template}"<br />            tofile="${app.flex.dir}/${services.config.client.name}" &gt;<br />         &lt;filterchain&gt;<br />            &lt;replacetokens&gt;<br />               &lt;token key="host" value="${client.host}"/&gt;<br />               &lt;token key="port" value="${client.port}"/&gt;<br />            &lt;/replacetokens&gt;<br />         &lt;/filterchain&gt;<br />      &lt;/copy&gt;<br />   &lt;/target&gt;</p>
<p>   &lt;target name="compile"<br />           depends="compileJavaBasedServer, compileFlexBasedClients"<br />           description="Compile Java and Flex code." /&gt;</p>
<p>   &lt;target name="compileJavaBasedServer"<br />           description="Compile Java source code used for server side."&gt;<br />      &lt;javac srcdir="${src.dir}"<br />             destdir="${classes.dir}"<br />             classpathref="classpath" /&gt;<br />   &lt;/target&gt;</p>
<p>   &lt;target name="compileFlexBasedClients"<br />           description="Compile the Flex clients"<br />           depends="compileFlexBasedHelloWorldClient,<br />                    compileFlexBasedComplexObjectClient" /&gt;</p>
<p>   &lt;target name="compileFlexBasedHelloWorldClient"  <br />           description="Compile Flex Hello World client application into SWF file."&gt;  <br />      &lt;exec executable="mxmlc"&gt;<br />         &lt;arg line="-debug=${flex.debug}" /&gt;  <br />         &lt;arg line="-context-root=${flex.context.root}" /&gt;  <br />         &lt;arg line="-services=${flex.services}" /&gt;<br />         &lt;arg line="-warnings=${flex.warnings}" /&gt;<br />         &lt;arg line="-publisher=${flex.publisher}" /&gt;  <br />         &lt;arg line="-title=${flex.title}" /&gt;  <br />         &lt;arg line="-description=${flex.description}" /&gt;<br />         &lt;arg line="-verbose-stacktraces=${flex.verbose.stacktraces}" /&gt;<br />         &lt;arg line="-show-actionscript-warnings=${flex.actionscript.warnings}" /&gt;<br />         &lt;arg line="-output ${dist.dir}/${flex.app.helloworld.name.swf}" /&gt;<br />         &lt;arg line="-- ${flex.app.helloworld.name.source}" /&gt;<br />      &lt;/exec&gt;  <br />   &lt;/target&gt;</p>
<p>   &lt;target name="compileFlexBasedComplexObjectClient"  <br />           description="Compile Flex Complex Object client application into SWF file."&gt;  <br />      &lt;exec executable="mxmlc"&gt;<br />         &lt;arg line="-debug=${flex.debug}" /&gt;  <br />         &lt;arg line="-context-root=${flex.context.root}" /&gt;  <br />         &lt;arg line="-services=${flex.services}" /&gt;<br />         &lt;arg line="-warnings=${flex.warnings}" /&gt;<br />         &lt;arg line="-publisher=${flex.publisher}" /&gt;  <br />         &lt;arg line="-title=${flex.title}" /&gt;  <br />         &lt;arg line="-description=${flex.description}" /&gt;<br />         &lt;arg line="-verbose-stacktraces=${flex.verbose.stacktraces}" /&gt;<br />         &lt;arg line="-show-actionscript-warnings=${flex.actionscript.warnings}" /&gt;<br />         &lt;arg line="-output ${dist.dir}/${flex.app.complexobject.name.swf}" /&gt;<br />         &lt;arg line="-- ${flex.app.complexobject.name.source}" /&gt;<br />      &lt;/exec&gt;  <br />   &lt;/target&gt;</p>
<p>   &lt;target name="war"<br />           description="Build server's web application archive (WAR)."<br />           depends="-init,<br />                    -copy-respective-services-config-files,<br />                    compileJavaBasedServer"&gt;<br />      &lt;war webxml="${web.inf.dir}/web.xml"<br />           destfile="${dist.dir}/${serverside.war}"<br />           filesonly="true"&gt;<br />         &lt;zipfileset dir="${web.inf.dir}"<br />                     excludes="web.xml<br />                               flex/${services.config.client.name}"<br />                     prefix="WEB-INF" /&gt;<br />      &lt;/war&gt;<br />   &lt;/target&gt;</p>
<p>   &lt;target name="all" depends="war, compileFlexBasedClients"<br />           description="Build it all; the default target." /&gt;</p>
<p>   &lt;target name="clean" description="Remove generated files."<br />           depends="-clean-generated-blazeds-config-files"&gt;<br />      &lt;delete dir="${dist.dir}" /&gt;<br />      &lt;delete dir="${classes.dir}/dustin" /&gt;<br />   &lt;/target&gt;</p>
<p>   &lt;target name="-clean-generated-blazeds-config-files"&gt;<br />      &lt;delete file="${app.flex.dir}/${services.config.server.name}"<br />              quiet="true" /&gt;<br />      &lt;delete file="${app.flex.dir}/${services.config.client.name}"<br />              quiet="true"/&gt;<br />   &lt;/target&gt;</p>
<p>   &lt;target name="javadoc" description="Generate Javadoc-based documentation"&gt;<br />      &lt;javadoc doctitle="Dustin's Spring BlazeDS Integration Example"<br />               destdir="${javadoc.dir}"<br />               sourcepath="${src.dir}"<br />               classpathref="classpath"<br />               private="true"<br />               author="Dustin" /&gt;<br />   &lt;/target&gt;</p>
<p>&lt;/project&gt;</p>
<p>In the above <code>build.xml</code> file, there are three properties defined near the top that would most likely need to be changed for a different deployment environment.  They are <code>client.host</code>, <code>client.port</code>, and <code>app.dir</code>.  The first two are used to appropriately build the client's version of <code>services-config.xml</code> to reference the host and port on which the server BlazeDS-powered application will be running.  Because I am using GlassFish defaults for my server, I define these properties respectively to <code>localhost</code> and <code>8080</code>.  The third property, <code>app.dir</code> defines the directory into which I expanded the contents of the <code>blazeds.war</code> file for editing.</p>
<p>Targets of specific interest in the above <code>build.xml</code> file include the <code>compileFlexBasedHelloWorldClient</code> target for building the Flex client with the mxmlc compiler and the <code>war</code> target for building the WAR file to be deployed on the server.</p>
<p>When I build the WAR and the client SWF file (same name as its source MXML file but with an .swf extension rather than the .mxml extension), I can then deploy the WAR and run the SWF client.  The deployment of the WAR file is done with whatever mechanism your web serve provides.  The SWF client can easily be executed by clicking on it or typing its full name on the command line.  The following two screen snapshots show the client running by first showing how it initially appears and then showing how it appears once a name has been entered into the name field.</p>
<p><a href="http://2.bp.blogspot.com/_sDOe5HxTdMk/SV1tgV9VnRI/AAAAAAAAA8M/SKvp6xacxyA/s1600-h/blazeDS-remoting-helloWorld-initial.png"></a></p>
<p><a href="http://4.bp.blogspot.com/_sDOe5HxTdMk/SV1tmjkG_9I/AAAAAAAAA8U/o-uKwc40xyo/s1600-h/blazeDS-remoting-helloWorld-populated.png"></a></p>
<p><strong>Binding Java to ActionScript</strong></p>
<p>The above example demonstrates the ability to remotely call Java on the server from MXML on the client via the <a href="http://livedocs.adobe.com/flex/3/langref/mx/rpc/remoting/mxml/RemoteObject.html">RemoteObject</a> and BlazeDS.  However, the example up to this point has only used simple mappings (in this case Strings).  It is more interesting to now move onto an example of binding a more complex objects.  The good news is that it is all still pretty easy.</p>
<p>For this slightly more complex example, we will expand the <code>HelloWorldRemotingServer</code> class to feature a method that accepts a domain object that is neither a primitive, a boxed version of a primitive, or a String.  The revised version of <code>HelloWorldRemotingServer</code> is shown next:</p>
<p><strong>HelloWorldRemotingServer.java (Finished Version)</strong></p>
<p>package dustin;</p>
<p>/**<br /> * Simple "Hello World" example meant for use in BlazeDS remoting example.<br /> * This is the server-side POJO that will be exposed to a Flex client via<br /> * BlazeDS remoting.<br /> * <br /> * @author Dustin<br /> */<br />public class HelloWorldRemotingServer<br />{<br />   /** No-arguments constructor. */<br />   public HelloWorldRemotingServer() {}</p>
<p>   /**<br />    * Accept a String representing a name and return that name as part of a<br />    * Hello message.<br />    *<br />    * @param nameToSayHelloTo Name to which Hello will be addressed.<br />    * @return Hello address to provided name.<br />    */<br />   public String processHello(final String nameToSayHelloTo)<br />   {<br />      return "Hello, " + nameToSayHelloTo + "!";<br />   }</p>
<p>   /**<br />    * Accept a last name and a first name and return the concatendated name as<br />    * part of a James Bond like introduction.<br />    * <br />    * @param firstName Provided first name of person.<br />    * @param lastName Provided last name of person.<br />    * @return The James Bond like introductory message.<br />    */<br />   public String processName(final String firstName, final String lastName)<br />   {<br />      return "Your name is " + lastName + ". " + firstName + " " + lastName + ".";<br />   }</p>
<p>   /**<br />    * Accept a Person and return that person's name as part of a James Bond like<br />    * introduction.<br />    * <br />    * @param person Person whose name will be returned.<br />    * @return The James Bond like introductory message.<br />    */<br />   public String processName(final Person person)<br />   {<br />      return  "Your name is " + person.getLastName() + ". "<br />             + person.getFirstName() + " " + person.getLastName() + "!";<br />   }<br />}</p>
<p>One of the newly added methods is called <code>processName(String,String)</code>.  This wouldn't make a very exciting example because it still uses two separate Strings.  The more interesting example will be <a href="http://livedocs.adobe.com/flex/3/html/data_access_4.html">binding</a> a Flex client to the <code>processName(Person)</code> method that expects a <code>Person</code> instance.  For our newly updated class to compile, we need to define a <code>Person</code> class in the same package.  That is shown next:</p>
<p><strong>Person.java</strong></p>
<p>package dustin;</p>
<p>/**<br /> * Encapsulates a person's information.<br /> * <br /> * @author Dustin<br /> */<br />public class Person<br />{<br />   /** Last name of person. */<br />   private String lastName;</p>
<p>   /** First name of person. */<br />   private String firstName;</p>
<p>   /** No-arguments constructor. */<br />   public Person() {}</p>
<p>   /**<br />    * Constructor accepting names for this person.<br />    * <br />    * @param newLastName Last name of the person.<br />    * @param newFirstName First name of the person.<br />    */<br />   public Person(final String newLastName,<br />                 final String newFirstName,<br />                 final int newAge)<br />   {<br />      this.lastName = newLastName;<br />      this.firstName = newFirstName;<br />   }</p>
<p>   /**<br />    * Provide person's first name.<br />    * <br />    * @return Person's first name.<br />    */<br />   public String getFirstName()<br />   {<br />      return this.firstName;<br />   }</p>
<p>   /**<br />    * Set/change the person's first name.<br />    * <br />    * @param newFirstName New first name for the person.<br />    */<br />   public void setFirstName(final String newFirstName)<br />   {<br />      this.firstName = newFirstName;<br />   }</p>
<p>   /**<br />    * Provide person's last name.<br />    * <br />    * @return Person's last name.<br />    */<br />   public String getLastName()<br />   {<br />      return this.lastName;<br />   }</p>
<p>   /**<br />    * Set/change person's last name.<br />    * <br />    * @param newLastName New last name for person.<br />    */<br />   public void setLastName(final String newLastName)<br />   {<br />      this.lastName = newLastName;<br />   }</p>
<p>   /**<br />    * String representation of me.<br />    * <br />    * @return My String representation.<br />    */<br />   @Override<br />   public String toString()<br />   {<br />      return this.firstName + " " + this.lastName;<br />   }<br />}</p>
<p>There is nothing remarkable about the <code>Person</code> class and there is no sign of any association with ActionScript or Flex in this Java class.  In fact, the <code>Person</code> class is downright boring.</p>
<p>For Strings, primitives, and object/boxed versions of primitives, BlazeDS can typically map these types to appropriate ActionScript types.  Now that we've introduced the <code>Person</code> type, however, we need to <a href="http://livedocs.adobe.com/blazeds/1/blazeds_devguide/serialize_data_3.html">instruct BlazeDS</a> how to use this Java class on the Flex-based client side.  This is easily done by simply creating a parallel <code>Person</code> class in ActionScript that explicitly associates itself with the Java version of <code>Person</code>.  The code for the ActionScript version of <code>Person</code> is shown next.</p>
<p><strong>Person.as</strong></p>
<p>package dustin<br />{<br />   [Bindable]<br />   [RemoteClass(alias="dustin.Person")]<br />   public class Person<br />   {<br />      /** First name of person. */<br />      private var _firstName:String;</p>
<p>      /** Last name of person. */<br />      private var _lastName:String;</p>
<p>      /**<br />       * Constructor accepting names of this newly instantiated person.<br />       * Because each parameter has a default of null, this can be used as a<br />       * no-arguments constructor.<br />       *<br />       * @param newFirstName First name to be used for this person.<br />       * @param newLastName Last name to be used for this person.<br />       */<br />      public function Person(<br />         newFirstName:String = null,<br />         newLastName:String = null)<br />      {<br />         _firstName = newFirstName;<br />         _lastName = newLastName;<br />      }</p>
<p>      /**<br />       * WRITE (set/change) firstName property.<br />       *<br />       * @param newFirstName New first name.<br />       */<br />      public function set firstName(newFirstName:String):void<br />      {<br />         _firstName = newFirstName;<br />      }</p>
<p>      /**<br />       * READ firstName property.<br />       *<br />       * @return My first name.<br />       */<br />      public function get firstName():String<br />      {<br />         return _firstName;<br />      }</p>
<p>      /**<br />       * WRITE (set/change) lastName property.<br />       *<br />       * @param newLastName new last name.<br />       */<br />      public function set lastName(newLastName:String):void<br />      {<br />         _lastName = newLastName;<br />      }</p>
<p>      /**<br />       * READ lastName property.<br />       *<br />       * @return My last name.<br />       */<br />      public function get lastName():String<br />      {<br />         return _lastName;<br />      }<br />   }<br />}</p>
<p>Arguably the most interesting point about the ActionScript version of <code>Person</code> is the use of RemoteClass metadata tag (<code>[RemoteClass(alias=&quot;dustin.Person&quot;)]</code>) to explicitly associate this ActionScript class with the Java class.  By naming the property write/set and read/get methods to match those in the Java class, the remaining binding of ActionScript object to Java object is handled by BlazeDS.</p>
<p>The ActionScript <code>Person.as</code> file should be placed in a newly created subdirectory named <code>dustin</code> (for the "dustin" package) parallel to the WEB-INF directory.  We now need to move onto building a new Flex client to use this new method on the server-side.</p>
<p>I want to make one final observation regarding the <code>Person</code> class in ActionScript.  The code would have been even more concise if I had made the data members public.  In that case, they could be accessed directly and the set and get methods would not be necessary.  Many of the online examples take this approach.</p>
<p><strong>A New Flex Client (Complex Object Client)</strong></p>
<p>The code for <code>ComplexObjectRemotingClient.mxml</code> is shown next.  It should be placed in the same location as our previous Flex client (in expanded directory and parallel to the <code>WEB-INF</code> subdirectory).</p>
<p><strong>ComplexObjectRemotingClient.mxml</strong></p>
<p>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br />&lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"<br />                width="1100" height="700"&gt;</p>
<p>   &lt;mx:Script&gt;<br />   import dustin.Person;</p>
<p>   /**<br />    * Prepare provided name information and send to server.<br />    *<br />    * @param firstName First name of person.<br />    * @param lastName Last name of person.<br />    */<br />   public function processAndSubmitName(firstName:String, lastName:String):void<br />   {<br />      const person:Person = new Person(firstName, lastName);<br />      remoteObject.processName(person);<br />   }<br />   &lt;/mx:Script&gt;</p>
<p>   &lt;!-- Associate client with BlazeDS destination via RemoteObject. --&gt;<br />   &lt;mx:RemoteObject id="remoteObject" destination="HelloWorld" /&gt;</p>
<p>   &lt;mx:Panel id="mainPanel" title="BlazeDS Remoting Example - Complex Object Mapping"&gt;<br />      &lt;mx:Form&gt;<br />         &lt;mx:FormItem label="Your First Name"&gt;<br />            &lt;mx:TextInput id="firstNameInput" /&gt;<br />         &lt;/mx:FormItem&gt;<br />         &lt;mx:FormItem label="Your Last Name"&gt;<br />            &lt;mx:TextInput id="lastNameInput" /&gt;<br />         &lt;/mx:FormItem&gt;<br />         &lt;mx:FormItem&gt;<br />            &lt;mx:Button label="Submit Name!"<br />                       click="processAndSubmitName(firstNameInput.text, lastNameInput.text);" /&gt;<br />         &lt;/mx:FormItem&gt;<br />         &lt;mx:FormItem label="Server's Response"&gt;<br />            &lt;mx:Label text="{remoteObject.processName.lastResult}" /&gt;<br />         &lt;/mx:FormItem&gt;<br />      &lt;/mx:Form&gt;<br />   &lt;/mx:Panel&gt;<br />&lt;/mx:Application&gt;</p>
<p>The new Flex client uses a little ActionScript to prepare the call to the server and instantiates one of our newly written <code>Person</code> objects in the process.  The <code>build.xml</code> file shown previously already included the target for building this new client ("compileFlexBasedComplexObjectClient").  Note that the Java code also needs to be rebuilt and the WAR reassembled and redeployed to the web server because of the addition of methods to the server class.</p>
<p>The following two screen snapshots show the initial and final state of the new client when it is executed as the Hello World client was earlier. </p>
<p><a href="http://4.bp.blogspot.com/_sDOe5HxTdMk/SV17uHIg1VI/AAAAAAAAA8c/i1uWo3L178E/s1600-h/blazeDS-remoting-complexObject-initial.png"></a></p>
<p><a href="http://3.bp.blogspot.com/_sDOe5HxTdMk/SV170hJhGdI/AAAAAAAAA8k/YyvokEzJ7to/s1600-h/blazeDS-remoting-complexObject-populated.png"></a></p>
<p>As the above output shows, the method accepting a Person object (note the exclamation point in the returned message) has been contacted on the Java side from a remote Flex client.</p>
<p><strong>Pictorial Overview of Directory/File Structure</strong></p>
<p>One of the things that can be a little tricky about using BlazeDS or the mxmlc compiler if you have very little experience using them is the placement of files.  Fortunately, most of this was already setup correctly by the <code>blazeds.war</code> file that we expanded.  However, I did add some directories and files.  In an effort to make it more clear where these directories and files are in relation to one another, I include the next screen snapshot of my final directory structure.  I tried in the text above to describe where within these various directories each file should go.</p>
<p><a href="http://2.bp.blogspot.com/_sDOe5HxTdMk/SV2A1fj1MKI/AAAAAAAAA8s/UTY5PByqUJ4/s1600-h/blazeDS-remoting-directory-structure-described.png"></a></p>
<p>The image above shows where to place MXML source files, ActionScript source files, and Java source files for the <code>build.xml</code> file described above to work properly.  I did not provide descriptions of the <code>nbproject</code> subdirectory (used for NetBeans specifically), the <code>images</code> subdirectory (used to store the screen snapshots shown in this blog posting), or the <code>WEB-INF</code> subdirectory (it was provided by the expanding of <code>blazeds.war</code>).  The only thing to note here is that I added the Java source code files (but not ActionScript source code files) into the <code>src</code> directory under <code>WEB-INF</code>.</p>
<p><strong>Conclusion</strong></p>
<p>This has turned out to be a rather lengthy blog entry.  However, this is to be expected considering that I've intentionally tried to make this a complete and thorough introduction to BlazeDS/Java remoting and because I have included the code directly within the blog posting rather than as a separate attachment.  Also, I've tried to avoid use of anything specific to FlexBuilder so that anyone with any text editor should be able to use my examples.</p>
<p>Despite the length of this blog entry, use of the BlazeDS remoting is pretty straightforward once you have tried it a couple times.  It does get more complex when security constraints and other details are added back in, but one can choose how much one implements at each step and the examples above are nice for confirming that client-to-server communication is working properly.</p>
<p><strong>Additional Resources</strong>
<ul>
<li><a href="http://livedocs.adobe.com/blazeds/1/blazeds_devguide/">BlazeDS Developer Guide</a> (<a href="http://livedocs.adobe.com/blazeds/1/blazeds_devguide/blazeds_devguide.pdf">PDF</a>)<br /> 
<ul> 
<li><a href="http://livedocs.adobe.com/blazeds/1/blazeds_devguide/serialize_data_1.html">Data Serialization</a></li>
<p> 
<li><a href="http://livedocs.adobe.com/blazeds/1/blazeds_devguide/help.html?content=rpc_remoteobject_1.html">Using the Remoting Service</a></li>
<p>  </ul>
<p></li>
<p>
<li><a href="http://www.infoq.com/articles/blazeds-intro">Building Web and Desktop Applications with BlazeDS and AMF</a></li>
<p>
<li><a href="http://www.flexlive.net/?p=92">BlazeDS Tutorial - Remove Object Service</a></li>
<p>
<li><a href="http://www.adobe.com/devnet/livecycle/articles/blazeds_gettingstarted_02.html">Getting Started with BlazeDS</a></li>
<p>
<li><a href="http://www.infoaccelerator.net/blog/post.cfm/blazeds-remoting-messging">BlazeDS: Remoting != Messging</a></li>
<p>
<li><a href="http://cornelcreanga.com/2008/11/bringing-data-into-flex-applications-introduction/">Bringing Data into Flex Applications - Introduction</a></li>
<p></ul>
    ]]></content>
  </entry>
  <entry>
    <title>G1 address book: innovation through degradation</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2179" />
    <id>http://www.javaworld.com/community/node/2179</id>
    <published>2009-01-01T09:13:18-05:00</published>
    <updated>2009-01-01T09:13:18-05:00</updated>
    <author>
      <name>Oleg Mikheev</name>
    </author>
    <category term="Android" />
    <summary type="html"><![CDATA[<p>Being very annoyed with G1's lack of contacts import functionality I decided to take a look into Android programming.</p>
<p>The first thing I noticed was contact Name being a single field (no separate field for First, Second, Middle names). I've never seen this before, so I consider it an innovation. This makes it impossible for any application to sort contacts by the second name. Also it makes life a lot harder for ones who would want to import, export or synchronize contacts with any other application (except for Gmail which also has names as a single field).</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>Being very annoyed with G1's lack of contacts import functionality I decided to take a look into Android programming.</p>
<p>The first thing I noticed was contact Name being a single field (no separate field for First, Second, Middle names). I've never seen this before, so I consider it an innovation. This makes it impossible for any application to sort contacts by the second name. Also it makes life a lot harder for ones who would want to import, export or synchronize contacts with any other application (except for Gmail which also has names as a single field).</p>
<p>Second, Android defines a number of predefined phone types. Unfortunately these types can't be combined, so there's no chance to define a mobile work phone for your contact. Of course there is that 'other' type, but still it will add another task of mapping text-to-normal types to any contacts application.</p>
    ]]></content>
  </entry>
  <entry>
    <title>2009 Predictions, 2008 Predictions Revisited</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2176" />
    <id>http://www.javaworld.com/community/node/2176</id>
    <published>2009-01-01T02:54:29-05:00</published>
    <updated>2009-01-05T02:57:08-05:00</updated>
    <author>
      <name>Ted Neward</name>
    </author>
    <summary type="html"><![CDATA[<p>
It's once again that time of year, and in keeping with my tradition, I'll revisit<br />
the 2008 predictions to see how close I came before I start waxing prophetic on the<br />
coming year. (I'm thinking that maybe the next year--2010's edition--I should actually<br />
take a shot at predicting the next decade, but I'm not sure if I'd remember to go<br />
back and revisit it in 2020 to see how I did. Anybody want to set a calendar reminder<br />
for Dec 31 2019 and remind me, complete with URL? ;-) )
</p>
<p>
Without further preamble, here's what I said for 2008:
</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>
It's once again that time of year, and in keeping with my tradition, I'll revisit<br />
the 2008 predictions to see how close I came before I start waxing prophetic on the<br />
coming year. (I'm thinking that maybe the next year--2010's edition--I should actually<br />
take a shot at predicting the next decade, but I'm not sure if I'd remember to go<br />
back and revisit it in 2020 to see how I did. Anybody want to set a calendar reminder<br />
for Dec 31 2019 and remind me, complete with URL? ;-) )
</p>
<p>
Without further preamble, here's what I said for 2008:
</p>
<ul>
<li>
<strong>THEN: </strong><em>General</em>: The buzz around building custom languages<br />
will only continue to build. More and more tools are emerging to support the creation<br />
of custom programming languages, like Microsoft's Phoenix, Scala's parser combinators,<br />
the Microsoft DLR, SOOT, Javassist, JParsec/NParsec, and so on. Suddenly, the whole<br />
"write your own lexer and parser and AST from scratch" idea seems about as outmoded<br />
as the idea of building your own String class. Granted, there are cases where a from-hand<br />
scanner/lexer/parser/AST/etc is the Right Thing To Do, but there are times when building<br />
your own String class is the Right Thing To Do, too. Between the rich ecosystem of<br />
dynamic languages that could be ported to the JVM/CLR, and the interesting strides<br />
being made on both platforms (JVM and CLR) to make them more "dynamic-friendly" (such<br />
as being able to reify classes or access the call stack directly), the probability<br />
that your company will find a need that is best answered by building a custom language<br />
are only going to rise. <strong>NOW: </strong>The buzz has definitely continued to<br />
build, but buzz can only take us so far. There's been some scattershot use of custom<br />
languages in a few scattershot situations, but it's certainly not "taken the world<br />
by storm" in any meaningful way yet.</li>
<li>
<strong>THEN: </strong><em>General</em>: The hype surrounding "domain-specific languages"<br />
will peak in 2008, and start to generate a backlash. Let's be honest: when somebody<br />
looks you straight in the eye and suggests that "scattered, smothered and covered"<br />
is a domain-specific language, the term has lost all meaning. A lexicon unique to<br />
an industry is not a domain-specific language; it's a lexicon. Period. If you can<br />
incorporate said lexicon into your software, thus making it accessible to non-technical<br />
professionals, that's a good thing. But simply using the lexicon doesn't make it a<br />
domain-specific language. Or, alternatively, if you like, every single API designed<br />
for a particular purpose is itself a domain-specific language. This means that Spring<br />
configuration files are a DSL. Deployment descriptors are a DSL. The Java language<br />
is a DSL (since the domain is that of programmers familiar with the Java language).<br />
See how nonsensical this can get? Until somebody comes up with a workable definition<br />
of the term "domain" in "domain-specific language", it's a nonsensical term. The idea<br />
is a powerful one, mind you--creating something that's more "in tune" with what users<br />
understand and can use easily is a technique that's been proven for decades now. Anybody<br />
who's ever watched an accountant rip an entirely new set of predictions for the new<br />
fiscal outlook based entirely on a few seed numbers and a deeply-nested set of Excel<br />
macros knows this already. Whether you call them domain-specific languages or "little<br />
languages" or "user-centric languages" or "macro language" is really up to you. <strong>NOW:</strong> The<br />
backlash hasn't begun, but only because the DSL buzz hasn't materialized in much way<br />
yet--see previous note. It generally takes a year or two of deployments (and hard-earned<br />
experience) before a backlash begins, and we haven't hit that "deployments" stage<br />
yet in anything yet resembling "critical mass" yet. But the DSL/custom language buzz<br />
continues to grow, and the more the buzz grows, the more the backlash is likey.</li>
<li>
<strong>THEN: </strong><em>General</em>: Functional languages will begin to make their<br />
presence felt. Between Microsoft's productization plans for F# and the growing community<br />
of Scala programmers, not to mention the inherently functional concepts buried inside<br />
of LINQ and the concurrency-friendly capabilities of side-effect-free programming,<br />
the world is going to find itself working its way into functional thinking either<br />
directly or indirectly. And when programmers start to see the inherent capabilities<br />
inside of Scala (such as Actors) and/or F# (such as asynchronous workflows), they're<br />
going to embrace the strange new world of functional/object hybrid and never look<br />
back. <strong>NOW:</strong> Several books on F# and Scala (and even one or two on<br />
Haskell!) were published in 2008, and several more (including one of my own) are on<br />
the way. The functional buzz is building, and lots of disparate groups are each evaluating<br />
it (functional programming) independently.</li>
<li>
<strong>THEN: </strong><em>General</em>: MacOS is going to start posting some serious<br />
market share numbers, leading lots of analysts to predict that Microsoft Windows has<br />
peaked and is due to collapse sometime within the remainder of the decade. Mac's not<br />
only a wonderful OS, but it's some of the best hardware to run Vista on. That will<br />
lead not a few customers to buy Mac hardware, wipe the machine, and install Vista,<br />
as many of the uber-geeks in the Windows world are already doing. This will in turn<br />
lead Gartner (always on the lookout for an established trend they can "predict" on)<br />
to suggest that Mac is going to end up with 115% market share by 2012 (.8 probability),<br />
then sell you this wisdom for a mere price of $1.5 million (per copy). <strong>NOW:</strong> Can't<br />
speak to the Gartner report--I didn't have $1.5 million handy--but certainly the MacOS<br />
is growing in popularity. More on that later.</li>
<li>
<strong>THEN:</strong> <em>General</em>: Ted will be hired by Gartner... if only to<br />
keep him from smacking them around so much. .0001 probability, with probability going<br />
up exponentially as my salary offer goes up exponentially. (Hey, I've got kids headed<br />
for college in a few years.) <strong>NOW:</strong> Well, Gartner appears to have lost<br />
my email address and phone number, but I'm sure they were planning to make me that<br />
offer.</li>
<li>
<strong>THEN: </strong><em>General</em>: MacOS is going to start creaking in a few<br />
places. The Mac OS is a wonderful OS, but it's got its own creaky parts, and the more<br />
users that come to Mac OS, the more that software packages are going to exploit some<br />
of those creaky parts, leading to some instability in the Mac OS. It won't be widespread,<br />
but for those who are interested in finding it, they're there. Assuming current trends<br />
(of customers adopting Mac OS) hold, the Mac OS 10.6 upgrade is going to be a very<br />
interesting process, indeed. <strong>NOW:</strong> Shhh. Don't tell anybody, but I've<br />
been seeing it starting to happen. Don't get me wrong, Apple still does a pretty good<br />
job with the OS, but the law of numbers has started to create some bad upgrade scenarios<br />
for some people.</li>
<li>
<strong>THEN: </strong><em>General</em>: Somebody is going to realize that iTunes<br />
is the world's biggest monopoly on music, and Apple will be forced to defend itself<br />
in the court of law, the court of public opinion, or both. Let's be frank: if this<br />
were Microsoft, offering music that can only be played on Microsoft music players,<br />
the world would be through the roof. All UI goodness to one side, the iPod represents<br />
just as much of a monopoly in the music player business as Internet Explorer did in<br />
the operating system business, and if the world doesn't start taking Apple to task<br />
over this, then "justice" is a word that only applies when losers in an industry want<br />
to drag down the market leader (which I firmly believe to be the case--nobody likes<br />
more than to pile on the successful guy). <strong>NOW:</strong> Nothing this year.</li>
<li>
<strong>THEN: </strong><em>General</em>: Somebody is going to realize that the iPhone's<br />
"nothing we didn't write will survive the next upgrade process" policy is nothing<br />
short of draconian. As my father, who gets it right every once in a while, says, "If<br />
I put a third-party stereo in my car, the dealer doesn't get to rip it out and replace<br />
it with one of their own (or nothing at all!) the next time I take it in for an oil<br />
change". Fact is, if I buy the phone, I own the phone, and I own what's on it. Unfortunately,<br />
this takes us squarely into the realm of DRM and IP ownership, and we all know how<br />
clear-cut that is... But once the general public starts to understand some of these<br />
issues--and I think the iPhone and iTunes may just be the vehicle that will teach<br />
them--look out, folks, because the backlash will be huge. As in, "Move over, Mr. Gates,<br />
you're about to be joined in infamy by your other buddy Steve...." <strong>NOW:</strong> Apple<br />
released iPhone 2.0, and with it, the iPhone SDK, so at least Apple has opened the<br />
dashboard to third-party stereos. But the deployment model (AppStore) is still a bit<br />
draconian, and Apple still jealously holds the reins over which apps can be deployed<br />
there and which ones can't, so maybe they haven't learned their lesson yet, after<br />
all....</li>
<li>
<strong>THEN: </strong><em>Java</em>: The OpenJDK in Mercurial will slowly start to<br />
see some external contributions. The whole point of Mercurial is to allow for deeper<br />
control over which changes you incorporate into your build tree, so once people figure<br />
out how to build the JDK and how to hack on it, the local modifications will start<br />
to seep across the Internet.... <strong>NOW:</strong> OpenJDK has started to collect<br />
contributions from external (to Sun) sources, but still in relatively small doses,<br />
it seems. None of the local modifications I envisioned creeping across the 'Net have<br />
begun, that I can see, so maybe it's still waiting to happen. Or maybe the OpenJDK<br />
is too complicated to really allow for that kind of customization, and it never will.</li>
<li>
<strong>THEN:</strong> <em>Java</em>: SpringSource will soon be seen as a vendor like<br />
BEA or IBM or Sun. Perhaps with a bit better reputation to begin, but a vendor all<br />
the same. <strong>NOW:</strong> SpringSource's acquisition of G2One (the company behind<br />
Groovy just as SpringSource backs Spring) only reinforced this image, but it seems<br />
it's still something that some fail to realize or acknowledge due to Spring's open-source<br />
(?) nature. (I'm not a Spring expert by any means, but apparently Spring 3 was pulled<br />
back inside the SpringSource borders, leading some people to wonder what SpringSource<br />
is up to, and whether or not Spring will continue to be open source after all.)</li>
<li>
<strong>THEN:</strong> <em>.NET</em>: Interest in OpenJDK will bootstrap similar interest<br />
in Rotor/SSCLI. After all, they're both VMs, with lots of interesting ideas and information<br />
about how the managed platforms work. <strong>NOW:</strong> Nope, hasn't really happened<br />
yet, that I can see. Not even the 2nd edition of the SSCLI book (by Joel Pobar and<br />
yours truly, yes that was a plug) seemed to foster the kind of attention or interest<br />
that I'd expected, or at least, not on the scale I'd thought might happen.</li>
<li>
<strong>THEN: </strong><em>C++/Native</em>: If you've not heard of LLVM before this,<br />
you will. It's a compiler and bytecode toolchain aimed at the native platforms, complete<br />
with JIT and GC. <strong>NOW:</strong> Apple sank a lot of investment into LLVM, including<br />
hosting an LLVM conference at the corporate headquarters.</li>
<li>
<strong>THEN:</strong> <em>Java</em>: Somebody will create Yet Another Rails-Killer<br />
Web Framework. 'Nuff said. <strong>NOW:</strong> You know what? I honestly can't say<br />
whether this happened or not; I was completely not paying attention.</li>
<li>
<strong>THEN:</strong> <em>Native</em>: Developers looking for a native programming<br />
language will discover D, and be happy. Considering D is from the same mind that was<br />
the core behind the Zortech C++ compiler suite, and that D has great native platform<br />
integration (building DLLs, calling into DLLs easily, and so on), not to mention automatic<br />
memory management (except for those areas where you want manual memory management),<br />
it's definitely worth looking into. <a href="http://www.digitalmars.com">www.digitalmars.com</a> <strong>NOW:</strong> D<br />
had its own get-together as well, and appears to still be going strong, among the<br />
group of developers who still work on native apps (and aren't simply maintaining legacy<br />
C/C++ apps).</li>
</ul>
<p>
Now, for the 2009 predictions. The last set was a little verbose, so let me see if<br />
I can trim the list down a little and keep it short and sweet:
</p>
<ul>
<li>
<em>General:</em> "Cloud" will become the next "ESB" or "SOA", in that it will be<br />
something that everybody will talk about, but few will understand and even fewer will<br />
do anything with. (Considering the widespread disparity in the definition of the term,<br />
this seems like a no-brainer.)</li>
<li>
<em>Java</em>: Interest in Scala will continue to rise, as will the number of detractors<br />
who point out that Scala is too hard to learn.</li>
<li>
<em>.NET</em>: Interest in F# will continue to rise, as will the number of detractors<br />
who point out that F# is too hard to learn. (Hey, the two really are cousins, and<br />
the fortunes of one will serve as a pretty good indication of the fortunes of the<br />
other, and both really seem to be on the same arc right now.)</li>
<li>
<em>General:</em> Interest in all kinds of functional languages will continue to rise,<br />
and more than one person will take a hint from Bob "crazybob" Lee and liken functional<br />
programming to AOP, for good and for ill. People who took classes on Haskell in college<br />
will find themselves reaching for their old college textbooks again.</li>
<li>
<em>General:</em> The iPhone is going to be hailed as "the enterprise development<br />
platform of the future", and companies will be rolling out apps to it. Look for Quicken<br />
iPhone edition, PowerPoint and/or Keynote iPhone edition, along with connectors to<br />
hook the iPhone up to a presentation device, and (I'll bet) a World of Warcraft iPhone<br />
client (legit or otherwise). iPhone is the new hotness in the mobile space, and people<br />
will flock to it madly.</li>
<li>
<em>.NET</em>: Another Oslo CTP will come out, and it will bear only a superficial<br />
resemblance to the one that came out in October at PDC. Betting on Oslo right now<br />
is a fools' bet, not because of any inherent weakness in the technology, but just<br />
because it's way too early in the cycle to be thinking about for anything vaguely<br />
resembling production code.</li>
<li>
<em>.NET</em>: The IronPython and IronRuby teams will find some serious versioning<br />
issues as they try to manage the DLR versioning story between themselves and the CLR<br />
as a whole. An initial hack will result, which will be codified into a standard practice<br />
when .NET 4.0 ships. Then the next release of IPy or IRb will have to try and slip<br />
around its restrictions in 2010/2011. By 2012, IPy and IRb will have to be shipping<br />
as part of Visual Studio just to put the releases back into lockstep with one another<br />
(and the rest of the .NET universe).</li>
<li>
<em>Java</em>: The death of JSR-277 will spark an uprising among the two leading groups<br />
hoping to foist it off on the Java community--OSGi and Maven--while the rest of the<br />
Java world will breathe a huge sigh of relief and look to see what "modularity" means<br />
in Java 7. Some of the alpha geeks in Java will start using--if not building--JDK<br />
7 builds just to get a heads-up on its impact, and be quietly surprised and, I dare<br />
say, perhaps even pleased.</li>
<li>
<em>Java</em>: The invokedynamic JSR will leapfrog in importance to the top of the<br />
list.</li>
<li>
<em>Windows</em>: Another Windows 7 CTP will come out, and it will spawn huge media<br />
interest that will eventually be remembered as Microsoft promises, that will eventually<br />
be remembered as Microsoft guarantees, that will eventually be remembered as Microsoft<br />
FUD and "promising much, delivering little". Microsoft ain't always at fault for the<br />
inflated expectations people have--sometimes, yes, perhaps even a lot of times, but<br />
not always.</li>
<li>
<em>Mac OS</em>: Apple will begin to legally threaten the clone market again, except<br />
this time somebody's going to get the DOJ involved. (Yes, this is the iPhone/iTunes<br />
prediction from last year, carrying over. I still expect this to happen.)</li>
<li>
<em>Languages</em>: Alpha-geek developers will start creating their own languages<br />
(even if they're obscure or bizarre ones like Shakespeare or Ook#) just to have that<br />
listed on their resume as the DSL/custom language buzz continues to build.</li>
<li>
<em>XML Services</em>: Roy Fielding will officially disown most of the "REST"ful authors<br />
and software packages available. Nobody will care--or worse, somebody looking to make<br />
a name for themselves will proclaim that Roy "doesn't really understand REST". And<br />
they'll be right--Roy doesn't understand what <em>they</em> consider to be REST, and<br />
the fact that he created the term will be of no importance anymore. Being "REST"ful<br />
will equate to "I did it myself!", complete with expectations of a gold star and a<br />
lollipop.</li>
<li>
<em>Parrot</em>: The Parrot guys will make at least one more minor point release.<br />
Nobody will notice or care, except for a few doggedly stubborn Perl hackers. They<br />
will find themselves having nightmares of previous lives carrying around OS/2 books<br />
and Amiga paraphernalia. Perl 6 will celebrate it's seventh... or is it eighth?...<br />
anniversary of being announced, and nobody will notice.</li>
<li>
<em>Agile</em>: The debate around "Scrum Certification" will rise to a fever pitch<br />
as short-sighted money-tight companies start looking for reasons to cut costs and<br />
either buy into agile at a superficial level and watch it fail, or start looking to<br />
cut the agilists from their company in order to replace them with cheaper labor.</li>
<li>
<em>Flash</em>: Adobe will continue to make Flex and AIR look more like C# and the<br />
CLR even as Microsoft tries to make Silverlight look more like Flash and AIR. Web<br />
designers will now get to experience the same fun that back-end web developers have<br />
enjoyed for near-on a decade, as shops begin to artificially partition themselves<br />
up as either "Flash" shops or "Silverlight" shops.</li>
<li>
<em>Personal</em>: Gartner will still come knocking, looking to hire me for outrageous<br />
sums of money to do nothing but blog and wax prophetic.</li>
</ul>
<p>
Well, so much for brief or short. See you all again next year....
</p>
<p></p>
<p>Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.<br />
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact<br />
me for details</a>.</p>
    ]]></content>
  </entry>
  <entry>
    <title>JavaFX: Not just for the RIA space</title>
    <link rel="alternate" type="text/html" href="http://www.javaworld.com/community/node/2175" />
    <id>http://www.javaworld.com/community/node/2175</id>
    <published>2008-12-31T18:46:04-05:00</published>
    <updated>2008-12-31T18:46:04-05:00</updated>
    <author>
      <name>Josh Fruhlinger</name>
    </author>
    <category term="javafx" />
    <category term="swing" />
    <category term="SwingX" />
    <summary type="html"><![CDATA[<!--paging_filter--><p>Continuing to explore the notion that <a href="http://www.javaworld.com/community/node/2058" target="_blank">JavaFX may well be Swing 2.0</a>, I came across a couple of interesting how-to articles upon my return from my holiday journeys.    ]]></summary>
    <content type="html"><![CDATA[<!--paging_filter--><p>Continuing to explore the notion that <a href="http://www.javaworld.com/community/node/2058" target="_blank">JavaFX may well be Swing 2.0</a>, I came across a couple of interesting how-to articles upon my return from my holiday journeys.   <a href="http://lobobrowser.wordpress.com/2008/12/29/javafx-video-in-a-swing-application-technically-doable/" target="_blank">The Lobo Project Blog</a> explores the process of actually mingling JavaFX and Swing, putting JavaFX video into a Swing application, declaring the procedure "technically doable."  The ability to do this sort of thing is crucial if the transition between UI technologies is to be at all smooth.  Also of note is a piece in which a developer <a href="http://internna.blogspot.com/2008/12/javafx-mario-and-me.html" target="_blank">animates Mario in JavaFX</a>, in which he grumbles "why the hell do they call this Java?" but is ultimately kind of impressed.</p>

<p>Speaking of which: for all those who feared that JavaFX had sucked all the oxygen away from S