I have recently submitted a few posts regarding JavaOne 2010, but there are several posts by other people related to JavaOne 2010 that I think are worth special mention here.
Not surprisingly, the Java One Conference Blog has several good posts regarding JavaOne 2010. The first post (of an advertised three) on JavaOne Rock Stars (named at previous JavaOne conferences) returning to present at JavaOne 2010 has been published. As featured in Kevin Farnham's 28 July 2010 Java.net editorial (Editor's Daily Blog), the Java One Conference Blog also recently announced an opportunity to win a pass to JavaOne (or Oracle OpenWorld or Oracle Develop) by submitting a video explaining why the entrant "deserve[s] to go to Oracle OpenWorld, JavaOne or Oracle Develop for FREE." The main page for this video contest specifies that "entries [are] accepted from 7/27/10 to 08/09/10" and states that one pass will be awarded to Oracle Open World and two passes will be awarded for JavaOne and Oracle Develop. Those who do not win, but submit a valid video for the contest, will also get a $400 discount (early bird discount) off the conference registration price (see FAQ for details). Because Early Bird Pricing ended yesterday (after being extended past its original end date of 16 July 2010), this is a potentially very welcome discount.
There are numerous blog posts mentioning JavaOne not as the main topic of the post, but in an expression of hope for hearing a relevant announcement or others news on the main topic at this conference. For example, in JavaFX Revisited: Moving Forward, James Sugrue writes about some possible scenarios for Oracle to pursue related to JavaFX and JavaOne and adds, "I believe that this year's JavaOne is make or break time for JavaFX." In his simply titled post JavaOne 2010, David Bonilla also lists things he hopes to get from JavaOne 2010. The responses to a recent Java.net poll regarding JavaOne confirms my theory that many of us are hoping for a better idea of the timeframe of Java 7/JDK 7 after JavaOne.
Markus Eisele's recent blog post Links and Tips for OpenWorld, JavaOne and OracleDevelop 2010, as its name implies, is a nice collection of links and tips related to the three Oracle-sponsored conferences being held together (including JavaOne). Eisele covers everything from getting a visa to staying and playing in San Francisco. I especially appreciated his link to A Local's Guide for People Visiting or Moving to San Francisco. Eisele provides a list of his personal list of his "must see" attractions in San Francisco including the signature cable cars, Fisherman's Wharf, and Alcatraz Island. Oh yeah, JavaOne is not a mere boondoggle: he provides links to conference-related sites as well.
As JavaOne approaches and arrives, I expect to see and look foreward to reading many more useful blog posts covering this event.
Dustin's Software Development Cogitations and Speculations My observations and thoughts concerning software development (general development, Java, JavaFX, Groovy, Flex, ...). Select posts from this blog are syndicated on DZone and Java Code Geeks and were formerly syndicated on JavaWorld.
Saturday, July 31, 2010
Friday, July 30, 2010
Explicitly Specifying 'args' Property with Groovy CliBuilder
As I have blogged on previously, Groovy's CliBuilder makes parsing with Apache Commons CLI very straightforward. However, there are a few minor things to be aware of when using CliBuilder. One of these observations is the importance of explicitly specifying the args property for options that have more than the default (zero) arguments. In this blog post, I look at what can happen when this is not done.
The following script, groovyArgsHelloWorld.groovy, demonstrates this with the typical "Hello World" type example.
groovyArgsHelloWorld.groovy
At first glance, it might appear that the above script will print out "Hello" followed by the name specified with the -n option. However, because no 'args' property was specified for the "n" option, the default of zero is assumed and any value provided after the -n flag is ignored. The specification of the -n flag results only in "true" (because the -n flag is present) when printed in this case as shown in the next screen snapshot.
This is easily fixed by explicitly specifying one argument in the option. The revised version of the script is shown next.
groovyArgsHelloWorld.groovy (Revised)
The simple addition of "args: 1" makes a big difference as shown in the next screen snapshot. The output indicates that the value for the -n option is now processed.
Not specifying the args property for certain options when there are multiple required options can lead the Groovy script's CliBuilder instance to think that some of the options are not specified. In the following script, the three options other than help do not have their args explicitly specified.
Because the number of options for the -c, -y, and -s options are not specified explicitly, this script does not work as hoped. Its output is shown in the next screen snapshot.
As the output demonstrates, the script's CliBuilder support cannot process the provided options because it doesn't expect there to be any values for the -c, -y, and -s options. Again, fixing this is easy by simply specifying that each option has 1 option rather than letting the zero arguments default confuse the issue. The revised script is shown next.
The additional explicit specification of "args: 1" for each of the three options does the trick!
In all these scripts, I did not need to explicitly specify the args for "help" because that flag was one for which no value was expected to be specified.
Groovy's CliBuilder supports makes it easy to provide more elegant command-line handling than is normally available via raw handling of Java arguments. This is especially useful when writing Groovy scripts with heavy command-line interaction.
The following script, groovyArgsHelloWorld.groovy, demonstrates this with the typical "Hello World" type example.
groovyArgsHelloWorld.groovy
#!/usr/bin/env groovy // // groovyArgsHelloWorld.groovy // // Simple Groovy script that demonstrates importance of declaring args property // explicitly in CliBuilder when the number of arguments for the option is // different than the default of zero arguments. // def cli = new CliBuilder() cli.with { h(longOpt: 'help', 'Help - Usage Information') n(longOpt: 'name', 'Name to say hello to', type: String, required: true) } def opt = cli.parse(args) if (!opt) return if (opt.h) cli.usage() println "Hello ${opt.n}"
At first glance, it might appear that the above script will print out "Hello" followed by the name specified with the -n option. However, because no 'args' property was specified for the "n" option, the default of zero is assumed and any value provided after the -n flag is ignored. The specification of the -n flag results only in "true" (because the -n flag is present) when printed in this case as shown in the next screen snapshot.
This is easily fixed by explicitly specifying one argument in the option. The revised version of the script is shown next.
groovyArgsHelloWorld.groovy (Revised)
#!/usr/bin/env groovy // // groovyArgsHelloWorld.groovy // // Simple Groovy script that demonstrates importance of declaring args property // explicitly in CliBuilder when the number of arguments for the option is // different than the default of zero arguments. // def cli = new CliBuilder() cli.with { h(longOpt: 'help', 'Help - Usage Information') n(longOpt: 'name', 'Name to say hello to', args: 1, type: String, required: true) } def opt = cli.parse(args) if (!opt) return if (opt.h) cli.usage() println "Hello ${opt.n}"
The simple addition of "args: 1" makes a big difference as shown in the next screen snapshot. The output indicates that the value for the -n option is now processed.
Not specifying the args property for certain options when there are multiple required options can lead the Groovy script's CliBuilder instance to think that some of the options are not specified. In the following script, the three options other than help do not have their args explicitly specified.
#!/usr/bin/env groovy // // groovyArgsMultiples.groovy // // Simple Groovy script that demonstrates importance of declaring args property // explicitly in CliBuilder when the number of arguments for the option is // different than the default of zero arguments. // def cli = new CliBuilder() cli.with { h(longOpt: 'help', 'Help - Usage Information') c(longOpt: 'city', 'City', type: String, required: true) y(longOpt: 'county', 'County', type: String, required: true) s(longOpt: 'state', 'State', type: String, required: true) } def opt = cli.parse(args) if (!opt) return if (opt.h) cli.usage() println "The location is ${opt.c}, ${opt.y}, ${opt.s}."
Because the number of options for the -c, -y, and -s options are not specified explicitly, this script does not work as hoped. Its output is shown in the next screen snapshot.
As the output demonstrates, the script's CliBuilder support cannot process the provided options because it doesn't expect there to be any values for the -c, -y, and -s options. Again, fixing this is easy by simply specifying that each option has 1 option rather than letting the zero arguments default confuse the issue. The revised script is shown next.
#!/usr/bin/env groovy // // groovyArgsMultiples.groovy // // Simple Groovy script that demonstrates importance of declaring args property // explicitly in CliBuilder when the number of arguments for the option is // different than the default of zero arguments. // def cli = new CliBuilder() cli.with { h(longOpt: 'help', 'Help - Usage Information') c(longOpt: 'city', 'City', type: String, args: 1, required: true) y(longOpt: 'county', 'County', type: String, args: 1, required: true) s(longOpt: 'state', 'State', type: String, args: 1, required: true) } def opt = cli.parse(args) if (!opt) return if (opt.h) cli.usage() println "The location is ${opt.c}, ${opt.y}, ${opt.s}."
The additional explicit specification of "args: 1" for each of the three options does the trick!
In all these scripts, I did not need to explicitly specify the args for "help" because that flag was one for which no value was expected to be specified.
Groovy's CliBuilder supports makes it easy to provide more elegant command-line handling than is normally available via raw handling of Java arguments. This is especially useful when writing Groovy scripts with heavy command-line interaction.
Sunday, July 25, 2010
JavaOne 2010: So Many Interesting Sessions, So Few Time Slots
JavaOne 2010 has so many presentations that I want to see that even my current alternatives list ("My Interests" in Schedule Builder) is full of presentations that sound compelling. The following presentations are currently in "My Interests" because I have (as of today) selected another presentation at the same time to "Enroll" in. I think this list speaks for itself. Of course, it is likely that I will change my mind several times between now and JavaOne and it's almost certain that I'll attend some of these. For now, though, these are the presentations I wish I could attend, but currently think I'll have to miss because there's something else also scheduled at the same time.
[CS] - [S318719] MySQL Performance Tuning Best Practices
[CS] - [S318720] You Know Databases, So How Hard Can MySQL Be?
[CS] - [S313185] Writing Stunning Cross-Platform Applications Using LWUIT
[CS] - [S314273] Groovy: To Infinity and Beyond
[CS] - [S314588] Java Context Dependency Injection and OSGi to Help with Modularity
[CS] - [S313657] Tips and Tricks for Building JavaFX Applications
[CS] - [S313504] Project Coin: Small Language Changes for JDK 7
[CS] - [S313431] Java Persistence API 2.0: An Overview
[CS] - [S314629] HTML5 and Java: Opening the Door to New Possibilities
[CS] - [S315885] Ten Easy Ways to Improve Java EE Performance
[CS] - [S314362] Time to Improve: JSR 310 Date and Time API
[CS] - [S314039] Google Web Toolkit (GWT) Cloud Applications: Fast, Fun, and Easier Than Ever
[CS] - [S312988] Unit Testing That's Not That Bad: Small Things That Make a Big Difference
[CS] - [S313520] Funky Java, Objective Scala Available 2:30-15:30 Parc 55, Cyril Magnin III
[CS] - [S313839] Using the File System API in JDK 7
[CS] - [S314492] Java Persistence API (JPA) 2.0 with EclipseLink
[BOF] - [S314416] The Collections Connection: Special "It Goes Up to the 11th" Edition
[BOF] - [S314190] The Better RESTful Web Services Framework: Jersey or Spring Framework
[CS] - [S313557] The Java EE 6 Programming Model Explained: How to Write Better Applications
[CS] - [S317739] Java Persistence API: Tips, Patterns, and Best Practices
[CS] - [S313248] Creating Lightweight Applications with Nothing but Vanilla Java EE 6
[CS] - [S314395] WebSockets Versus Comet: What Are the Differences, and Why Should I Care?
[CS] - [S312989] Comparing Groovy and Jruby
[CS] - [S313831] Breaking Up Is Hard to Do: Modularizing the JDK and Lessons Learned
[CS] - [S313189] Complete Tools Coverage for the Java EE 6 Platform
[CS] - [S314168] What's New in Enterprise JavaBean Technology
[PAN] - [S315029] Java API for Keyhole Markup Language
[CS] - [S314408] Java Puzzlers: Scraping the Bottom of the Barrel
[CS] - [S314696] The Secret Power of JavaFX Script
[CS] - [S314286] Dual-Pivot Quicksort and Timsort, or Sorting on Steroids
[CS] - [S314665] A Journey to the Center of the Java Universe
[CS] - [S314256] Securing RESTful Web Services in Java
[CS] - [S314491] Effective XML: Leveraging JAXB and SDO
[CS] - [S314424] Polyglot Programming in the Java Virtual Machine (JVM)
[BOF] - [S314475] 10 Years of The Java Specialists' Newsletter
[CS] - [S314822] Myths, Misconceptions, and Hidden Gems in Java Platform Security
[CS] - [S313960] JavaFX Graphics
[CS] - [S313501] The Merging Point of Android and Swing
[CS] - [S314405] Google Web Toolkit Versus Rich Ajax Platform: Which Java-Based Ajax Is for You?
[HOL] - [S313277] Beginning with the Java EE 6 Platform
[HOL] - [S313674] Building a JavaFX-Based Monitoring App, Using the GlassFish REST Monitoring API
[CS] - [S314403] Java Transaction API Caching: Consistent, Distributed, and Coherent
[CS] - [S314385] Ninety-Seven Things Every Programmer Should Know
[CS] - [S313005] Domain-Specific Language Versus Library API Shootout
[CS] - [S314359] Remote Compiling and Performance Analysis Using the NetBeans IDE
[CS] - [S313819] What's Happening with My Application?: Java Virtual Machine Monitoring Tool
[CS] - [S314154] Writing Domain-Specific Languages (DSLs), Using Groovy
[CS] - [S314334] Static Analysis in Search for Performance Antipatterns
[CS] - [S314226] SomeSQL: Combining NoSQL Technologies with Existing RDBMS Architectures
The first acronyms listed on each line in square braces have the following meanings: BOF (Birds of a Feather), CS (Conference Session), ESS (Executive Solution Session), GS (General Session), HOL (Hands-On Lab), KEY (Keynotes Session), and PAN (Panel).
The alternative sessions listed above are the result of my first run-through with the Schedule Builder and that list does not even include potential OracleDevelop presentations of interest related to subjects such as Oracle Fusion, JDeveloper, Java in the Oracle Database, Oracle ADF, etc.
There are so many interesting-sounding presentations to choose from at JavaOne 2010 that it is very difficult to decide on which to attend.
[CS] - [S318719] MySQL Performance Tuning Best Practices
[CS] - [S318720] You Know Databases, So How Hard Can MySQL Be?
[CS] - [S313185] Writing Stunning Cross-Platform Applications Using LWUIT
[CS] - [S314273] Groovy: To Infinity and Beyond
[CS] - [S314588] Java Context Dependency Injection and OSGi to Help with Modularity
[CS] - [S313657] Tips and Tricks for Building JavaFX Applications
[CS] - [S313504] Project Coin: Small Language Changes for JDK 7
[CS] - [S313431] Java Persistence API 2.0: An Overview
[CS] - [S314629] HTML5 and Java: Opening the Door to New Possibilities
[CS] - [S315885] Ten Easy Ways to Improve Java EE Performance
[CS] - [S314362] Time to Improve: JSR 310 Date and Time API
[CS] - [S314039] Google Web Toolkit (GWT) Cloud Applications: Fast, Fun, and Easier Than Ever
[CS] - [S312988] Unit Testing That's Not That Bad: Small Things That Make a Big Difference
[CS] - [S313520] Funky Java, Objective Scala Available 2:30-15:30 Parc 55, Cyril Magnin III
[CS] - [S313839] Using the File System API in JDK 7
[CS] - [S314492] Java Persistence API (JPA) 2.0 with EclipseLink
[BOF] - [S314416] The Collections Connection: Special "It Goes Up to the 11th" Edition
[BOF] - [S314190] The Better RESTful Web Services Framework: Jersey or Spring Framework
[CS] - [S313557] The Java EE 6 Programming Model Explained: How to Write Better Applications
[CS] - [S317739] Java Persistence API: Tips, Patterns, and Best Practices
[CS] - [S313248] Creating Lightweight Applications with Nothing but Vanilla Java EE 6
[CS] - [S314395] WebSockets Versus Comet: What Are the Differences, and Why Should I Care?
[CS] - [S312989] Comparing Groovy and Jruby
[CS] - [S313831] Breaking Up Is Hard to Do: Modularizing the JDK and Lessons Learned
[CS] - [S313189] Complete Tools Coverage for the Java EE 6 Platform
[CS] - [S314168] What's New in Enterprise JavaBean Technology
[PAN] - [S315029] Java API for Keyhole Markup Language
[CS] - [S314408] Java Puzzlers: Scraping the Bottom of the Barrel
[CS] - [S314696] The Secret Power of JavaFX Script
[CS] - [S314286] Dual-Pivot Quicksort and Timsort, or Sorting on Steroids
[CS] - [S314665] A Journey to the Center of the Java Universe
[CS] - [S314256] Securing RESTful Web Services in Java
[CS] - [S314491] Effective XML: Leveraging JAXB and SDO
[CS] - [S314424] Polyglot Programming in the Java Virtual Machine (JVM)
[BOF] - [S314475] 10 Years of The Java Specialists' Newsletter
[CS] - [S314822] Myths, Misconceptions, and Hidden Gems in Java Platform Security
[CS] - [S313960] JavaFX Graphics
[CS] - [S313501] The Merging Point of Android and Swing
[CS] - [S314405] Google Web Toolkit Versus Rich Ajax Platform: Which Java-Based Ajax Is for You?
[HOL] - [S313277] Beginning with the Java EE 6 Platform
[HOL] - [S313674] Building a JavaFX-Based Monitoring App, Using the GlassFish REST Monitoring API
[CS] - [S314403] Java Transaction API Caching: Consistent, Distributed, and Coherent
[CS] - [S314385] Ninety-Seven Things Every Programmer Should Know
[CS] - [S313005] Domain-Specific Language Versus Library API Shootout
[CS] - [S314359] Remote Compiling and Performance Analysis Using the NetBeans IDE
[CS] - [S313819] What's Happening with My Application?: Java Virtual Machine Monitoring Tool
[CS] - [S314154] Writing Domain-Specific Languages (DSLs), Using Groovy
[CS] - [S314334] Static Analysis in Search for Performance Antipatterns
[CS] - [S314226] SomeSQL: Combining NoSQL Technologies with Existing RDBMS Architectures
The first acronyms listed on each line in square braces have the following meanings: BOF (Birds of a Feather), CS (Conference Session), ESS (Executive Solution Session), GS (General Session), HOL (Hands-On Lab), KEY (Keynotes Session), and PAN (Panel).
The alternative sessions listed above are the result of my first run-through with the Schedule Builder and that list does not even include potential OracleDevelop presentations of interest related to subjects such as Oracle Fusion, JDeveloper, Java in the Oracle Database, Oracle ADF, etc.
There are so many interesting-sounding presentations to choose from at JavaOne 2010 that it is very difficult to decide on which to attend.
Saturday, July 24, 2010
How Much Time to Spend on JavaFX at JavaOne 2010?
For any conference that one attends, one of the difficult decisions is which presentations to attend. This is particularly problematic when there are some really interesting-sounding presentations held during the same hour. I find that I often change my plans for which presentations to see based on earlier presentations in the same conference. A presentation (often an opening keynote) may stir my interest in a topic I had entered the conference not knowing or not caring much about. On the other hand, an early presentation could equally dissuade me from attending further presentations on the same topic because I may realize that the subject is not as relevant to me as I thought it would be.
I am already struggling with this for JavaOne 2010, particularly when it comes to JavaFX presentations. On the one hand, there are some abstracts for JavaFX-related presentations that look interesting. On the other, I am still a little bitter about my time wasted looking into JavaFX after 2007 JavaOne and 2008 JavaOne. I realize that I can only blame myself for any wasted time on a third failed attempt at learning to love JavaFX. JavaOne 2010 gives me the opportunity to learn more about JavaFX in a potentially optimized way, reducing the risk of time wasted. That being said, I could end up pretty disappointed if I miss some really good presentations to attend JavaFX presentations and then realize either during the conference or (even worse) realize later that JavaFX does not have a future.
This isn't to say that I wouldn't attend a presentation on something I don't know a lot about, because I would. I feel that one of the best things about attending a conference is the ability in an hour or two to quickly identify whether something is worth further effort. JavaFX, though, is different because I've already been burned by what I believe was hyperbole. It's one thing to spend an hour in a session learning about something and realizing it has no immediate benefit for me. That's actually positive because I only needed to spend an hour to learn that. For JavaFX, I already have incurred a large tab for the time spent learning about it with little satisfaction. There has been a huge net opportunity cost associated with time spent with JavaFX so far.
Max Katz, in his blog post JavaFX... does it have a future? (Sys-Con Media version), provides significant additional information for me to consider as I try to resolve the dilemma of deciding how much time to spend on JavaFX at JavaOne. It is obvious from the tone and content of the writing in this post that Katz is an advocate of JavaFX. Perhaps even more significantly in terms of considering JavaFX presentations to attend at JavaOne 2010, Katz is presenting at JavaOne 2010 on Enterprise JavaFX Applications with CDI (JSR299). With all of this in mind, I found some quotes in this blog post particularly interesting. I look at some of them in detail here in the context of trying to determine what number of JavaFX presentations to attend and which ones to attend.
First off, I appreciate that Katz is a realistic. Some evangelists for a particular technology can see no wrong (or at least not admit any wrong) with their favorite technology. This is, of course, ridiculous because nothing is perfect, everything has its flaws, everything has problems it fits better than others, and the natural difference of human beings' opinions means that nothing will ever be "perfect" for everyone. In my opinion, this early quote from Katz's blog post provides him some credibility:
Katz lists several benefits (the good) of JavaFX (such as "power" and "ease of use") first and states:
Katz fairly addresses one of JavaFX's best known problems (the bad): deployment issues. He covers this pretty thoroughly and says exactly what needs to be done to remedy this: "Make it as simple and transparent as running a Flash application." Well said.
I agree with Katz when he states that developers today need to learn new things all the time, so learning JavaFX Script as a new language should not be a big deal. As long as everyone understands it is a new language, I think this is a fair statement. My problem has been when anyone has pushed JavaFX as "Java." You cannot have it both ways. Is it Java or is it something else? It may be Java in the same sense that JRuby and Groovy are Java, but Groovy is significantly more Java-like in syntax than is JavaFX Script. Because it's not Java in terms of syntax and because there's no JSR (that I'm aware of) for it, its last hold on "being Java" seems to be the ability to run in the JVM, but every language and its brother seems to be doing that these days.
Katz makes several good points that I am skipping here (but I recommend reading his entire blog post if you have any interest in JavaFX whatsoever). His conclusion, I believe, is objective and spot-on:
Katz's blog post increased my interest in attending his JavaOne 2010 presentation. The two main reasons that I might not attend it are that there are several really good presentations of high level of interest to me and his topic is not really focused as much on the introduction to and examination of the future of JavaFX as I probably need and want. Katz's presentation is scheduled for Monday, September 20, at 1 pm, at Golden Gate 2 in the Hilton San Francisco. I currently have "Advanced Java API for RESTful Web Services (JAX-RS)" scheduled for that slot. It's still a difficult dilemma because I am now really interested in Katz's presentation, but I think it's safer to bet my time and attention of JAX-RS and REST than it is on to bet them on JavaFX. I am fairly confident what I learn from a JAX-RS/REST presentation will be of benefit for some time to come.
I hope that JavaOne 2010 provide some direction that allows us to be comfortable knowing how much time and effort to invest in it. If I have a better idea of what JavaFX is going to become, then I can better make the decision about how much time to invest in JavaFX and what projects to build around it.
I am already struggling with this for JavaOne 2010, particularly when it comes to JavaFX presentations. On the one hand, there are some abstracts for JavaFX-related presentations that look interesting. On the other, I am still a little bitter about my time wasted looking into JavaFX after 2007 JavaOne and 2008 JavaOne. I realize that I can only blame myself for any wasted time on a third failed attempt at learning to love JavaFX. JavaOne 2010 gives me the opportunity to learn more about JavaFX in a potentially optimized way, reducing the risk of time wasted. That being said, I could end up pretty disappointed if I miss some really good presentations to attend JavaFX presentations and then realize either during the conference or (even worse) realize later that JavaFX does not have a future.
This isn't to say that I wouldn't attend a presentation on something I don't know a lot about, because I would. I feel that one of the best things about attending a conference is the ability in an hour or two to quickly identify whether something is worth further effort. JavaFX, though, is different because I've already been burned by what I believe was hyperbole. It's one thing to spend an hour in a session learning about something and realizing it has no immediate benefit for me. That's actually positive because I only needed to spend an hour to learn that. For JavaFX, I already have incurred a large tab for the time spent learning about it with little satisfaction. There has been a huge net opportunity cost associated with time spent with JavaFX so far.
Max Katz, in his blog post JavaFX... does it have a future? (Sys-Con Media version), provides significant additional information for me to consider as I try to resolve the dilemma of deciding how much time to spend on JavaFX at JavaOne. It is obvious from the tone and content of the writing in this post that Katz is an advocate of JavaFX. Perhaps even more significantly in terms of considering JavaFX presentations to attend at JavaOne 2010, Katz is presenting at JavaOne 2010 on Enterprise JavaFX Applications with CDI (JSR299). With all of this in mind, I found some quotes in this blog post particularly interesting. I look at some of them in detail here in the context of trying to determine what number of JavaFX presentations to attend and which ones to attend.
First off, I appreciate that Katz is a realistic. Some evangelists for a particular technology can see no wrong (or at least not admit any wrong) with their favorite technology. This is, of course, ridiculous because nothing is perfect, everything has its flaws, everything has problems it fits better than others, and the natural difference of human beings' opinions means that nothing will ever be "perfect" for everyone. In my opinion, this early quote from Katz's blog post provides him some credibility:
Don’t get me wrong, JavaFX is very far from perfect. It has it’s problems and challenges (listed below) and its future is hanging on life support right now.I believe my previous blog posts on JavaFX prove that I am in agreement here. This is precisely why it's difficult for me to justify time spent on JavaFX (including in JavaOne presentations): I just cannot be sure that it's going to be around (at least in a form acceptable to me) for more than the near-term future.
Katz lists several benefits (the good) of JavaFX (such as "power" and "ease of use") first and states:
I have been working with JSF (JavaServer Faces) since its inception and I can tell you that using JavaFX Script to build the UI is probably simpler than using JSF.I have no doubt that this is true, but unfortunately being simpler than JavaServer Faces is the purview of just about every Java-based framework out there and non-Java Flex/ActionScript is, in my opinion, significantly less complicated than JSF.
Katz fairly addresses one of JavaFX's best known problems (the bad): deployment issues. He covers this pretty thoroughly and says exactly what needs to be done to remedy this: "Make it as simple and transparent as running a Flash application." Well said.
I agree with Katz when he states that developers today need to learn new things all the time, so learning JavaFX Script as a new language should not be a big deal. As long as everyone understands it is a new language, I think this is a fair statement. My problem has been when anyone has pushed JavaFX as "Java." You cannot have it both ways. Is it Java or is it something else? It may be Java in the same sense that JRuby and Groovy are Java, but Groovy is significantly more Java-like in syntax than is JavaFX Script. Because it's not Java in terms of syntax and because there's no JSR (that I'm aware of) for it, its last hold on "being Java" seems to be the ability to run in the JVM, but every language and its brother seems to be doing that these days.
Katz makes several good points that I am skipping here (but I recommend reading his entire blog post if you have any interest in JavaFX whatsoever). His conclusion, I believe, is objective and spot-on:
There is still time to make JavaFX successful, but the time is running out. First, fix the deployment issue as soon as possible. ... Second, Oracle needs to make it very clear what its plans are for JavaFX (maybe at JavaOne 2010?). ... I think Oracle has 6-12 months at the most to try and revive JavaFX. If nothing happens by then (which would be about 4 years since the technology was announced), we just might as well close the door on JavaFX.There's nothing I can add to that. Probably the only debatable piece is the timeframe he provides of 6 to 12 months. It might be longer (say 18 months), but it could be that Katz is right on. With the seemingly increasing negative news regarding JavaFX and the strengthening of its competitors' positions, I do think there is a limited window for Oracle to turn things around for JavaFX in terms of it ever being mainstream popular. There's always a possibility that it's already too late.
Katz's blog post increased my interest in attending his JavaOne 2010 presentation. The two main reasons that I might not attend it are that there are several really good presentations of high level of interest to me and his topic is not really focused as much on the introduction to and examination of the future of JavaFX as I probably need and want. Katz's presentation is scheduled for Monday, September 20, at 1 pm, at Golden Gate 2 in the Hilton San Francisco. I currently have "Advanced Java API for RESTful Web Services (JAX-RS)" scheduled for that slot. It's still a difficult dilemma because I am now really interested in Katz's presentation, but I think it's safer to bet my time and attention of JAX-RS and REST than it is on to bet them on JavaFX. I am fairly confident what I learn from a JAX-RS/REST presentation will be of benefit for some time to come.
I hope that JavaOne 2010 provide some direction that allows us to be comfortable knowing how much time and effort to invest in it. If I have a better idea of what JavaFX is going to become, then I can better make the decision about how much time to invest in JavaFX and what projects to build around it.
Thursday, July 22, 2010
JavaOne 2010 Schedule Builder is Now Available
I previously posted that I was looking forward to JavaOne 2010 and this is even more true today. Like Mitch Pronschinske, the trouble now is determining which presentations to attend. This "problem" is complicated by the coexistence of Oracle OpenWorld and Oracle Develop with JavaOne 2010. There are roughly 2400 different options for sessions, conferences, keynotes, Birds of a Feather (BOF) sessions, and so forth between the three simultaneous conferences. Although I'm likely to attend JavaOne presentations the majority of the time, there are several Oracle Develop presentations that have caught my attention and I may even attend a few Oracle OpenWorld presentations. It was a very pleasant surprise when I went to view the Content Catalog this afternoon and saw that it had been replaced by the Schedule Builder! I received a few hours later stating its availability.
There originally was a single online Content Catalog tool for all three conferences. At first this catalog only had the sessions without dates and times and then dates and times were added. When I selected the "JavaOne" stream on the online Content Catalog, it reported the availability of 249 conference sessions, 111 BOFs, 19 hands-on labs, 8 panels, and two JavaOne-specific keynotes.
The first keynote specific to JavaOne is Thomas Kurian's (Oracle) and Doug Fisher's (Intel) "JavaOne Keynote" on Monday, September 20, from 5:45 pm to 7:15 pm. The other JavaOne-specific keynote is called "The Java Frontier" and will be held Thursday, September 23, from 9 am to 10:30 am. Other interesting streams that were displayed on the Content Catalog included MySQL Sunday (which seems to imply Oracle has more interest in MySQL's future than some had feared), Oracle Develop, and the several OpenWorld streams.
Even with the dates and times available, it was still difficult to get my head around which sessions were conflicting. Fortunately, ScheduleBuilder is now available for "registered attendees of Oracle OpenWorld, JavaOne, and Oracle Develop 2010 to pre-enroll in conference events." Once you log in to Schedule Builder with the username and password used during JavaOne registration, you can click on the link "Start Building my Agenda." In the "Stream/Track" drop-down, you can select the "JavaOne" stream or a particular track in JavaOne. When I set the "Search Criteria" to "JavaOne" (Stream/Track) for "All" (Events) and view "Session" (View), there are 395 matching results. While Content Catalog had only allowed a person to see 50 results at a time, Schedule Builder allows one to see up to 200 results at a time.
I have started enrolling in presentations that look most interesting to me. I'm already finding many of my most anticipated presentations at the same time. The Schedule Builder tool identifies when a newly chosen ("Enroll") presentation is in conflict with one that is already scheduled and provides flexible choices as to which to keep (previously enrolled or newly enrolled) and what to do with the one not scheduled (either remove altogether or add it to one's interests). I am particularly interested in the REST-related presentations and the JVM languages presentations and have already found many of them in conflict with one another.
I may post my tentative agenda once it is assembled along with the presentations saved in my interests section. However, I never actually attend exactly the same presentations as originally planned so it will almost certainly change some.
There originally was a single online Content Catalog tool for all three conferences. At first this catalog only had the sessions without dates and times and then dates and times were added. When I selected the "JavaOne" stream on the online Content Catalog, it reported the availability of 249 conference sessions, 111 BOFs, 19 hands-on labs, 8 panels, and two JavaOne-specific keynotes.
The first keynote specific to JavaOne is Thomas Kurian's (Oracle) and Doug Fisher's (Intel) "JavaOne Keynote" on Monday, September 20, from 5:45 pm to 7:15 pm. The other JavaOne-specific keynote is called "The Java Frontier" and will be held Thursday, September 23, from 9 am to 10:30 am. Other interesting streams that were displayed on the Content Catalog included MySQL Sunday (which seems to imply Oracle has more interest in MySQL's future than some had feared), Oracle Develop, and the several OpenWorld streams.
Even with the dates and times available, it was still difficult to get my head around which sessions were conflicting. Fortunately, ScheduleBuilder is now available for "registered attendees of Oracle OpenWorld, JavaOne, and Oracle Develop 2010 to pre-enroll in conference events." Once you log in to Schedule Builder with the username and password used during JavaOne registration, you can click on the link "Start Building my Agenda." In the "Stream/Track" drop-down, you can select the "JavaOne" stream or a particular track in JavaOne. When I set the "Search Criteria" to "JavaOne" (Stream/Track) for "All" (Events) and view "Session" (View), there are 395 matching results. While Content Catalog had only allowed a person to see 50 results at a time, Schedule Builder allows one to see up to 200 results at a time.
I have started enrolling in presentations that look most interesting to me. I'm already finding many of my most anticipated presentations at the same time. The Schedule Builder tool identifies when a newly chosen ("Enroll") presentation is in conflict with one that is already scheduled and provides flexible choices as to which to keep (previously enrolled or newly enrolled) and what to do with the one not scheduled (either remove altogether or add it to one's interests). I am particularly interested in the REST-related presentations and the JVM languages presentations and have already found many of them in conflict with one another.
I may post my tentative agenda once it is assembled along with the presentations saved in my interests section. However, I never actually attend exactly the same presentations as originally planned so it will almost certainly change some.
Monday, July 19, 2010
split Command for DOS/Windows Via Groovy
One of the commands that I miss most from Linux when working in Windows/DOS environments is the split command. This extremely handy command allows one to split a large file into multiple smaller files determined by the specification of either by number of lines or number of bytes (or kilobytes or megabytes) desired for the smaller files. There are many uses for such functionality including fitting files onto certain media, making files "readable" by applications with file length restrictions, and so on. Unfortunately, I'm not aware of a split equivalent for Windows or DOS. PowerShell can be scripted to do something like this, but that implementation is specific to PowerShell. There are also third-party products available that perform similar functionality. However, these existing solutions leave just enough to be desired that I have the motivation to implement a split equivalent in Groovy and that is the subject of this post. Because Groovy runs on the JVM, this implementation could be theoretically run on any operating system with a modern Java Virtual Machine implementation.
To test and demonstrate the Groovy-based split script, some type of source file is required. I'll use Groovy to easily generate this source file. The following simple Groovy script, buildFileToSplit.groovy, creates a simple text file that can be split.
This simple script uses Groovy's implicitly available "args" handle to access command-line arguments for the buildFileToSplit.groovy script. It then creates a single file of size based on the provided number of lines argument. Each line is largely unoriginal and states "This is line #" followed by the line number. It's not a fancy source file, but it works for the splitting example. The next screen snapshot shows it run and its output.
The generated source.txt file looks like this (only beginning and ending of it is shown here):
There is now a source file available to be split. This script is significantly longer because I have made it check for more error conditions, because it needs to handle more command-line parameters, and simply because it does more than the script that generated the source file. The script, simply called split.groovy, is shown next:
This script could be optimized and better modularized, but it fulfills its purpose of demonstrating how Groovy provides a nice approach for implementing platform-independent utility scripts.
The next screen snapshot demonstrates the script's use of Groovy's built-in CLI support.
The next two screen snapshots demonstrate splitting the source file into smaller files by line numbers and by bytes respectively (and using different suffix and file name options). The first image demonstrates that three output files are generated when split into 100 lines (250 lines in source file). The -a option specifies that four integer places will be in the filename. Unlike the Linux split, this script does not guarantee that the user-provided number of integers is sufficient to cover the number of necessary output files.
The second image (next image) shows the script splitting the source file based on number of bytes and using a different filename and only two integers for the numbering.
As mentioned above, this script is a "rough cut." It could be improved in terms of the code itself as well as in terms of functionality (extended to better support binary formats and to make sure file name suffixes are sufficiently long for number of output files). However, the script here does demonstrate one of my favorite uses of Groovy: to write platform-independent scripts using familiar Java and Groovy libraries (SDK and GDK).
To test and demonstrate the Groovy-based split script, some type of source file is required. I'll use Groovy to easily generate this source file. The following simple Groovy script, buildFileToSplit.groovy, creates a simple text file that can be split.
#!/usr/bin/env groovy // // buildFileToSplit.groovy // // Accepts single argument for number of lines to be written to generated file. // If no number of lines is specified, uses default of 100,000 lines. // if (!args) { println "\n\nUsage: buildFileToSplit.groovy fileName lineCount\n" println "where fileName is name of file to be generated and lineCount is the" println "number of lines to be placed in the generated file." System.exit(-1) } fileName = args[0] numberOfLines = args.length > 1 ? args[1] as Integer : 100000 file = new File(fileName) // erases output file if it already existed file.delete() 1.upto(numberOfLines, {file << "This is line #${it}.\n"})
This simple script uses Groovy's implicitly available "args" handle to access command-line arguments for the buildFileToSplit.groovy script. It then creates a single file of size based on the provided number of lines argument. Each line is largely unoriginal and states "This is line #" followed by the line number. It's not a fancy source file, but it works for the splitting example. The next screen snapshot shows it run and its output.
The generated source.txt file looks like this (only beginning and ending of it is shown here):
This is line #1. This is line #2. This is line #3. This is line #4. This is line #5. This is line #6. This is line #7. This is line #8. This is line #9. This is line #10. . . . This is line #239. This is line #240. This is line #241. This is line #242. This is line #243. This is line #244. This is line #245. This is line #246. This is line #247. This is line #248. This is line #249. This is line #250.
There is now a source file available to be split. This script is significantly longer because I have made it check for more error conditions, because it needs to handle more command-line parameters, and simply because it does more than the script that generated the source file. The script, simply called split.groovy, is shown next:
#!/usr/bin/env groovy // // split.groovy // // Split single file into multiple files similarly to how Unix/Linux split // command works. This version of the script is intended for text files only. // // This script does differ from the Linux/Unix variant in certain ways. For // example, this script's output messages differ in several cases and this // script requires that the name of the file being split is provided as a // command-line argument rather than providing the option to provide it as // standard input. This script also provides a "-v" ("--version") option not // advertised for the Linux/Unix version. // // CAUTION: This script is intended only as an illustration of using Groovy to // emulate the Unix/Linux script command. It is not intended for production // use as-is. This script is designed to make back-up copies of files generated // from the splitting of a single source file, but only one back-up version is // created and is overridden by any further requests. // // http://marxsoftware.blogspot.com/ // import java.text.NumberFormat NEW_LINE = System.getProperty("line.separator") // // Use Groovy's CliBuilder for command-line argument processing // def cli = new CliBuilder(usage: 'split [OPTION] [INPUT [PREFIX]]') cli.with { h(longOpt: 'help', 'Usage Information') a(longOpt: 'suffix-length', type: Number, 'Use suffixes of length N (default is 2)', args: 1) b(longOpt: 'bytes', type: Number, 'Size of each output file in bytes', args: 1) l(longOpt: 'lines', type: Number, 'Number of lines per output file', args: 1) t(longOpt: 'verbose', 'Print diagnostic to standard error just before each output file is opened', args: 0) v(longOpt: 'version', 'Output version and exit', args: 0) } def opt = cli.parse(args) if (!opt || opt.h) {cli.usage(); return} if (opt.v) {println "Version 0.1 (July 2010)"; return} if (!opt.b && !opt.l) { println "Specify length of split files with either number of bytes or number of lines" cli.usage() return } if (opt.a && !opt.a.isNumber()) {println "Suffix length must be a number"; cli.usage(); return} if (opt.b && !opt.b.isNumber()) {println "Files size in bytes must be a number"; cli.usage(); return} if (opt.l && !opt.l.isNumber()) {println "Lines number must be a number"; cli.usage(); return} // // Determine whether split files will be sized by number of lines or number of bytes // private enum LINES_OR_BYTES_ENUM { BYTES, LINES } bytesOrLines = LINES_OR_BYTES_ENUM.LINES def suffixLength = opt.a ? opt.a.toBigInteger() : 2 if (suffixLength < 0) { suffixLength = 2 } def numberLines = opt.l ? opt.l.toBigInteger() : 0 def numberBytes = opt.b ? opt.b.toBigInteger() : 0 if (!numberLines && !numberBytes) { println "File size must be specified in either non-zero bytes or non-zero lines." return } else if (numberLines && numberBytes) { println "Ambiguous: must specify only number of lines or only number of bytes" return } else if (numberBytes) { bytesOrLines = LINES_OR_BYTES_ENUM.BYTES } else { bytesOrLines = LINES_OR_BYTES_ENUM.LINES } def verboseMode = opt.t if (verboseMode) { print "Creating output files of size " print "${numberLines ?: numberBytes} ${numberLines ? 'lines' : 'bytes'} each " println "and outfile file suffix size of ${suffixLength}." } fileSuffixFormat = NumberFormat.getInstance() fileSuffixFormat.setMinimumIntegerDigits(suffixLength) fileSuffixFormat.setGroupingUsed(false) filename = "" candidateFileName = opt.arguments()[0] if (candidateFileName == null) { println "No source file was specified for splitting." System.exit(-2) } else if (candidateFileName.startsWith("-")) { println "Ignoring option ${candidateFileName} and exiting." System.exit(-3) } else { println "Processing ${candidateFileName} as source file name." filename = candidateFileName } def prefix = opt.arguments().size() > 1 ? opt.arguments()[1] : "x" try { file = new File(filename) if (!file.exists()) { println "Source file ${filename} is not a valid source file." System.exit(-4) } int fileCounter = 1 firstFileName = "${prefix}${fileSuffixFormat.format(0)}" if (verboseMode) { System.err.println "Creating file ${firstFileName}..." } outFile = createFile(firstFileName) if (bytesOrLines == LINES_OR_BYTES_ENUM.BYTES) { int byteCounter = 0 file.eachByte { if (byteCounter < numberBytes) { outFile << new String(it) } else { nextOutputFileName = "${prefix}${fileSuffixFormat.format(fileCounter)}" if (verboseMode) { System.err.println "Creating file ${nextOutputFileName}..." } outFile = createFile(nextOutputFileName) outFile << new String(it) fileCounter++ byteCounter = 0 } byteCounter++ } } else { int lineCounter = 0 file.eachLine { if (lineCounter < numberLines) { outFile << it << NEW_LINE } else { nextOutputFileName = "${prefix}${fileSuffixFormat.format(fileCounter)}" if (verboseMode) { System.err.println "Creating file ${nextOutputFileName}..." } outFile = createFile(nextOutputFileName) outFile << it << NEW_LINE fileCounter++ lineCounter = 0 } lineCounter++ } } } catch (FileNotFoundException fnfEx) { println System.properties println "${fileName} is not a valid source file: ${fnfEx.toString()}" System.exit(-3) } catch (NullPointerException npe) { println "NullPointerException encountered: ${npe.toString()}" System.exit(-4) } /** * Create a file with the provided file name. * * @param fileName Name of file to be created. * @return File created with the provided name; null if provided name is null or * empty. */ def File createFile(String fileName) { if (!fileName) { println "Cannot create a file from a null or empty filename." return null } outFile = new File(fileName) if (outFile.exists()) { outFile.renameTo(new File(fileName + ".bak")) outFile = new File(fileName) } return outFile }
This script could be optimized and better modularized, but it fulfills its purpose of demonstrating how Groovy provides a nice approach for implementing platform-independent utility scripts.
The next screen snapshot demonstrates the script's use of Groovy's built-in CLI support.
The next two screen snapshots demonstrate splitting the source file into smaller files by line numbers and by bytes respectively (and using different suffix and file name options). The first image demonstrates that three output files are generated when split into 100 lines (250 lines in source file). The -a option specifies that four integer places will be in the filename. Unlike the Linux split, this script does not guarantee that the user-provided number of integers is sufficient to cover the number of necessary output files.
The second image (next image) shows the script splitting the source file based on number of bytes and using a different filename and only two integers for the numbering.
As mentioned above, this script is a "rough cut." It could be improved in terms of the code itself as well as in terms of functionality (extended to better support binary formats and to make sure file name suffixes are sufficiently long for number of output files). However, the script here does demonstrate one of my favorite uses of Groovy: to write platform-independent scripts using familiar Java and Groovy libraries (SDK and GDK).
The Continuing Struggles of JavaFX
In the post O JavaFX, What Art Thou? I publicly posted questions about JavaFX that largely pertain to its future. As I stated in that post, I had felt somewhat deceived by Sun's overhasty JavaFX marketing at 2007 JavaOne and 2008 JavaOne and wasted more time than I like to waste looking into what JavaFX was (or in most cases, was supposed to become). I have hesitated to really invest time and effort into it a third time until I feel better about its future. Since posting O JavaFX,What Art Thou? there's been little to make me feel more optimistic about JavaFX's future. This week, there was a major piece of bad press for JavaFX.
In his blog post JavaFX is a Train Wreck, Kirill Grouchnikov expresses frustration at JavaFX not delivering on early promises to make it easy for developers and designers to work together to build compelling user interfaces with JavaFX. His feeling is that there are next to no good examples of real JavaFX applications that take advantage of designer skills and asserts that JavaFX seems to be of some interest to developers but is not very interesting to designers. Kirill is not the first to express dissatisfaction with JavaFX. However, his critique is especially significant because of his obvious experience developing user interfaces and because he seems to have really wanted JavaFX to be something special. This blog post apparently hit a nerve as it quickly soared into the DZone Top Links after I initially saw it featured on Java.net's "Java Today" section (for July 15) and other bloggers have referenced it.
In his blog post JavaFX is a Train Wreck, Kirill Grouchnikov expresses frustration at JavaFX not delivering on early promises to make it easy for developers and designers to work together to build compelling user interfaces with JavaFX. His feeling is that there are next to no good examples of real JavaFX applications that take advantage of designer skills and asserts that JavaFX seems to be of some interest to developers but is not very interesting to designers. Kirill is not the first to express dissatisfaction with JavaFX. However, his critique is especially significant because of his obvious experience developing user interfaces and because he seems to have really wanted JavaFX to be something special. This blog post apparently hit a nerve as it quickly soared into the DZone Top Links after I initially saw it featured on Java.net's "Java Today" section (for July 15) and other bloggers have referenced it.
JavaWorld blogger Josh Fruhlinger observed that Kirill's post and the user feedback to his post provide a summary of the trouble with JavaFX, in one tidy blog comment thread. Fruhlinger points out that the feedback comments provide a nice overview of various problems Java developers (and any designers who have tried it) have run into when using JavaFX (such as bitterness about Sun reallocating people from working on Swing to working on JavaFX [mentioned in a different Kirill Grouchnikov post]).
In How Can Oracle Make JavaFX More Popular, James Sugrue also references the JavaFX is a Train Wreck post and asks what Oracle can do to improve JavaFX's popularity. This post is a question intended for developers to answer and the feedback is insightful. Many want to simply "kill" JavaFX and have Oracle reallocate resources to Swing or other technologies. Others want to see it open sourced. Based on the feedback to both the original Train Wreck post and to this Sugrue post, it seems that Java developers in general do not have a positive perception of JavaFX or its future. That's daunting news because it means a reputation is being established that may be difficult to tear down.
Shai Almog has posted a poll based off the just-mentioned DZone poll specifically targeted at mobile developers. Similarly called How Can Oracle Make JavaFX More Popular, Shai asks how JavaFX can be more popular among mobile developers and I think Ryan de Laplante's answer in the feedback probably sums up the answer best: "JavaFX Mobile needs to be available. Where is it? Not on Android. Not on iPhone. Not on BlackBerry. Not on Palm Pre." I admit that I'd probably be more likely to get into JavaFX if it worked on my Droid. This is what I was poking at when I asked Does JavaFX Have a Niche?
Being called a "Train Wreck" wasn't JavaFX's only exposure this week. The two top DZone links as I write this are related to a petition to Oracle requesting that JavaFX be open sourced: Stephen Chin's Petition to Open Source JavaFX (both comments so far favor Pivot over JavaFX) and the original Petition to Open Source JavaFX. Open source success depends heavily on community involvement and/or a strong sponsoring organization, so I'm not certain that open sourcing JavaFX would improve its future. As I stated in the post O JavaFX, What Art Thou?, JavaFX cannot make the argument that it's standard or any more "Java" than other open source frameworks such as Pivot. Being open source does not magically save projects. Oracle could open source JavaFX as it has done with TopLink Essentials/EclipseLink and ADF Faces (Apache MyFaces Trinidad) and several other projects, but my current speculation (and that's all it is) is that JavaFX is more likely to be taken the same direction as Oracle's Application Developer Framework (ADF).
It wasn't all negative this week for JavaFX. Early in the week, the Sun Developer Network (AKA java.sun.com) featured the article Stylin' with JavaFX. There is a small number of ardent JavaFX proponents in the blogosphere and the author of this article, Jim Weaver, may be at the top of that list. The article's introduction talks about JavaFX's CSS support that is meant to "encourage this collaboration" between "designers and developers." The irony, of course, is that it is the lack of greater support for collaboration between designers and developers that led to the "Train Wreck" post.
Despite the enthusiastic and valiant efforts of a seemingly small number of developers who like to use JavaFX, the momentum seems to be moving away from JavaFX. Perhaps it never had momentum because it took so long to deliver anything of real value from its initial announcement at 2007 JavaOne. For now, I cannot justify spending any more time or effort learning JavaFX. Perhaps things will turn around for JavaFX and it will be worth a third look, but I wouldn't bet much on that at this time. JavaOne 2010 may be the next serious look I give to JavaFX, if it's fate is not sealed by then.
In How Can Oracle Make JavaFX More Popular, James Sugrue also references the JavaFX is a Train Wreck post and asks what Oracle can do to improve JavaFX's popularity. This post is a question intended for developers to answer and the feedback is insightful. Many want to simply "kill" JavaFX and have Oracle reallocate resources to Swing or other technologies. Others want to see it open sourced. Based on the feedback to both the original Train Wreck post and to this Sugrue post, it seems that Java developers in general do not have a positive perception of JavaFX or its future. That's daunting news because it means a reputation is being established that may be difficult to tear down.
Shai Almog has posted a poll based off the just-mentioned DZone poll specifically targeted at mobile developers. Similarly called How Can Oracle Make JavaFX More Popular, Shai asks how JavaFX can be more popular among mobile developers and I think Ryan de Laplante's answer in the feedback probably sums up the answer best: "JavaFX Mobile needs to be available. Where is it? Not on Android. Not on iPhone. Not on BlackBerry. Not on Palm Pre." I admit that I'd probably be more likely to get into JavaFX if it worked on my Droid. This is what I was poking at when I asked Does JavaFX Have a Niche?
Being called a "Train Wreck" wasn't JavaFX's only exposure this week. The two top DZone links as I write this are related to a petition to Oracle requesting that JavaFX be open sourced: Stephen Chin's Petition to Open Source JavaFX (both comments so far favor Pivot over JavaFX) and the original Petition to Open Source JavaFX. Open source success depends heavily on community involvement and/or a strong sponsoring organization, so I'm not certain that open sourcing JavaFX would improve its future. As I stated in the post O JavaFX, What Art Thou?, JavaFX cannot make the argument that it's standard or any more "Java" than other open source frameworks such as Pivot. Being open source does not magically save projects. Oracle could open source JavaFX as it has done with TopLink Essentials/EclipseLink and ADF Faces (Apache MyFaces Trinidad) and several other projects, but my current speculation (and that's all it is) is that JavaFX is more likely to be taken the same direction as Oracle's Application Developer Framework (ADF).
It wasn't all negative this week for JavaFX. Early in the week, the Sun Developer Network (AKA java.sun.com) featured the article Stylin' with JavaFX. There is a small number of ardent JavaFX proponents in the blogosphere and the author of this article, Jim Weaver, may be at the top of that list. The article's introduction talks about JavaFX's CSS support that is meant to "encourage this collaboration" between "designers and developers." The irony, of course, is that it is the lack of greater support for collaboration between designers and developers that led to the "Train Wreck" post.
Despite the enthusiastic and valiant efforts of a seemingly small number of developers who like to use JavaFX, the momentum seems to be moving away from JavaFX. Perhaps it never had momentum because it took so long to deliver anything of real value from its initial announcement at 2007 JavaOne. For now, I cannot justify spending any more time or effort learning JavaFX. Perhaps things will turn around for JavaFX and it will be worth a third look, but I wouldn't bet much on that at this time. JavaOne 2010 may be the next serious look I give to JavaFX, if it's fate is not sealed by then.
Saturday, July 10, 2010
RMOUG SQL>Update Spring 2010 Highlights
The attractive full-color Spring 2010 edition of the RMOUG SQL>Update newsletter arrived this week and I read several things in it that I felt were worth mentioning in this blog post. The three technical articles featured in this edition are the second part of Mark Molnar’s “Oracle & Excel – Why Fight It?”, Mark Rittman’s “Integrating Oracle GoldenGate and Oracle Data Integrator for Change Data Capture”, and Dan Hotka’s “Index Quality.” Besides these three technical articles this edition also features RMOUG
member Bern Bray and RMOUG Board Member Carolyn Fryc. In the remainder of this post, I highlight some of the things I found most generally interesting in these articles and member highlights.
As is usual with these RMOUG newsletters, the cover of this edition features a photograph of a beautiful Rocky Mountain area scene. In this case it is a Bern Bray photograph of Rock Cut Bloom in Rocky Mountain National Park. My family and I try to get to Estes Park, Grand Lake, and Rocky Mountain National Park often and the scene in this photograph is very familiar. Unfortunately, this beautiful cover does have a typo: it indicates that the GoldenGate/Data Integrator article is by Mark Ritter instead of Mark Rittman. With all the Marks in this issue, this typo is more understandable.
From a technical standpoint, the articles focusing on RMOUG members are intentionally and not surprisingly typically far less interesting than the technical articles. Their focus, after all, is more on the “soft skills” than on technical insight. That being stated, I particularly enjoyed reading a couple of Bern Bray’s comments in his self-written “Member Focus.” In that, Bray writes, “Like many younger engineers, my early days found me doing technical stuff on my own at night. It paid off, as I was able to advance my career and choose what I liked to work on. Several years ago, I started to feel that my life was out of balance.”
Later, in concluding, Bray states his “little nugget of wisdom”: “Work hard during working hours, but at quitting time, put the keyboard down and walk away… You will be a fresher and better worker when you come back in the morning. Besides, everyone knows that you get your best ideas in the shower.” I liked these statements because they reflect that there are career advantages to technical work done on one’s own time, but that it is also useful to take a break. This is my excuse for the less frequent and more intermittent blog posts this summer!
In the second (of two) part of his “Oracle & Excel – Why Fight It?” series, Mark Molnar demonstrates with extensive code samples and screen snapshots how to create flat files of usefully formatted data via Excel and an Oracle database. In his words, his examples show “how to take data out of the database, via Excel, and produce flat files in the format desired.” At first reading this, I wondered why one would do such a thing when it is easy to read from a database in a language like Java or Groovy using JDBC and write out flat files. However, I found the article informative because of its extensive coverage of using Visual Basic with Excel and use of 7-Zip from the command line. Even if I’d probably solve the problem of the example in this article with a Java-based approach, I enjoyed learning some details of using Visual Basic with Excel and Molnar’s coverage of some low-level details involved in that. He specifically references the URL
http://en.wikibooks.org/wiki/Visual_Basic/External_Processes as a source of useful details regarding use of Visual Basic with external processes.
Dan Hotka provides a code listing in his article “Index Quality” that contains the source code for a script he calls Index_Info.sql. According to the “description” included in the script’s comments, this script is an “SQL*Plus script to display Index Statistics in relation to the clustering factor.” Hotka writes that this script is available on his website and discusses background details of the script and why it’s useful in this article.
I’m significantly more developer-oriented than DBA-oriented, so Rittman’s article on integrating GoldenGate and Data Integrator was largely outside of my core areas of interest. However, it also meant that I learned plenty from reading the article, even though it was more difficult because I lacked the requisite knowledge in the two products he was demonstrating integrating. At the end of this article, Rittman states, “For a more
detailed, step-by-step version of this article that also describes the process to set up Oracle GoldenGate on the Microsoft Windows platform, an article is available on my website at: http://www.rittmanmead.com/2010/03/22/configuring-odi-10-1-3-6-to-use-oracle-golden-gate-for-changed-data-capture/”
Oracle OpenWorld (OOW) is mentioned more than once in this edition of the newsletter. In “RMOUG Board Focus,” Carolyn Fryc writes about her first Oracle OpenWorld (2005) and talks about the focus of that OOW being Fusion (likely a major theme every year since then as well). Dan Hotka’s training advertisement also mentions that he will be at Oracle OpenWorld September 19-23. I’ve never attended Oracle OpenWorld, but will likely attend at least portions of it this year when I attend JavaOne 2010 and Oracle Develop 2010 which are being held simultaneously in the same city.
In this blog post, I’ve attempted to outline some facets of the Spring 2010 edition of the RMOUG SQL>Update newsletter that I thought had some general interest. According to RMOUG President Peggy King’s “From the President” column, RMOUG Training Days 2011 is scheduled for 15-17 February 2011 at the Colorado Convention Center.
member Bern Bray and RMOUG Board Member Carolyn Fryc. In the remainder of this post, I highlight some of the things I found most generally interesting in these articles and member highlights.
As is usual with these RMOUG newsletters, the cover of this edition features a photograph of a beautiful Rocky Mountain area scene. In this case it is a Bern Bray photograph of Rock Cut Bloom in Rocky Mountain National Park. My family and I try to get to Estes Park, Grand Lake, and Rocky Mountain National Park often and the scene in this photograph is very familiar. Unfortunately, this beautiful cover does have a typo: it indicates that the GoldenGate/Data Integrator article is by Mark Ritter instead of Mark Rittman. With all the Marks in this issue, this typo is more understandable.
From a technical standpoint, the articles focusing on RMOUG members are intentionally and not surprisingly typically far less interesting than the technical articles. Their focus, after all, is more on the “soft skills” than on technical insight. That being stated, I particularly enjoyed reading a couple of Bern Bray’s comments in his self-written “Member Focus.” In that, Bray writes, “Like many younger engineers, my early days found me doing technical stuff on my own at night. It paid off, as I was able to advance my career and choose what I liked to work on. Several years ago, I started to feel that my life was out of balance.”
Later, in concluding, Bray states his “little nugget of wisdom”: “Work hard during working hours, but at quitting time, put the keyboard down and walk away… You will be a fresher and better worker when you come back in the morning. Besides, everyone knows that you get your best ideas in the shower.” I liked these statements because they reflect that there are career advantages to technical work done on one’s own time, but that it is also useful to take a break. This is my excuse for the less frequent and more intermittent blog posts this summer!
In the second (of two) part of his “Oracle & Excel – Why Fight It?” series, Mark Molnar demonstrates with extensive code samples and screen snapshots how to create flat files of usefully formatted data via Excel and an Oracle database. In his words, his examples show “how to take data out of the database, via Excel, and produce flat files in the format desired.” At first reading this, I wondered why one would do such a thing when it is easy to read from a database in a language like Java or Groovy using JDBC and write out flat files. However, I found the article informative because of its extensive coverage of using Visual Basic with Excel and use of 7-Zip from the command line. Even if I’d probably solve the problem of the example in this article with a Java-based approach, I enjoyed learning some details of using Visual Basic with Excel and Molnar’s coverage of some low-level details involved in that. He specifically references the URL
http://en.wikibooks.org/wiki/Visual_Basic/External_Processes as a source of useful details regarding use of Visual Basic with external processes.
Dan Hotka provides a code listing in his article “Index Quality” that contains the source code for a script he calls Index_Info.sql. According to the “description” included in the script’s comments, this script is an “SQL*Plus script to display Index Statistics in relation to the clustering factor.” Hotka writes that this script is available on his website and discusses background details of the script and why it’s useful in this article.
I’m significantly more developer-oriented than DBA-oriented, so Rittman’s article on integrating GoldenGate and Data Integrator was largely outside of my core areas of interest. However, it also meant that I learned plenty from reading the article, even though it was more difficult because I lacked the requisite knowledge in the two products he was demonstrating integrating. At the end of this article, Rittman states, “For a more
detailed, step-by-step version of this article that also describes the process to set up Oracle GoldenGate on the Microsoft Windows platform, an article is available on my website at: http://www.rittmanmead.com/2010/03/22/configuring-odi-10-1-3-6-to-use-oracle-golden-gate-for-changed-data-capture/”
Oracle OpenWorld (OOW) is mentioned more than once in this edition of the newsletter. In “RMOUG Board Focus,” Carolyn Fryc writes about her first Oracle OpenWorld (2005) and talks about the focus of that OOW being Fusion (likely a major theme every year since then as well). Dan Hotka’s training advertisement also mentions that he will be at Oracle OpenWorld September 19-23. I’ve never attended Oracle OpenWorld, but will likely attend at least portions of it this year when I attend JavaOne 2010 and Oracle Develop 2010 which are being held simultaneously in the same city.
In this blog post, I’ve attempted to outline some facets of the Spring 2010 edition of the RMOUG SQL>Update newsletter that I thought had some general interest. According to RMOUG President Peggy King’s “From the President” column, RMOUG Training Days 2011 is scheduled for 15-17 February 2011 at the Colorado Convention Center.
Thursday, July 8, 2010
The Sleek EnumMap and EnumSet
After having spent several years developing primarily in C++, I missed having an enum in Java until it was finally introduced with J2SE 5. The long wait was worth it because the Java enum is much more useful and powerful than its C++ counterpart. Although the Java enum can be used with any Java collection, its full power is best leveraged when used with the EnumMap and EnumSet.
Why would I use an EnumMap rather than a HashMap? The primary reasons boil down to some inherent advantages of Java's enum as stated in the Javadoc documentation for EnumMap: "Enum maps are represented internally as arrays. This representation is extremely compact and efficient." Later in the same Javadoc documentation, there is an "Implementation Note" that states: "All basic operations execute in constant time. They are likely (though not guaranteed) to be faster than their HashMap counterparts."
The Javadoc documentation states similar advantages for the EnumSet over the HashSet:
ColorEnum.java
EnumCollections.java
As the code demonstrates (or describes in the comments), instances of EnumMap are acquired via one of the overloaded constructors (one of three shown in the example) while instances of EnumSet are acquired via one of the overload static initialization methods (most of which are demonstrated in the example). In all cases, the specific enum being used is supplied at instantiation time. As their names imply, EnumSet implements Set and EnumMap implements Map, so they can generally be used anywhere those interfaces apply and generally support the methods and contracts of those interfaces.
Many fellow Java developers have blogged on the virtues of EnumMap and EnumSet. These include the blog posts Fun with EnumSet, Playing with EnumSet, Java's EnumSet: Fun for the Whole Family, and EnumSet in Java.
Why would I use an EnumMap rather than a HashMap? The primary reasons boil down to some inherent advantages of Java's enum as stated in the Javadoc documentation for EnumMap: "Enum maps are represented internally as arrays. This representation is extremely compact and efficient." Later in the same Javadoc documentation, there is an "Implementation Note" that states: "All basic operations execute in constant time. They are likely (though not guaranteed) to be faster than their HashMap counterparts."
The Javadoc documentation states similar advantages for the EnumSet over the HashSet:
Enum sets are represented internally as bit vectors. This representation is extremely compact and efficient. The space and time performance of this class should be good enough to allow its use as a high-quality, typesafe alternative to traditional int-based 'bit flags.' ... Implementation note: All basic operations execute in constant time. They are likely (though not guaranteed) to be much faster than their HashSet counterparts. Even bulk operations execute in constant time if their argument is also an enum set.Compact and efficient, these enum-powered collections are also easy to use as demonstrated in the following code listings. First, an example enum is provided in ColorEnum. Then, the class EnumCollections.java provides some simple demonstrations of EnumMap and EnumSet in action. In particular, the code listing demonstrates different ways to instantiate instances of these (using constructors for EnumMap and static initialization factories for EnumSet).
ColorEnum.java
package dustin.examples; import java.awt.Color; /** * Enum representing colors. * * @author Dustin */ public enum ColorEnum { BLACK("#000000", Color.BLACK, new RedGreenBlue(0, 0, 0)), BLUE("#0000FF", Color.BLUE, new RedGreenBlue(0, 0, 255)), CYAN("#00FFFF", Color.CYAN, new RedGreenBlue(0, 255, 255)), GRAY("#808080", Color.GRAY, new RedGreenBlue(128, 128, 128)), GREEN("#00FF00", Color.GREEN, new RedGreenBlue(0, 159, 107)), MAGENTA("#FF00FF", Color.MAGENTA, new RedGreenBlue(255, 0, 255)), ORANGE("#FF8040", Color.ORANGE, new RedGreenBlue(255, 127, 0)), PINK("#FFC0CB", Color.PINK, new RedGreenBlue(255, 192, 203)), RED("#FF0000", Color.RED, new RedGreenBlue(255, 0, 0)), WHITE("#FFFFFF", Color.WHITE, new RedGreenBlue(255, 255, 255)), YELLOW("#FFFF00", Color.YELLOW, new RedGreenBlue(255, 205, 0)); /** * Parameterized constructor. * * @param newHtmlHex HTML hex code for this color. * @param newJavaColor Color from java.awt package. */ ColorEnum( final String newHtmlHex, final Color newJavaColor, final RedGreenBlue newRgb) { this.htmlHexCode = newHtmlHex; this.javaColorCode = newJavaColor; this.rgb = newRgb; } /** HTML hexadecimal code for this color. */ private final String htmlHexCode; /** java.awt.Color code. */ private final Color javaColorCode; /** RGB. */ private final RedGreenBlue rgb; /** * Provide the java.awt.Color code for this color. * * @return The java.awt.Color code. */ public Color getJavaColorCode() { return this.javaColorCode; } /** * Provide the HTML hexadecimal code for this color. * * @return HTML hexadecimal code for this color. */ public String getHtmlHexadecimalCode() { return this.htmlHexCode; } /** * Provide RGB representation of this color. * * @return RGB representation of this color. */ public String getRgbRepresentation() { return this.rgb.getRgbString(); } /** * Represents RGB. */ public static class RedGreenBlue { /** Red portion of RGB. */ private final int redValue; /** Green portion of RGB. */ private final int greenValue; /** Blue portion of RGB. */ private final int blueValue; public RedGreenBlue( final int newRedValue, final int newGreenValue, final int newBlueValue) { this.redValue = newRedValue; this.greenValue = newGreenValue; this.blueValue = newBlueValue; } /** * Provide the red value of my RGB. * * @return Red portion of my RGB. */ public int getRedValue() { return this.redValue; } /** * Provide the green value of my RGB. * * @return Green portion of my RGB. */ public int getGreenValue() { return this.greenValue; } /** * Provide the blue value of my RGB. * * @return Blue portion of my RGB. */ public int getBlueValue() { return this.blueValue; } /** * Provide my RGB settings in String format: (r,g,b). * * @return String version of my RGB values: (r, g, b). */ public String getRgbString() { return "(" + this.redValue + ", " + this.greenValue + ", " + this.blueValue + ")"; } } }
EnumCollections.java
package dustin.examples; import java.util.EnumMap; //import java.util.HashMap; import java.util.EnumSet; import java.util.Map; import java.util.Set; import static java.lang.System.out; /** * Simple demonstration of EnumMap and EnumSet. * * http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/util/EnumMap.html * http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/util/EnumSet.html * * @author Dustin */ public class EnumCollections { /** Preferred form feed/carriage return/line feed. */ private static final String NEW_LINE = System.getProperty("line.separator"); /** Demonstrate the EnumMap in action. */ public static void demonstrateEnumMap() { // final Map<ColorEnum, String> colorsAndCauses = new HashMap<ColorEnum, String>(); final Map<ColorEnum, String> colorsAndAwarenessRibbons = new EnumMap<ColorEnum, String>(ColorEnum.class); colorsAndAwarenessRibbons.put(ColorEnum.BLUE, "Bipolar"); colorsAndAwarenessRibbons.put(ColorEnum.GRAY, "Diabetes"); colorsAndAwarenessRibbons.put(ColorEnum.PINK, "Breast Cancer"); colorsAndAwarenessRibbons.put(ColorEnum.RED, "Acquired Immunodeficiency Syndrome"); colorsAndAwarenessRibbons.put(ColorEnum.YELLOW, "Support the Troops"); displayMap("Awareness Ribbons Colors", colorsAndAwarenessRibbons); // The EnumMap can also be constructed by passing another EnumMap to one // of its constructors or by passing a general Map to one of its // constructors. } /** Demonstrate the EnumSet in action. */ public static void demonstrateEnumSet() { // instantiate empty EnumSet and fill it individually final Set<ColorEnum> denverBroncosColors = EnumSet.noneOf(ColorEnum.class); denverBroncosColors.add(ColorEnum.BLUE); denverBroncosColors.add(ColorEnum.ORANGE); displaySet("Denver Broncos Colors", denverBroncosColors); // instantiate EnumSet with single value final Set<ColorEnum> orangeFruitColor = EnumSet.of(ColorEnum.ORANGE); displaySet("What Color is an Orange?", orangeFruitColor); // instantiate EnumSet with two values final Set<ColorEnum> greeceFlagColors = EnumSet.of(ColorEnum.BLUE, ColorEnum.WHITE); displaySet("Colors of Greek Flag", greeceFlagColors); // instantiate EnumSet with three values final Set<ColorEnum> usFlagColors = EnumSet.of(ColorEnum.RED, ColorEnum.WHITE, ColorEnum.BLUE); displaySet("Colors of United States Flag", usFlagColors); // instantiate EnumSet with four values final Set<ColorEnum> googleIconColors = EnumSet.of(ColorEnum.BLUE, ColorEnum.RED, ColorEnum.YELLOW, ColorEnum.GREEN); displaySet("Google Icon Colors", googleIconColors); // instantite EnumSet with five values final Set<ColorEnum> olympicsRingsColors = EnumSet.of(ColorEnum.BLUE, ColorEnum.YELLOW, ColorEnum.BLACK, ColorEnum.GREEN, ColorEnum.RED); displaySet("Olympics Rings Colors", olympicsRingsColors); // place all enum choices in this Set final Set<ColorEnum> allColors = EnumSet.allOf(ColorEnum.class); displaySet("All Available Colors", allColors); // Instantiate Set of ColorEnums that are complement to EnumSet of GRAY // Note that the graySet passed to the complementOf method must be an // EnumSet specifically rather than the more general Set. final EnumSet<ColorEnum> graySet = EnumSet.of(ColorEnum.GRAY); final Set<ColorEnum> allButGrayColors = EnumSet.complementOf(graySet); displaySet("All Colors Except Gray", allButGrayColors); final EnumSet<ColorEnum> btogColors = EnumSet.range(ColorEnum.BLACK, ColorEnum.GREEN); displaySet("'B' Colors to 'G' Colors", btogColors); } /** * Display the provided Map by writing its contents to standard output with * a separating header that includes the provided header text. * * @param header Header text to demarcate the output. * @param mapToDisplay Map whose contents should be written to standard output. */ private static void displayMap( final String header, final Map<ColorEnum, String> mapToDisplay) { out.println(buildHeaderSeparator(header)); for (final Map.Entry<ColorEnum, String> entry : mapToDisplay.entrySet()) { final ColorEnum color = entry.getKey(); out.println(color + " is used to represent " + entry.getValue()); out.println( " (and it is represented in HTML as " + color.getHtmlHexadecimalCode() + " and in RGB as " + color.getRgbRepresentation() + "."); } } /** * Write the provided Set to standard output along with the provided header. * * @param header Header to be displayed before the set being printed. * @param setToDisplay Set to be displayed by writing to standard output. */ private static void displaySet(final String header, final Set<ColorEnum> setToDisplay) { out.println(buildHeaderSeparator(header)); out.println(setToDisplay); } /** * Provide a separating header based on the provided header String. * * @param header The string to be placed in the header. * @return Header separator with provided String and separation marks. */ private static String buildHeaderSeparator(final String header) { return NEW_LINE + "==================================================================" + NEW_LINE + "= " + header + NEW_LINE + "=================================================================="; } /** * Main executable function. * * @param arguments Command-line arguments; none expected. */ public static void main(final String[] arguments) { demonstrateEnumMap(); demonstrateEnumSet(); } }
As the code demonstrates (or describes in the comments), instances of EnumMap are acquired via one of the overloaded constructors (one of three shown in the example) while instances of EnumSet are acquired via one of the overload static initialization methods (most of which are demonstrated in the example). In all cases, the specific enum being used is supplied at instantiation time. As their names imply, EnumSet implements Set and EnumMap implements Map, so they can generally be used anywhere those interfaces apply and generally support the methods and contracts of those interfaces.
Many fellow Java developers have blogged on the virtues of EnumMap and EnumSet. These include the blog posts Fun with EnumSet, Playing with EnumSet, Java's EnumSet: Fun for the Whole Family, and EnumSet in Java.
Subscribe to:
Posts (Atom)