Thứ Tư, 24 tháng 12, 2008

Effective Technical Blogs

In this blog post, I will list and briefly describe some of the characteristics that I have observed to be common among many of my favorite technical blogs. I try to incorporate these ideas into my own blogging, but being aware of these advantageous characteristics does not always translate to me following them as well as I would like.

There is no shortage of ideas on what makes an effective blog. Related resources include The Seven Habits of Highly Effective Blogs, Fifty Habits of Highly Effective Blogging, Eight Tips to More Effective Blogging, Ten Habits of Highly Effective ProBloggers, Aristotle's Top Three Tips for Effective Blogging, Ten Effective Ways to Get More Blog Subscribers, Ten Tips for Effective Blogging, Thirteen Steps to Successful Blogging, Characteristics Required for Successful Blogging, How to Write a Successful Blog: Top Ten Tips, Five Tips to Create an Effective Blog Post, and Five Blogging Secrets for a Successful Blog. The majority of these focus on blogging in general or on business blogging in particular, but there are still many general concepts that apply to technical blogs specifically. These posts also tend to focus on an effective blog being measured by the number of subscribers.

For this blog post, I am going to shift my focus slightly from necessarily striving for the largest number of subscribers to focus instead on effective blogs in terms of usefulness of the entries to readers whether they be subscribers or stumble upon the blog post via search engine or link. For purposes of this blog post, an "effective technical blog" is one that either answers a question, links to something that answers a question, or provides new technical insight to the reader. While my focus is on a blog that provides high value rather than one that has a lot of subscribers, it is not surprising that a blog that consistently provides high value will often see an increase in terms of regular readers as a natural byproduct of that value.

Before getting into the characteristics I have seen to be common among my favorite technical blogs, it goes without saying that perhaps THE most important characteristic is quality of content.


Make Your Blog Posts Easy to Find

Great content is next to useless if no one is aware of it. Powerful search engines such as Google's search engine have made it easier than ever to find things on the web, but I find that there are still times when I cannot find exactly what I'm looking for due to terminology issues. A blog author can help here by uses different descriptive terms in his or her blog post for the same topic to increase the chances of the blog entry being found via search engine. An important caveat is that it is most helpful when the blog author uses the correct terminology and accuracy in names so that correct information is propagated. However, subtle references to other likely used names and terms for the same concept can help trigger search engines to find the posting.

For example, in my previous posts on the Java Persistence API (JPA), I have tried to use the phrase "convention over configuration" (a phrase commonly associated with Ruby on Rails) in addition to the phrase "configuration by exception" (more commonly associated with JPA). The reason for this is that someone may be searching for that general idea, but may type in "convention over configuration" with JPA in the search engine rather than "convention by exception."

It is no secret that Google has the most widely used search engine. This was one of the criteria that led to me selecting Blogger as my blogging platform. An advantage of using Google's Blogger is that my blog posts are almost immediately available on the Google search engine after I post them.

Another way to make your blog entry more discoverable is to create links to it. There is some controversy surrounding whether one should submit and/or vote for one's own work at the various social aggregation sites such as DZone, Digg, etc. I personally prefer that my blog postings only be submitted to these sites if at least one other person finds them worth posting, but I don't hold it against someone who submits and/or votes his or her own blog posting. This can be an effective technique because the social aggregation site is more likely to be discovered by a search engine and because the link on such sites to a blog post will increase the importance of that linked-to blog post in the algorithms of many search engines.


Version Your Post

It is easy to focus on the present and neglect the future reader. One of the most frustrating experiences I have encountered when trying to learn how to do something or resolve a problem is when I stumble across a blog entry without any obvious date of the posting. It doesn't help to have the current date (I generally am aware of what day it is) without the date of the original posting. It is even better if the date is supplemented with versioning information. For example, it is helpful to know if a code snippet or other piece of technical information applies to JDK 1.4.2, J2SE 5, or Java SE 6. It may be really obvious at time of your posting which version you are talking about (especially if it is the current latest production release), but it might not be nearly so obvious even in the near future.


Give Credit Where Credit is Due

I have read several blog entries that seem to be closely related or even inspired by another previously released blog posting. Not only is it more ethical in such cases to link to and reference that blog post, but it can also be of tremendous value to the reader. A reader who likes the post will probably like the original as well. There may be a different perspective in the original post. More than once, I have found that "little piece of missing information" in a blog entry referenced by the one that came up in my search engine query. In other words, my search engine query hasn't directly led me to the answer I was looking for, but someone's blog posting has been the helpful bridge that linked me from the search engine to the results I was looking for. As mentioned above, linking to useful related sites will benefit the one being linked to in search engines' rankings. If that site or blog posting has been helpful or inspiring, it seems the least one can do in appreciation is to link to it to help increase its exposure.


Don't Assume Everyone Knows It

Some people believe that all blog entries should provide all new or mostly new content. However, my experience has been that it is helpful to have the same information presented multiple times as long as the blog entry author puts his or her own perspective on the topic and, as discussed in the previous tip, provides references to the original material.

As evidence of this principle, I have noted that two of the more successful recent postings on DZone have been to blog entries covering topics that some of us have been familiar with for some time. However, they have still been widely popular because they obviously provided the first exposure of that topic to a number of readers. Had the authors of these blog entries decided not to post because it was an "old" topic, several people would have missed out on the information.

