|
|
||
Richard Bair's BlogJune 2006 ArchivesSimple Yahoo! News ReaderPosted by rbair on June 30, 2006 at 03:52 PM | Permalink | Comments (0)My last few blogs have been on using web services in Swing. This time I've created a simple Yahoo! News RSS reader JavaBean you can use in your own apps. And yes, this time I went all the way and wrote a JNLP. But beware, it is only running on 1.6 for now. I didn't even know I was developing on 1.6 until I tested the deploy, and now I'm headed out on vacation. Here's a screenshot, for those you can't or won't run the demo: It is a very ugly demo. Again, vacation and all that. But, here's basically what it does. You enter the name of the feed you'd like to see in the combo box on the top. Or you can pick one of the predefined ones, its up to you. Then click the "Refresh" button. On a background thread (there ya go, vtech!) I get the feed results, parse them, and then back on the UI thread I load them into the JTextArea. The results are raw output from the ROME RSS reader which I use to do all the heavy lifting. The point here isn't to show off some slick looking application -- its the work that went into creating it. Or the lack thereof. Read the source code yourself. You can also download the sources and rebuild the project (but good luck getting it to load up in NetBeans. Sorry no time to make it pretty, vacation calls). For the impatient, here's the source code boiled down. First, I created a YahooNews bean (well, after creating the UI). I then created a BackgroundWorker bean called "worker". I then filled in the BackgroundWorker's event handlers, and wrote an action listener for the "Refresh" button. Here's all the magic:
Aerith is free!Posted by rbair on June 28, 2006 at 02:00 PM | Permalink | Comments (9)The Aerith source code has just been released to the aerith.dev.java.net project. With this milestone I thought I'd just blog a bit about the backstory that went into Aerith. Hopefully, by the time you're done reading this, you won't stone us for some pretty hacked up code. Aerith was a really fun project to work on. We sort of had an idea for what we wanted to do for JavaOne. We had a lot of fun doing the Joplin music player the year before and really wanted to get back up on stage this year with something even cooler. Romain had a lot of demos lying around. The client group had this sweet intro screen idea and Romain had already mocked up a UI that would form the basis of the Aerith look. Every year James Gosling holds a kind of "tryouts" for keynote demos. We didn't know when those tryouts would be held, so we sent a few emails to find out. What we found was that we had about a week to get the demo finished before the tryouts. I was at home at the time and had to say goodbye to the wife and kid for the next few days. Romain, Josh and I setup a war room in one of the conference rooms here on campus. As all good war rooms, ours was stocked with food, liquid nourishment (water for me, on a diet :-)), and pizza (so much for the diet). Oh, and chocolate cake. No "Romain" war room is complete without chocolate cake. In three days of intense coding (Thursday, Friday, and Saturday. Usually about 18 hours+ each day) we wrote the entire map viewer and editor, and part of the applet. The original applet contained only the 3d "twinkle" code. (For those familiar with Romain's blog, Twinkle is one of the projects he released that we reused for this demo). With that, the demo was more or less feature complete. Later that week I added what we called the "Indiana Jones" viewer in the applet. Otherwise, bugfixes occupied our time. And endless tweaks to get things up to Romains standards. It was also a lot of fun to tryout for James' keynote and finally make it into Jeff Jackson's keynote on Tuesday morning. I always have a blast at JavaOne, and love getting up on stage. Even if I am boring to watch :-). The moral of this story (if there is one, besides diet's and war rooms not getting along so well) is that a sizeable portion of the Aerith code is very, very raw. It wasn't written as a "best practices" application, or to be maintained. It has a lot of bugs, is difficult to setup, needs a better build script, and nobody knows how the 3d stuff works besides Romain. It was written to show off what is possible with Swing/Java. It was written to demo well. And it was written because it was fun to do. I think in all three respects it was a home run. Especially the last one: it was a lot of fun. I think there is a great deal of potential in Aerith as a consumer application. We're looking for individuals who want to move Aerith to the next level. I'd be stoked to see it deployed and working with real people's data in real world situations. That'd really make my day. So, this makes 3 blogs in 3 days. If I keep this up, I'll have my yearly quota down by the end of the week! Swing and Non Blocking JAX-WSPosted by rbair on June 27, 2006 at 04:12 PM | Permalink | Comments (5)Yesterday I blogged about JAX-WS and how to use it with Swing. I tried to sneak by with a simple example that happened to block the EDT during the web service invocation (bad Richard! bad). Since I was called out on it, I took the opportunity to create a new JavaBean for working with background tasks and update my example to use it. The problem with yesterday's example was this method:
In this method I contact the webservice (a potentially lengthy process) while in the Event Dispatch Thread. In other words, while trying to contact the web service the entire GUI was frozen. Solid. Today we'll fix the problem by using a background thread. For this task I created a new non visual JavaBean called BackgroundWorker. For those familiar with .NET, you'll notice the name. BackgroundWorker is a helper class that handles a lot of the threading work for you. BackgroundWorker is intended to be used in your GUI builder environment. To use it, you:
Those who've written multithreaded Swing code in the past have probably used SwingWorker. SwingWorker is an excellent piece of code, and handles a lot of the really sticky details for multithreading. BackgroundWorker, in fact, delegates to SwingWorker to do the actual multi-threading work. Why write BackroundWorker then? Well, when using a GUI builder, using a non visual component like BackgroundWorker can really be nice. I've found it much easier to "view" code visually in a GUI builder than to read and mentally visualize code. Here's the new code, using a JXStatusBar and the BackgroundWorker. Oh, and by the way, I also implement the "started" and "done" events to make sure my GUI is properly disabled and re-enabled during this long process.
And here's the code for BackgroundWorker (I've omitted the event classes because they're boring :-). If there is enough interest, I'll push this code into SwingX).
Swing, JAX-WS, and JavaBeansPosted by rbair on June 26, 2006 at 01:29 PM | Permalink | Comments (6)On the SwingLabs Forums we have been discussing Web Services and Swing. In particular, I want to start/retrofit a project on java.net where we can build both visual (like the Aerith map viewer) and non visual components. Some examples of non visual JavaBean components could include a Flickr bean, YahooSearch bean, YahooWeather bean, and so on. During the discussion, Adam expressed some concern about focusing on potentially gimicky web services like Flickr at the expense of more mainstream services such as those that would be developed in house at your local enterprise. I decided to take a shot at that situation and see what the development landscape looked like from the enterprise angle, especially when using the latest JEE 5 features. What I found was surprisingly easy, and very... uh... addicting. There's no webstart demo, because I don't have a webserver ready to handle the server side tasks. I guess you'll just have to trust me that it works. Or better yet, try it yourself :-) SetupJAX-WS can be daunting. The most difficult aspect of it is the setup and configuation of the build environment. This will become a bit more clear as we go along. I've chosen to sidestep the whole issue and just try NetBeans 5.5 with the Enterprise development pack This really made the setup process a lot easier for a lowly desktop guy like myself. I went to the NetBeans 5.5 download area and downloaded both the NetBeans IDE 5.5 Beta Installer and the NetBeans Enterprise Pack 5.5 EA Installer. I then downloaded and installed NetBeans 5.5, followed by the Enterprise Pack. I chose to install the SJAS 9 application server as part of the Enterprise Pack install. This was to make sure I had a Java EE 5 compatible server handy to test the new featuers. Note, I'm running on an Intel Mac with Mustang, and was surprised that everything *almost* worked. The only thing I had to do special was configure my netbeans.conf file to point to the JDK. This may have been because I've been messing with my JDK settings on MacOSX to get Mustang running. Finally, after installing everything and starting NetBeans, I had to enter the Server Manager and configure SJAS 9 as a web server. This is important, because later when we create our web application a Java EE 5 compatible server needs to be available. Now that I had everything installed and configured, I created two projects: Swing-WS-Website and Swing-WS. Swing-WS-Website is a normal NetBeans Web Application project type. The only special requirement was to make sure SJAS 9 was selected as the target server, and that JEE 5 is selected as the target. The Swing-WS project was just a normal Java Application project type. Nothing special. Creating the Web ServiceI chose a really simple and pointless web service as an example -- a random number generator. In NetBeans, I created a new Web Service. I altered the code to look like this:
There really isn't much to this code. I simply marked the RandomNumbers class with the @WebService annotation, and then marked the generateRandomNumbers method with the @WebMethod annotation. By creating this class with the NetBeans wizard, it made sure that the appropriate build configuration was done so that at this point, all I have to do is deploy. In SJAS 9 I can test my web service by going to the admin site. By default this is installed at http://localhost:4848. I won't go into any more detail on this product. I've found it very easy to use, and you can find info on the net for it. Writing the ClientNow that I knew my service was deployed and working, I was ready to write the client. First, I had to make the client project aware of the web service. When doing this by hand, this is where the nasty part is. All SOAP web services (which is what NetBeans created and deployed for me) have a WSDL file. This file describes the service in a language neutral manner. The same WSDL can be used by .NET clients or Java clients, for instance. In Java EE 5, the wsimport command line program reads WSDL files and generates java source files. You can then call these Java classes from within your client. I've tried doing all this by hand in the past and found it to be a huge pain. Tool support makes this experience much, much better. In NetBeans, I opened the New File wizard and selected Web Service Client. I then pointed it at my RandomNumbers web service (note: in the IDE I didn't even have to deal with the WSDL directly, NB hid all this mess from me). NetBeans automatically called wsimport and created the source files for the web service for me. The only problem I had was that I never saw these source files. Even though I'd specified a source package. As it turns out, NB 5.5 puts the source files in the "build" directory (which normally just contains class files). I guess they're trying to be clever and hide the sources from your source tree (no point cluttering it up). I'd have preferred that they generated a jar file and put it on my classpath, or at least told me what was going on. It took a while to figure out what was happening. Now that I know, it isn't so bad. Once the web service was imported into the project, I wrote a quick main method to test it out:
Before running the sample I opened the SJAS admin webapp in my browser to check the logs and see what happened when the webservice was called. I then ran the client. Bingo. Worked perfectly. So that's cool, but now how do I write a Swing application with this knowledge? Here's what I'd like it to look like (please Romain, don't laugh ;-)) <SIDETRACK> Sally is a server side super-engineer. She dreams in XML. Not just any XML, but we're talking namespace-declared, Schema-validated, fully robust XML. She's written a few web services to make available to the masses within her company. To help facilitate their work, she bundles the generated client stubs (generated by wsimport) along with a set of simple JavaBeans. Clint is a client side desktop kind of guy. He has more work to do than time to do it. All departments in the company want him to write their apps because he gets them done fast, and they work pretty well. Clint needs to access Sally's web services. No problem. He gets her web service bundle (including the client side stubs and JavaBeans) and adds them to his project. He takes the JavaBeans and adds them to his Visual editor's palette. He then creates a new form, adds the WS JavaBeans to the palette, configures them (and the rest of the UI) in his editor, compiles, tests, and deploys. All as fast as his little hands can type... er, click, since he uses the visual designer as much as possible to simplify his life. Funny enough, Wally the Web App guru also needs to write some clients. He also takes advantage of Sally's hard work and imports the JavaBeans into his JSF visual environment. Since I don't know enough about writing webapps, I'll stop the story here. Except to say that there is no fundemental difference between writing desktop and web applications when it comes to these simple JavaBeans. Ok, enough of the somewhat silly story, but perhaps you can see a bit of the vision. So, how do we write these JavaBeans? For this example, it is really quite simple. Basically, my RandomNumbersWS bean needs to allow the developer to specify the count -- the number of random numbers to return. In a real example it may take your Yahoo application id and search params. But that's another blog. Here's the code:
JavaBean is a convenience class in SwingX that I can extend. It makes writing these non visual beans a lot easier because it handles the infrastructure for a lot of the property change notification. You'll notice that this bean isn't doing much: it's simply a wrapper for the RandomNumbers client side proxy (called a "port" in JAX-WS). Now, let's see how to use it. I created my Swing GUI with Matisse -- took a minute, maybe two (Note for Scott: I didn't get any baseline support for JSpinner). I then wrote this code in the actionPerformed event handler for the generate button:
If bean binding was ready to go, this would have been even simpler. But as it is, this is just normal Swing code. I set the count on the ws bean, then asked it for the random numbers. I then put the resulting List into the JList component. Ok, so why bother with the bean? Seems like extra overhead here. Yes, this is a trivial example and it doesn't show off the point to a Bean very well. However, if I were using JSR 295: Bean Binding then having a Bean to bind to would have been really useful. Further, more complicated web services may benefit more from the beans approach. There is another subtle benefit to using the JavaBean in this case. It insulates the UI developer from the web service implementation. Both Clint and Wally won't have to change anything is Sally decides to switch to XML-RPC instead of SOAP and redistributes a new bean. From the UI perspective, they are dealing with the Web Service on the semantic level, rather than the level of the implementation. Once I learned how to use NB to execute web services from the client, it was a very easy process to get these calls into the UI. Those paying close attention will notice that the call blocks, though, so I have some more work to go before this is a genuinely rich rich client application. Gotta get rid of those blocking calls! | ||
|
|