Classpath wildcards for JAR files in Java SE 6 have been covered for some time, including in Mark Reinhold's blog entry Class-Path Wildcards in Mustang that was posted on 15 February 2006. This tip has been re-posted many times since then, including here. I have referenced it as a sidenote in some of my own blog postings such as this one on the JMX Web Services Connector. However, it was interesting to see how popular this December 2008 post on the topic was and how many people were introduced to this via this post.

Similarly, one of my most popular blog entries on DZone (as measured by Up votes) was my post on using the Java 6 Deque. This post received more Up votes (17-0 at time of this writing) on DZone than most of my blog entries on far newer and more unique posts.

Part of the explanation for this is that many people don't have the luxury of adopting the latest product (Java SE 6 in this case) when it and all of the introductory blogs come out. In such cases, it is helpful to have a current posting on the topic once the developer does start using that product or language. One might argue that a person could search for this via search engine, but what would prompt one to think to query for a multiple JAR classpath inclusion mechanism? Another could argue that a developer adopting Java SE 6 should read all pertinent documents on the language upgrade, but the reality is that many of us don't read the manual first.

I am not saying here that one should simply provide a link to another blog entry without any additional insight. Rather, a link to an original site with some additional commentary on why this has been helpful to the blog author is acceptable (to me at least) and can actually be helpful in terms of pointing me to that original work.


Separate Personal from the Technical

I have read some very good blog entries on blogs where personal stories are mixed with technical information. While this does not necessary affect the quality of the individual posting on a technical matter, it does make me less interested in subscribing to or bookmarking that blog. Further, the personal information can be distracting and make it more difficult to separate the technical from the personal. This is especially problematic if the two are mixed in the same blog postings.

I don't know (at least not very well) most of the people whose blogs I read, so I am generally not very interested in personal, unrelated details. I prefer to read blogs where the technical blog is clearly separate from the blog author's personal blog. This allows friends and family, including those with no interest in software development, to enjoy the personal blog while software developers who do not really know the author well can focus on the technical blog.

There are exceptions to this; I have seen very effective technical blogs where significant personal issues or stories have been mentioned because they explain something else on the blog or the blog author's status or because they provide an object lesson for or feed-in to the technical subject of the blog. Also, a personal interest used as material to demonstrate a technology can be very helpful. For example, showing how to build an inventory program for Blu-ray discs can provide a nice introduction to a technology. Similarly, explanation of a personal situation leading to a discovery or to a need that is satisfied by the described technical topic can also be effective.

The thing I least like to see in a technical blog entry is political opinion unrelated to software development. There are plenty of politically-oriented blog entries on the web for those who want to read that type of material. For me, political commentary is a distraction from the technical information I am seeking. Also, political commentary is often a sign that the blog author has forgotten that the people reading this blog are potentially from all over the world and often don't care about the political topic being discussed.

There are political topics that can be appropriate in a technical blog if the political issue is related to a technical topic. For example, it seems appropriate and relevant for a software development blog to cover political issues such as advantages and disadvantages of software developer unions, benefits and costs of offshore development and outsourcing, open source regulations and laws, and intellectual property laws. It is also relevant (and often very interesting and insightful) in a technical blog to post blog entries regarding politics associated with software development communities (such as the Java Community Process) and with standards committees.

In general, most of us know where to go to find political blogs. What we need from technical blogs is not more political opinions, but rather is technical insights of the blog author. While a blog author is certainly free to post whatever he or she likes, he or she can create a more effective technical blog if the temptation to stray into unrelated personal and political topics is avoided.


Explain Abbreviations and Idioms

It is easy to forget that a blog posted on the web has a worldwide audience. I have been repeatedly expressed by the ability of many developers with a native language other than English to read, write, and speak English. For example, the European attendees (not just those from Great Britain) at Colorado Software Summit 2008 that I spoke with regarding my presentations spoke fluent English and seemed to keep up with my very fast-paced presentations given in English.

Even for these people who have mastered English as a second (or third) language, we often use cliches and idioms that may not express to them the same nuances they express to those of us who are more familiar with the idioms. Furthermore, even developers whose first language is English may not understand or be aware of idioms and cliches from other nations or even other regions of the same nation. Finally, I have even had fellow developers from the same general region as I am from ask me what RTFM or CYA means when they have heard these acronyms thrown out at meetings. In other words, while idioms can quickly convey subtle nuances, they can also be confusing if not explained.

I prefer to not distract from the topic of my blog with a detailed explanation, but I still want to ensure that someone unfamiliar with the idiom or cliche understands any subtlety associated with them. To satisfy both desires, I try to link to an explanation of the idiom or cliche so that the reader who is unfamiliar with it can find additional details on it. This allows the reader who is already familiar with it to move on without needing to click the link or needing to read through or pass over an explanation they already understand. My favorite sites to link to for these explanations include Wikipedia, the FreeDictionary's Idioms and Phrases section, the Phrase Finder, SlangSite, and UrbanDictionary.

In addition to idioms and other such phrases, even generally accepted technical abbreviations should often be spelled out when first used. If nothing else, the spelling out of an acronym might help a reader new to the topic better refine his or her future search engine queries. Some creative blog entries actually apply idioms heavily and effectively, such as the blog entry Ten Programming Proverbs Every Developer Should Know.


Carefully Prepare Title and Opening Paragraph

Many readers will choose whether to read a blog entry largely on the title and, if they get past the title, on the first paragraph. In addition, these pieces of information are often what are posted on aggregation sites and on other blogs that reference the particular blog posting. Because the title and the first paragraph are likely to be repeated on referring sites and blogs, it is best if they provide a good summary of what the blog posting will be about and why a reader might be interested in it. I am a strong believer that it doesn't benefit anyone (author or reader) to deliberately misrepresent a blog posting's content with an unrelated title.

Besides providing material to motivate readers to read the blog entry, the title and first paragraph are also significant because their likely reproduction on other web sites mean these words may get more search engine attention (and possibly a higher ranking) than the original blog entry.


Conclusion

In my experience, the most effective technical blogs have been those that focus on technical subjects, that are easily discoverable even by those who may not know the exact terms to use to find the information, that reference similar resources that might have what I'm looking for, that provide date/version information for future reference, and that provide explanations or links to explanations of concepts that might be too distracting to cover in the same blog entry.

Thứ Hai, 22 tháng 12, 2008

View SWF Contents with Nemo 440

There are times when it is helpful to see the contents of a generated SWF to better understand what is being included in it. There are several tools that can help with this. I'll briefly summarize some of them here and provide a little additional detail on my preferred tool: Nemo 440.

In Disassembling a SWF with swfdump, Gordon Smith outlines how to use the open source Flex SDK download and its swfdump executable tool based on the provided swfutils.jar. Note that the swfdump executable is also available with the OpenLaszlo distribution in the same directory (WEB-INF/bin) as other Flex-specific commands such as mxmlc and asdoc.

The flash-decompiler project, hosted on Google Code, is intended to be used to decompile Flash files. There are also other Flash decompilers, including commercial products. These include Flash Decompiler, Flash Decompiler Gold, and Sothink SWF Decompiler. Other tools for determining SWF content include swfextract, abcdump, and Flare.

My favorite product for seeing how my Flash/SWF files have been put together is the easy-to-use Nemo 440. This AIR-based application is very simple and therefore very easy to use. It is relatively small in size and so downloads and installs quickly, especially if you already have Adobe AIR installed on your machine. Once the .air file is downloaded, it can be installed by clicking on it or by typing its name on the command-line. There are only a few choices once the application is loaded, so it is really easy to figure out how to use Nemo 440.

Looking at the code as available in the SWF can be useful in understanding better how the Flex-to-Flash process works and can be useful for ensuring that contents are being included in the SWF as you expect.

Even if you don't have a need to look at the contents of your SWF file for your own uses, it may be worth your time to look at what Nemo 440 and other similar tools do show from your files. You may find that there are some things in those files that you really don't want so easily observed. See Analyzing Malicious Flash Programs for additional details on such security implications.

For times when you need to peek into an SWF you have compiled, Nemo 440 is an extremely useful tool that makes viewing of this content easy and efficient.

Thứ Sáu, 19 tháng 12, 2008

2008: Year of the Java Persistence API

It appears that one of the most popular themes in Java development in 2008 has been the Java Persistence API (JPA). I base this statement on the recent announcements that JPA-focused articles appeared in the Top Ten lists of articles for both Oracle Technology Network (OTN) and JavaLobby.




UPDATE (1 January 2009): Since the original posting of this article, the popularity of JPA in 2008 has been further proven by two JPA-related articles making JavaWorld's 2008 Top Ten and by a JPA-related article on EclipseLink making the ElipseZone Top Ten of 2008. See updates at end of this blog for additional details on these.



The article Looking Forward to JPA 2.0 (including Part 2) came in at #6 in the JavaLobby Top Ten Articles of 2008. This two-part article looks at what we can expect with JPA 2.0 (JSR 317). As a side note, EclipseLink will be the reference implementation of JPA 2.0.

My article Basic Java Persistence API Best Practices ended up being the fifth most popular article on Oracle Technology Network's Best of 2008: The Most Popular Tech Articles and How-Tos Published by OTN This Year.

It seems to me that it is more than coincidence that would explain two articles so highly focused on the Java Persistence API being listed in the Java-centric JavaLobby's Top Ten as well as the more general OTN Top Ten. The popularity of these articles is a reflection on the popularity and level of interest in the topic itself.

As further evidence of JPA's popularity in 2008, witness the series of articles in JavaWorld on JPA (Understanding the Java Persistence API, Part 1 and Understanding the Java Persistence API, Part 2) that appeared in early 2008. The fact that the editors at Oracle Technology Network, JavaLobby, and JavaWorld all published articles on JPA in 2008 is further evidence of the popularity of the topic. These editors strive to ascertain what is important to readers and prospective readers and it seems clear that JPA was one of those themes that was widely popular.

For very simple applications, I still prefer Spring JDBC. However, for more complicated (and more common) applications, I have found JPA-compliant implementations to be my object-relational mapping (ORM) tools of choice. It seems clear that 2008 has been a great year for interest in the Java Persistence API. This is not all that surprising when one considers the many advantages of JPA: same data access code across Java SE, Java EE web, and Java EE EJB; ability to switch between specification-compliant implementations, and ease-of-use with features such as configuration by exception (convention over configuration) and the ability to override in-code annotations with external XML configuration.

UPDATE (30 December 2008): An article introducing EclipseLink made the top ten list (#2) of the ten best articles in 2008 at EclipseZone.

UPDATE (1 January 2009): JavaWorld has put out its 2008 top ten (based on page views) and JPA is a focus of two of its top ten articles. Specifically, the article iBATIS, Hibernate, and JPA: Which is Right for You? was the fourth most popular article and Understanding JPA was the sixth most popular. A screen snapshot of the JavaWorld Top Ten of 2008 is shown next:

Most-Missed Java SE 7 Features

I have blogged before about some of the interesting observations from previous Java.net polls. While these polls are in no way scientific and very little seems to be done to keep someone from stuffing the ballot, the fact that the results often correlate closely with my experiences and anecdotal observations leads to me believe they are generally fairly representative of the Java community's perceptions and opinions. With this in mind, the current results of the Java.net poll question Which of these excluded-from-Java-7 features were you most interested in? provides interesting insight into what matters most to each of us. I say this because it is my not-so-deep (read "obvious") theory that the feature an individual developer most wants in an upcoming version of Java is always closely related to what they miss the most in their daily tasks.


Closures

As of this writing, there are just over 160 votes (but new votes are coming in fairly rapidly right now) and the far-and-away leader for most missed dropped feature from Java SE 7 is closures. At this point, the closures feature has received relatively close to half of the total votes. In one respect, this is to be expected. Closures have seemed to dominate the Java SE 7 discussions until it was announced that they would not be included in Java SE 7. However, some of the reason for this significant discussion is the controversy surrounding both the concept of having closures at all as well as how closures would be implemented.

While closures have been one of the most hotly discussed proposals for Java SE 7, I have personally been fairly ambivalent about them. I can see how they would occasionally be useful in my work, but I can live without them for the most part. In other words, I wouldn't mind if they were added, but it did not really bother me when I heard that they would not be included in Java SE 7. However, if we are to believe the results of this poll so far, close to one half of Java developers wanted this feature the most. This is in line with a previous Java.net poll question regarding developers wanting the closures question resolved in time for Java SE 7.


Properties

The second most missed feature as of right now is first-class properties with just under 15% of the votes. This is clearly a distant second to closures. Like closures, this is another addition to Java that I have mixed feelings about. I strive to follow Joshua Bloch's advice to minimize mutability and Allen Holub's advice (Holub on Patterns) on being careful with get/set methods in my objects. I therefore prefer not to have "set" or mutator methods unless required. I find the idea of using my IDE to automatically generating get/set methods for any and every class that I write to be distasteful. However, there are some types of objects, such as data objects, that are intended for uses that involve many get/set methods. For these limited situations, the first-class properties would provide some desirable benefits. In the end, my leanings in favor of and my leanings against Java properties made it difficult for me to be too excited about the prospect of them or too disappointed when it was announced they would not be part of Java SE 7.


Reified Generics

The current third most interesting feature dropped from Java SE 7 is one I did really want -- reified generics. I don't think I'm capable of counting all the times that I could have used generics support at runtime. I have enjoyed many benefits of using generics, but am greedy and would like to enjoy even more benefits from generics by gaining runtime benefits to complement the current compile-time benefits. While "reified generics" currently has just under 12% of the votes, it certainly is one of the features I am most disappointed to see not included in Java SE 7.


Beans Binding

Fourth place in the poll on most interesting features dropped from Java SE 7 consists of a tie between another of the features that most interests me (beans binding) and "none of the above" (worded differently in the actual poll). Each currently has just under ten percent of the votes. My work with Flex and OpenLaszlo over the past two years has led me to greatly appreciate the productivity gains associated with solid beans or property binding implementations. I really wanted to see this added to Java with Java SE 7 and this is what I voted for on this poll. There are Java alternatives such as JGoodies Binding and the JSR 295 Reference Implementation, but it would have been nice to have this as a standard part of the Java language.


None of the Above

It was interesting to observe that almost ten percent of respondents don't miss any of the listed features dropped from Java SE 7. A natural question is how many of these are against most/all new features/changes to Java and how many just have a different feature or set of features they care about. An example of a feature that may still not make it into Java SE 7 that I think many of us really do care about is the new date/time API (JSR 310). I have blogged previously on my interest in the JMX 2 and JMX Web Services Connector being part of Java SE 7 as well.


Operator Overloading and BigDecimal Syntax

The two currently least interesting dropped Java SE 7 features are the somewhat related items of BigDecimal syntax and operator overloading. Like closures and first-class, properties, I am somewhat ambivalent on these. I could see some use for both, but am not too concerned about them not being added to Java SE 7.


Conclusion

There are obviously many factors that influence which features each of us most wants to see in a new version of Java. These factors include favoring features that reduce the things that cause us the most pain on a regular basis. Another factor impacting which features we desire most or are most against is our individual preference for or aversion to a particular design/implementation ideology. Finally, we are all influenced by syntax and characteristics of other languages that we use. I mentioned the data binding in Flex and OpenLaszlo influencing my desire to see a similar feature in Java. Similarly, advocates of closures and first-class properties cite such behaviors in other languages.


Additional Resources

For additional coverage of Java SE 7 coming features and dropped features, I don't think there is a better resource than Alex Miller's Pure Danger Tech blog. The Java SE 7 section of this blog is most pertinent to Java SE 7, though I laughed out loud at some of the "possibly true reviews" of the book The Definitive Guide to Terracotta.

Other good Java SE 7 resources include Danny Coward's Sun Weblog (particularly Java SE 7 section), Stephen Colebourne's Weblog (particularly the Devoxx-related blog posts), and Mark Reinhold's blog.

Thứ Hai, 15 tháng 12, 2008

Generating a Climograph with JFreeChart

A climograph can be easily generated with Excel as documented in Creating a Climograph in Excel and Directions for Using Excel to Make a Colorful Climograph. While it is a little more work to generate a climograph with JFreeChart, it is still pretty straightforward as demonstrated in this blog post. The advantage, of course, is that one can then easily generate a climograph directly from Java.

As its name suggests, the climograph is a useful graphical representation of climate data. Specifically, it displays precipitation and temperature data on the same chart. Typically, precipitation data is displayed as a bar chart and is overlaid with temperature data portrayed as a line chart.

The article Visualize Your Oracle Database Data with JFreeChart demonstrates how to build several different types of charts, but the article does not demonstrate building a climograph. In fact, most of the charts discussed in the article are charts generated directly from the ChartFactory class. A secondary motivation for this blog post is to demonstrate this additional chart type and some of the features used in JFreeChart to build this "custom" chart type.

I'll focus on some snippets of the code for generating a climograph first and then list the code in its entirety at the end of this post. The first code snippet shown is the method buildMainChartWithPrecipitation. The method uses ChartFactory.createBarChart to generate the bar chart representing precipitation. So far, this is the same old bar chart generation code one would see for generating any bar chart. Adding the line chart later will make this more interesting.

buildMainChartWithPrecipitation


/**
* Construct the initial chart with focus on the precipitation portion.
*
* @param precipitationDataset Precipitation dataset.
* @return First version of chart with precipitation data rendered on the
* chart.
*/
public JFreeChart buildMainChartWithPrecipitation(
final CategoryDataset precipitationDataset)
{
final JFreeChart chart =
ChartFactory.createBarChart(
this.chartTitle,
CHART_CATEGORY_AXIS_LABEL,
chartPrecipitationValueAxisLabel,
precipitationDataset,
CHART_ORIENTATION,
true, // legend required?
false, // tool tips?
false); // URLs generated?
customizeChart(chart.getCategoryPlot());
return chart;
}


The complete code listing at the end of this post will show the setting of the values used in this code such as title, orientation, and axis label. The precipitationDataset is prepared by a method that accepts an array of twelve numbers representing precipitation for each of the twelve months and places these values in a CategoryDataset.

The customizeChart method is needed to put the names of the months at a 45-degree angle because they won't fit on the graph in their full form otherwise.

With the bar chart representing the precipitation measurements, we now need to add a line chart representing temperature measurements to this chart to get the climograph. The following method, addTemperatureMeasurementsToChart,
adds the line chart representation of the measured temperatures to the previously generated bar chart representation of measured precipitation.

addTemperatureMeasurementsToChart


/**
* Add temperature-oriented line graph to existing chart.
*
* @param originalChart Chart to which line graph is to be added.
* @param temperatureDataset Dataset for the line graph.
*/
public void addTemperatureMeasurementsToChart(
final JFreeChart originalChart,
final CategoryDataset temperatureDataset)
{
final CategoryPlot plot = originalChart.getCategoryPlot();
final ValueAxis temperatureAxis =
new NumberAxis(this.chartTemperatureValueAxisLabel);
plot.setDataset(1, temperatureDataset);
plot.setRenderer(1, new LineAndShapeRenderer(true, true));
plot.setRangeAxis(1, temperatureAxis);
plot.mapDatasetToRangeAxis(1, 1);
plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
}


The code above adds the line graph representation of temperature data to the bar chart representation of precipitation data by accessing the original bar chart's category plot and manipulating that. Specifically, the line chart is added at the second index value (1 because it is a zero-based index). The LineAndShapeRenderer is constructed with two true valuesto indicate that both the lines and the shapes at each data point should be displayed. The DatasetRenderingOrder is also set as FORWARD to ensure that the line chart will be displayed on top of the bar chart. The temperature dataset is a CategoryDataset that is very similar to the one prepared for precipitation and its preparation is also shown in the full code listing.

The full code listing of the ClimographGenerator class is shown next:


package dustin.climograph;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Logger;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;

/**
* Example of generation of climograph with JFreeChart.
*
* @author Dustin
*/
public class ClimographGenerator
{
private final static Logger LOGGER =
Logger.getLogger(ClimographGenerator.class.getCanonicalName());

/** Degree symbol Unicode representation. */
private final static String DEGREE_SYMBOL = "\u00B0";

/** Title of generated chart. */
private String chartTitle;

/** Labels used for chart's categories (months). */
private final static String[] MONTHS_CATEGORIES =
{ "January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December" };

/** Precipitation series label. */
private final static String PRECIPITATION_SERIES_LABEL = "Precipitation";

/** Temperature series label. */
private final static String TEMPERATURE_SERIES_LABEL = "Temperature";

/** Category Axis Label (months). */
private final static String CHART_CATEGORY_AXIS_LABEL = "Months";

/** Value Axis Label (precipitation). */
private String chartPrecipitationValueAxisLabel;

/** Value Axis Label (temperature). */
private String chartTemperatureValueAxisLabel;

/** Orientation of generated chart. */
private final static PlotOrientation CHART_ORIENTATION = PlotOrientation.VERTICAL;

/** No-arguments constructor not intended for public consumption. */
private ClimographGenerator() {}

/**
* Preferred approach for obtaining an instance of me.
*
* @param chartTitle Title to be used on generated chart.
* @param precipitationUnit Units used for precipitation.
* @param temperatureUnit Units used for temperature.
* @return An instance of me.
*/
public static ClimographGenerator newInstance(
final String chartTitle,
final PrecipitationUnit precipitationUnit,
final TemperatureUnit temperatureUnit)
{
final ClimographGenerator instance = new ClimographGenerator();
instance.chartTitle = chartTitle;
instance.setPrecipitationValueAxisLabel(precipitationUnit);
instance.setTemperatureValueAxisLabel(temperatureUnit);
return instance;
}

/**
* Set preciptation value axis label.
*
* @param precipitationUnit Units being used for precipitation measurements.
*/
private void setPrecipitationValueAxisLabel(
final PrecipitationUnit precipitationUnit)
{
this.chartPrecipitationValueAxisLabel =
"Precipitation (" + precipitationUnit.getChartDisplay() + ")";
}

/**
* Set the temperature value axis label.
*
* @param temperatureUnit Units being used for temperature measurements.
*/
private void setTemperatureValueAxisLabel(
final TemperatureUnit temperatureUnit)
{
this.chartTemperatureValueAxisLabel =
"Temperature (" + DEGREE_SYMBOL + temperatureUnit.getChartDisplay() + ")";
}

/**
* Construct dataset representing the precipitation.
*
* @param precipitationValues Numeric precipitation values, one for each of
* the twelve months.
* @return Dataset representating the precipitation.
* @throws IllegalArgumentException Thrown if more than 12 or fewer than 12
* values are provided for precipitation measurements.
*/
public CategoryDataset buildPrecipitationDataset(
final Number[] precipitationValues)
{
final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
final int numberValues = precipitationValues.length;
if ( numberValues != 12)
{
throw new IllegalArgumentException(
"Twelve precipitation values need to be supplied, but only "
+ numberValues + " values were provided.");
}
for (int index=0; index < numberValues; index++ )
{
dataset.addValue(
precipitationValues[index],
PRECIPITATION_SERIES_LABEL,
MONTHS_CATEGORIES[index]);
}
return dataset;
}

/**
* Construct dataset representing the temperature.
*
* @param temperatureValues temperature values, one for each month.
* @return Dataset representing the temperature.
* @throws IllegalArgumentException Thrown if more than 12 or fewer than 12
* values are provided for temperature measurements.
*/
public CategoryDataset buildTemperatureDataset(
final Number[] temperatureValues)
{
final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
final int numberValues = temperatureValues.length;
if ( numberValues != 12)
{
throw new IllegalArgumentException(
"Twelve temperature values need to be supplied, but only "
+ numberValues + " values were provided.");
}
for (int index=0; index < numberValues; index++ )
{
dataset.addValue(
temperatureValues[index],
TEMPERATURE_SERIES_LABEL,
MONTHS_CATEGORIES[index]);
}
return dataset;
}

/**
* Construct the initial chart with focus on the precipitation portion.
*
* @param precipitationDataset Precipitation dataset.
* @return First version of chart with precipitation data rendered on the
* chart.
*/
public JFreeChart buildMainChartWithPrecipitation(
final CategoryDataset precipitationDataset)
{
final JFreeChart chart =
ChartFactory.createBarChart(
this.chartTitle,
CHART_CATEGORY_AXIS_LABEL,
chartPrecipitationValueAxisLabel,
precipitationDataset,
CHART_ORIENTATION,
true, // legend required?
false, // tool tips?
false); // URLs generated?
customizeChart(chart.getCategoryPlot());
return chart;
}

/**
* Add temperature-oriented line graph to existing chart.
*
* @param originalChart Chart to which line graph is to be added.
* @param temperatureDataset Dataset for the line graph.
*/
public void addTemperatureMeasurementsToChart(
final JFreeChart originalChart,
final CategoryDataset temperatureDataset)
{
final CategoryPlot plot = originalChart.getCategoryPlot();
final ValueAxis temperatureAxis =
new NumberAxis(this.chartTemperatureValueAxisLabel);
plot.setDataset(1, temperatureDataset);
plot.setRenderer(1, new LineAndShapeRenderer(true, true));
plot.setRangeAxis(1, temperatureAxis);
plot.mapDatasetToRangeAxis(1, 1);
plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
}

/**
* Customize the generated chart.
*
* @param plot Plot associated with generated chart.
*/
public void customizeChart(final CategoryPlot plot)
{
final CategoryAxis monthAxis = plot.getDomainAxis();
monthAxis.setCategoryLabelPositions(
CategoryLabelPositions.DOWN_45);
}

/**
* Write .png file based on provided JFreeChart.
*
* @param chart JFreeChart.
* @param fileName Name of file to which JFreeChart will be written..
* @param width Width of generated image.
* @param height Height of generated image.
*/
public void writePngBasedOnChart(final JFreeChart chart,
final String fileName,
final int width,
final int height )
{
try
{
ChartUtilities.writeChartAsPNG(new FileOutputStream(fileName),
chart,
width, height);
}
catch (IOException ioEx)
{
LOGGER.severe("Error writing PNG file " + fileName);
}
}

/**
* Main chart-building executable.
*
* @param arguments The command line arguments; none expected.
*/
public static void main(final String[] arguments)
{
final ClimographGenerator me =
newInstance(
"Climograph for Fantasy Land",
PrecipitationUnit.INCHES,
TemperatureUnit.FARENHEIT);
final CategoryDataset precipitationDataset = me.buildPrecipitationDataset(
new Number[]{35, 30, 50, 40, 40, 30, 25, 15, 35, 40, 45, 50});
final JFreeChart chart = me.buildMainChartWithPrecipitation(
precipitationDataset);
final CategoryDataset temperatureDataset = me.buildTemperatureDataset(
new Number[]{30, 25, 45, 60, 70, 85, 90, 95, 75, 60, 40, 35});
me.addTemperatureMeasurementsToChart(chart, temperatureDataset);
me.writePngBasedOnChart(chart, "C:\\example.png", 600, 400);
}
}


The example above is current written to write a PNG image containing the generated climograph to the specified file name. Most of the class implements in a relatively generic way the generation of a climograph. Most of the hard-coded values and choices are isolated to the main function. This is intentional so that the class could be used in other contexts such as being called by a Swing application, being called by a servlet application, being called by a Flex or OpenLaszlo application, being called by a command-line tool or script, etc.

For completeness, I include the definitions of the two enums used in the above code next. These define the units for precipitation and temperature respectively.

PrecipitationUnit


package dustin.climograph;

/**
* Simple enum for representing the units used with precipitation for
* generating a climograph with JFreeChart.
*
* @author Dustin
*/
public enum PrecipitationUnit
{
CENTIMETERS("cm"),
INCHES("in"),
METERS("m"),
FEET("ft");

/** String to be displayed on generated chart. */
private String chartDisplayableString;

/**
* Constructor accepting string to be displayed on chart for the type of unit.
*
* @param newChartDisplayableString String to be displayed on chart for the
* unit type.
*/
PrecipitationUnit(final String newChartDisplayableString)
{
this.chartDisplayableString = newChartDisplayableString;
}

/**
* Provide my string representation of the unit to appear on the generated
* chart for this unit.
*
* @return String representation on chart for this unit type.
*/
public String getChartDisplay()
{
return this.chartDisplayableString;
}
}



TemperatureUnit


package dustin.climograph;

/**
* Representation of temperature units used in generation of Climograph with
* JFreeChart.
*
* @author Dustin
*/
public enum TemperatureUnit
{
CELSIUS("C"),
FARENHEIT("F");

private String chartDisplayableString;

/**
* Constructor accepting String indicating units being used for temperature
* measurement and intended for display on generated Climograph chart.
*
* @param newDisplayableString String to indicate units used on climograph
* for temperature.
*/
TemperatureUnit(final String newDisplayableString)
{
this.chartDisplayableString = newDisplayableString;
}

/**
* Provide String indicating units of measure used for temperatures shown
* in the JFreeChart-generated climograph.
*
* @return String representation of temperature units.
*/
public String getChartDisplay()
{
return this.chartDisplayableString;
}
}



When the above code is executed, the PNG image that appears next is generated. Click on the image to see a larger version of it.




Conclusion

It is relatively easy to generate a climograph from Java with JFreeChart. It is not as easy as with Excel, but is still pretty easy relative to other Java-based methods. With the code for the ClimographGenerator class shown above now available, it is a straightforward task to make some small modifications that will make the class even more modular and reusable for generic climograph generation. See the article Visualize Your Oracle Database Data with JFreeChart for a more detailed introduction to JFreeChart.

Thứ Bảy, 13 tháng 12, 2008

Java RIA Momentum

In my previous blog post, I briefly discussed Flex's growing circle of friends that gained a powerful friend with the addition of the Spring Framework and the announcement of the Spring BlazeDS Integration project. To make things even more interesting, this announcement has been made in the same month as the release of JavaFX 1.0 SDK and as the announcement that JBoss will include Google Web Toolkit (GWT) as part of its middleware offerings. Besides the recent announcements of Flex+Spring collaboration, JBoss+GWT collaboration, and the release of JavaFX 1.0 SDK, there is also increased coverage of forthcoming JSF 2.0. All of these announcements are evidence of the battle for Java-based RIA supremacy.

The concept of momentum applies to just about any competitive sporting event one can imagine and often applies to the software development world as well. One interesting point about momentum is that it is difficult to measure quantitatively and is often something we "feel". Another interesting observation related to momentum is that it does not necessarily imply who is winning the overall particular sporting event at this moment, but rather describes who seems to be playing better currently. Even a team or individual losing the match or game might be said to have the momentum if that team or individual is narrowing the difference in score. A team that is widening its lead similarly is often said to have the momentum.

I see similarities in this somewhat nebulous concept of "momentum" in the trends of the software development world as well. Programming languages, approaches and methodologies, and so forth enjoy and lose momentum. For this blog post, I specifically want to focus on the momentum I have observed in the Java-based RIA world. Just as with momentum in sporting events, it is difficult to measure momentum, but it is something that I "feel" based on discussions with other Java developers, on attendance at conferences, and on frequent reading of related blog entries.

From what I have observed in attending conferences such as Colorado Software Summit 2008, in reading blogs, and in talking to fellow self-labeled Java developers is that both Flex and Google Web Toolkit seem to have significant momentum in the Java-based RIA world at this point. JSF seems to have lost significant momentum, though that could change with the 2.0 release. Sun is spending significant resources and energy to try to re-energize momentum for JavaFX that I believe (at least true for me) was damaged by the early announcement at 2007 JavaOne without a 1.0 SDK release until December 2008.

In many ways, the same thing happened to me with JSF; the momentum seemed to be significantly limited due to long delays on the delivering of its promises. I remember hearing about JSF being the next great thing during my development with Struts in early 2001, but it seemed to be many years before it was really ready for prime time. Even now, many are saying that 2.0 (2009) will finally bring JSF to where it needs to be.

When watching sporting events, we can look at the scoreboard to determine who is winning the overall competition (which may not be the team or individual with the current momentum). It is more difficult to see what is winning currently in the Java+RIA arena, but it is interesting to speculate on where current momentum and future potential momentum changes will take the Java-based RIA community in the future. Based on what I "feel" when I talk to others about Java development of RIAs, the current momentum seems to be in Flex's favor (as witnessed by many different events such as the Spring+Flex integration announcement and the defections of many high-profile Swing developers to Adobe) and in GWT's favor (as witnessed by several events including the JBoss+GWT collaboration announcement).

Another category of RIA development that could be argued to be enjoying current momentum is direct Ajax/JavaScript development. Like Flex, this approach is not Java-specific, but is used by Java developers. Current momentum does not guarantee a victory, but it is certainly something every competitor wants. An argument could be made that the current participant that is "winning" is the direct Ajax/JavaScript approach and the real question may be if the growing momentum of Flex, GWT, JavaFX, and other approaches can overtake that lead.

SpringSource and Red Hat/JBoss are major players in the Java-oriented open source community. Their collaborative efforts with Adobe (Flex) and Google (GWT) respectively indicates the momentum enjoyed by Flex and GWT in the Java development world. While using straight Ajax/JavaScript on the front-end with Java on the back-end is also currently popular, Flex and GWT seem to be taking advantage of a common desire among many Java developers to avoid direct contact with JavaScript and DOM browser idiosyncrasies whenever possible.

Finally, all of this is complicated by that fact that many of these approaches can, in fact, be used together. For example, Flex and Ajax/JavaScript can be used together (such as with the Flex-Ajax Bridge). Similarly, there are efforts underway to integrate Flex and JSF such as the JSF Flex Project. Similarly, there are projects surrounding integration of GWT and JSF.

To make matters even more complicated, there are other competitors trying to enter the competition. These include Flash/Flex-like competitors such as Silverlight and Curl. Silverlight, in particular, has many things in its favor, but winning the hearts and minds of Java developers seems like a long-shot. Java developers wishing to developer RIAs might also be interested in the next-generation Java plug-in (the return of the applet) or in one of the numerous Java-based frameworks such as Galileo and Pivot.

In summary and based on my own observations, I'd say that direct Ajax/JavaScript solutions are probably currently winning in terms of number of RIAs being developed with Java on the back-end, but that the momentum is shifting toward Java developers using Flex or GWT. However, the competition is not over yet. The good news is that the RIA options for the Java developer continue to get more diverse and productive.

Thứ Hai, 8 tháng 12, 2008

Flex's Increasing Circle of Friends: SpringSource

Many of us have discovered the benefits of using Flex for rich client side applications in conjunction with enterprise Java on the server side. The Flex/Java EE combination brings the best of both worlds to the developer seeking rich clients with robust enterprise strength back-ends.

While Flex and Enterprise Java go very well together, Flex is also used with a myriad of other languages. Some advertised efforts related to various languages and frameworks making special effort to work even better with Flex include PHP (Zend - "Zend to Collaborate with Adobe", 16 September 2008), Ruboss (22 May 2008), Ruby on Rails (Flexible Rails), Python, C++, and .NET ("Adobe Flex Reaches Out to .NET Developers", 17 November 2008).

In the Flex+Java world alone, there are many alternatives as well. While HTTPService and WebService make Flex useful with virtually any modern language, Flex (either directly or via its community) has a wide range of Java-specific goodies as well. These include BlazeDS (including support for Spring+Flex, JMS, and Java object remoting), and GraniteDS (specific support for Enterprise JavaBeans 3, the Spring Framework, Seam, and Guice).

Now, we have an announcement that SpringSource will be collaborating with Adobe to deliver Spring BlazeDS Integration. SpringSource will also be releasing an adapter for LiveCycle Data Services ES. With the established pervasiveness of the Spring Framework in the Java EE community and the rapidly growing popularity of Flex in the Java EE community, this announcement was really not much of a surprise and makes a lot of sense. Other articles covering this announcement can be found here, here (extra details), here, here, here (details on what Spring BlazeDS Integration offers above today's Flex+Spring options), and here.

Flex continues to be used with an ever increasing variety of back-end technologies. However, for those of us who still primarily develop our enterprise applications with Java EE and Spring, today's announcement is very good news.