Code, Coffee

Full contact Java programming from the trenches.


Main | Next page »
Tuesday Nov 11, 2008

Intellij 8.0

IntelliJ 8.0's a large step forward (and none back!)

I just downloaded the latest and greatest revision of Jetbrain's flagship product, Intellij IDEA 8.0. It is, in a word, pretty awesome. This is due in large part to the refactoring of the core that has occurred between 7 and 8 to improve the application of the IDE for different languages. Support includes, but is not limited to, Groovy, Scala, Ruby, and Java (wherein you also have a dozen different DSLs with which IDEA contends admirably).

What seems to happen with Intellij is that they include feature and support for a feature that's, shall we say, half baked. Don't get me wrong: a half baked Intellij feature's usually worth 2 or 3 fully baked Eclipse features. Compared to the usual level of quality, some times things slip through that don't meet expectations but that do – nonetheless – work. Where 7.0 of the IDE was pretty revolutionary, version 8.0 seems evolutionary (at least in terms of features.)

Instead, things are better polished, faster. Maven support was good when it was introduced in 7.0. Now, it's remarkably well thought and configurable. Intellij has supported displaying test coverage data when unit tests are running. Now it's possible to jump from a class to a test case. Ever wanted to be able to ride the data flow analysis and see where values in the system come from? Now you can. The support for Subversion and Subversion 1.5 is pretty stellar, and includes the ability to see which version of a change have already been integrated into a branch. Actually, the Subversion support is one of the things I've long liked from Intellij. Eclipse hasn't until version 3.4 officially supported Subversion at all. Eclipse 3.4 includes part of the functionality for accessing Subversion, but due to licensing issues you're on your own to install the remaining bits yourself. Intellij already had support for Flex (and the best JavaScript integration I've ever seen), but not much more than support for referencing and coding ActionScript. Now, you can almost effectively remove Flex Builder from your life if you're not planning on doing anything graphical.

And of course, there are new features, too. Support for Seam, better support for Jruby (which was already being called the best in the industry, and is now the extracted core of Intellij's RubyMine product), 20+ new intelligent refactoring capabilities, the ability to assign and swatch of text a “language” so that Intellij can enable proper editing for it, and the UML capabilities round out the features. One of my favorite new features is the ability to... remove... features. Intellij has a LOT of features. While they're not obtrusive or glaringly present like an overloaded Eclipse instance can be, they are there when you launch the application and they consume RAM. I loaded IntelliJ and it gave me a Plugin configuration wizard by which I could disable plug ins. I'm not likely going to be using the Perforce SCM integration, and nor am I likely going to be using the FreeMarker and Struts configuration tools. So, why not disable them? The speed boost at both runtime and startup is marked.

There are many more new features to like in this tool as well as the coder-friendly editor itself, which is just as tight a fit now as it's ever been. IntelliJ has always taken refactoring to a new plateau hiterto unmatched by Eclipse or Visual Studio, and this release is now exception.

What I didn't like: the tool had some JSP validation errors because of a URL that needs to be downloaded to resolve. In previous versions a little intelligent tooltip would prompt you to let IntelliJ download the file. Not so much in this case. Instead, I was prompted by IntelliLang's tool tip, asking me if I wanted to declare the URL to be a fragment of .. insert your favorite schema/dialect/language/grammar here. Annoying. I still don't know how to get the old functionality to return. Thankfully, in this case, the code was one "old" style JSP and the rest of the site consists of JSP Documents, which all displayed and edited perfectly. And quickly! IntelliJ is pretty quick, anyway, but it seems like the price you pay for invalid HTML is more pronounced in the IDE than, say, with DreamWeaver. )

All in all, a worthy upgrade and I wholeheartedly recommend it.

Thursday Nov 06, 2008

And now for something completely different, OR, The code That Almost Toppled Microsoft. Almost.

I just visited the Phillipines. While there, my-brother-in-law gave me a hard disk with 60GBs of photographs. I wanted them on Flickr. Complicating matters further were the photos that my wife and I took. Her photos - every blessed one of them -- were perfect. Mine, on the other hand, were an affront to color, tone, lighting and God. Nothing short of a week in front of GIMP and Flickr could save them.

Nothing, that is, except perhaps some automation. I devised a plan: auto color correct the images using ImageMagic (You know how Photoshop has the "Auto Levels" command that transforms images from Warhol's to Monet's?), correct some of the EXIF issues I had, and then upload all 65GBs of photos to Flickr.

Approach

I chose Ruby for the solution because I've worked with some of these APIs before. I know how I would approach this problem from Java: JMagick for ImageMagick access, FlickrJ for Flickr, and I'd probably just shell out to exiftool, which is a command line tool on Linux. I've disabused myself of the notion that this script going on to become the 100 lines of code that topples Microsoft, and thus I don't care if it just works on Linux.

I chose not to use Java because, frankly, I'm really picky about how I build my Java applications. Picky, to the point that sometimes it hinders me when I'm just trying to express an application. Unless it's for the most trivial of applications (where "trivial" most certainly does NOT include assimilating 3 different libraries and performing image processing for 2 days) I can't help but introduce elements from my war chest.

My war chest is derived from years of doing this singular task, from programming in Java. Years of experience have taught me to readily employ, for example: Maven, unit testing, persistence (so that I can keep track of what's been processed, for example) and with all of that, why not Spring? After all, I was going to write to interfaces anyway. My years of experience have taught me that I should plan the application out a little bit before I take to coding. After all, by the time I've integrated all those APIs, change will be slower going, and it's easier to refactor UML than DDL. My years of experience have made me slow for the small applications and fast for the big applications.

I chose not to use Python because I didn't know the APIs for Flickr that well in Python. Simple enough. I always use Python. It's the language I write my one-offs in. It's the language I go to when I want to express a solution without UML. It would have been perfect for this job. It's most redemptive quality is, in fact, how frequently I find myself thinking it would be perfect for a job. It inspires hope. But again, I don't know the API very well, no need to get lost in the weeds of Ruby offers a paved road.

Prerequisites

The players having been selected, I wrote a small checklist of what I'll need.

  1. Flickr API License key Make sure you choose the non professional version.
  2. Photos
  3. Ruby compiler. And the gem command, definitely don't forget those. You'll need some packages to get this running. I installed the packges using my Operating Systems package manager. I'm using Ubuntu Hardy Heron. The script I used to reproduce the solution on another machine (and thus to whose viability I can speak) is:
    sudo apt-get install libimage-exiftool-perl 
    sudo apt-get install libfreetype6-dev libfreetype6  
    sudo apt-get install libwmf0.2-7 ghostscript libjpeg62 
    sudo apt-get install libpng3 libpng3-dev  
    sudo apt-get install imagemagick  
    sudo apt-get install make gcc autoconf ruby rubygems ruby1.8-dev libmagick9-dev  
     
    sudo gem install rflickr 
    sudo gem install rmagick 
    sudo gem install mini_exiftool 
    sudo gem install openwferu-extras 
     

Code!

I took large swatches of this from loadr.rb script that ships with the Flickr library's source code. The application is anything if not fragile, and perhaps not even very efficient, but it does work, and that's what mattered here.

#!/usr/bin/ruby

require 'rubygems'
require 'pp'
require 'find'
require 'RMagick'
require 'fileutils'
require 'mini_exiftool'
require 'flickr'

#you will get these values when you sign up with Flickr. Make sure you choose the non professional version. 
$flickr_email = 'YOUR_YAHOO_EMAIL'
$api_key = 'YOUR_YAHOO_FLICKR_API_KEY'
$shared_secret =   'YOUR_YAHOO_SHARED_SECRET'
$flickr = Flickr.new("/tmp/flickr.cache", $api_key, $shared_secret) # change the path as you like 
setname = 'the_set_to_which_I_want_to_upload_these_photos'

def filename_to_title(filename)
    arr = filename.split(File::SEPARATOR).last.split('.')
    arr.pop
    my_title = arr.join('.')
end

# this will run each time. The first time it runs 
# it will cause Flickr to display a screen prompting you
# to give permission to the application, which you will do.
 
def auth_rflickr(api, secret)
    unless $flickr.auth.token
        $flickr.clear_cache
        $flickr.auth.getFrob
        url = $flickr.auth.login_link
        `firefox '#{url}'`
        puts "A browser is being opened to bring you to:\n#{url}. When you are done authorizing this application, hit enter."
        gets
        $flickr.auth.getToken
    end
end

# change the paths as you like 
dir_for_output =Dir.new( FileUtils.mkdir_p("../output"))
dir_for_input = Dir.new "/home/yourUser/Desktop/photos/" 

# here we run through the input folder and examine 
#the contents, building up the array of files to upload.
files= []
Find.find(dir_for_input.path) do |path|
    if !FileTest.directory?(path)
        tags = File.dirname(path )[dir_for_input.path.length .. -1]
        if tags[-1]== '/' or tags[0] == '/'
            tags = tags[1 .. -1]
        end
        if  ['.jpg', '.tiff', '.tif'].include? File.extname(path).downcase #only include images
            files << path
        end
    end
end


auth_rflickr($api_key, $shared_secret) unless $flickr.auth.token

# clean up the existing tmp folder
if File.exists?(dir_for_output.path )
    FileUtils.rm_rf(dir_for_output.path )
end

if not File.exists?(dir_for_output.path )
    if not Dir.mkdir(dir_for_output.path )
        raise "Can't create the directory!"
    end
end

sets = $flickr.photosets.getList
set = sets.find{|s| s.title == setname}  
set &&= set.fetch

eligible = (set ? set.fetch : [])
to_upload = []
uploaded = []

files.each do |filename|
    my_title = filename_to_title(filename)
    photo = eligible.find{|photo| photo.title==my_title}
    if photo
        uploaded << photo
    else
        to_upload << filename
    end
end

tix = []
to_upload.each { |fn|
    # here's where the most interestig work is done. 
    ifile= File.new fn  # output file
    ofile =   File.join( dir_for_output.path, File.basename(fn))  # input file 
    before = Magick::Image.read( ifile.path ).first # read in an image using ImageMagick 
    after = before.normalize 
    after.write( ofile )
    exif_out = MiniExiftool.new ofile
     # open the file with MiniExiftool, which wraps exif  
    #tool, and perform operations on the exif metadata.
    exif_in = MiniExiftool.new ifile.path
    exif_out['Orientation'] = exif_in ['Orientation']
    puts 'couldnt save exif data!' if !exif_out.save
    tags = File.dirname(fn )[dir_for_input.path.length .. -1] 
    if tags[0]== '/'
        tags = tags[1 .. -1]
    end
    if tags[-1] == '/'
        tags = tags.chomp
    end
    tags = tags.strip.split('/')
    tix <<  $flickr.photos.upload.upload_file_async( ofile, filename_to_title(ofile), 
       nil, 'tag1 tag2 tag3'.split(' ')+tags) 
# change these tags as you need to. They will be used to categorize the images on Flickr.  
}




tix = $flickr.photos.upload.checkTickets(tix)
while (tix.find_all{|t| t.complete==:incomplete }.length > 0)
    sleep 2
    puts "Checking on the following tickets: "+
            tix.map{|t| "#{t.id} (#{t.complete})"}.join(', ')
    tix = $flickr.photos.upload.checkTickets(tix)
end

failed = tix.find_all{|t| t.complete == :failed}
failed.each { |f|  puts "Failed to upload #{to_upload[tix.index(f)]}." }
0.upto(tix.length - 1) { |n| puts "#{to_upload[n]}\t#{tix[n].photoid}" }

uploaded += tix.find_all{|t| t.complete == :completed}.map do |ticket|
    $flickr.photos.getInfo(ticket.photoid)
end
uploaded.each do |photo|
    if set
        set << photo unless set.find{|ph| ph.id == photo.id}
    else
        set = $flickr.photosets.create(setname, photo, 'DESCRIPTION_HERE')
        set = set.fetch
        puts "creating set #{setname}"
    end
end

Tuesday Oct 07, 2008

TestNG, Spring TestContext, and Maven

If you've ever used the testing support in prior versions of Spring you know that it was essentially JUnit 3.x, oriented. There were ways to make those scaffolding classes work for (my personal favorite) TestNG or even Junit 4, but they largely were engineering hacks, not real solutions. For example, with the TestNG case you could override the setUp method and annotate it such that TestNG would call that method for setup, while also complying with Junit's interface requirements. Now there's a better way. Here's how I got it workiung with Maven and Surefire and TestNG 5.7. First, I added support for TestNG 5.7 (which is current as of this writing.):

<dependency> <artifactId>testng</artifactId> <groupId>org.testng</groupId> <version>5.7</version> <classifier>jdk15</classifier> </dependency>

Then I added support for SureFire to the Maven POM:

  <plugins> 
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> >
<version>2.4</version>
<configuration>
<suiteXmlFiles>

<suiteXmlFile>${basedir}/src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>

</plugin>

</plugins>

Finally, it comes time to write the test. Maven has a structure that's realized using the following command:

mkdir -p src/{test,main}/{java,resources};

Your unit test code goes into src/test/java and your testng.xml goes into src/test/resources.

Here's an example of the testng.xml:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"
> <suite name="myProject" verbose="5">
<test name="serviceTests">
<packages>
<package
name="com.joshlong.myProject.test.services"/>
</packages>
</test>

</suite>

And, finally, here's an example of a test class that works:

package com.joshlong.myProject.tests.services;
import com.joshlong.myProject.utils.LoggingUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests;
// THIS ONE's IMPORTANT! There are one of these for each of the 3 frameworks you're likely to want to use.
import static org.testng.Assert.assertTrue;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

/**
* @author Josh Long
*/
@ContextConfiguration(locations = {"classpath:service-context.xml", "classpath:test-context.xml"})
public class MyProjectTest extends AbstractTransactionalTestNGSpringContextTests {

@BeforeMethod public void announceClass() throws Throwable {
loggingUtils.log("Inside of MyProjectTest!");
}


@Autowired
private LoggingUtils loggingUtils; // this gets automatically injected from one of the contexts listed in the @ContextConfiguration annotations.

@Test
public void testBasicMath() throws Throwable {
loggingUtils.log("foo()");
assertTrue( 1 < 2, "1 < 2 -- pray that this is correct and that this test never does fail!");
}
}

Saturday Oct 04, 2008

GWT Continues to Produce Beautiful Sites

I stumbled upon the samples site from phpgwt.com – which features this application. The application seems to perform and work reasonably well in all browsers, although the transparent .pngs that are prevalent on the site don't seem to work well in Internet Explorer 6. Naturally, your mileage my vary, but I tested it against Firefox 3.0, Chrome, and Internet Explorer. Gorgeous. Similarly, look at the sample applications coming from ExtJS OR GWT-EXT. The first one's not quite as impressive as the second one, however, the second one may be at a dead end due to a licensing spat (as detailed here).

I should have a tutorial detailing how to get started with some of these technologies pretty soon.

Thursday Oct 02, 2008

J2ME and Android consitancy

Why is it that the basic 'optional' components on J2ME are pretty much the optional components on Android? What am I missing here? If you get a relatively new phone you're likely to get the same minimum requirements that you'll get from an Android phone – the things that are really interesting and attractive are optional, just as they're optional on J2ME. This applies, for example, to the GPS support, the ability to play MP3s, access the camera, etc. One thing I expect is that, because it's Google, that once you develop for Android and the phone "supports" the feature, then it won't be that hard to go from emulator to deployment on the handset with the same features. In the J2ME world, it's not easy to get an application that works identically once deployed without multi-hundred dollar certificates and so on. And of course, you still are better are programming to a common denominator if you want the application work across a lot of phones. Additionally, there are features that some phone supported that aren't supported in any one emulator, which means that testing j2ME is fine using the Wireless Toolkit but difficult if you're trying to access features from a Samsung A900 without then using Sprint's SDK. The Gphone is almost here, perhaps we'll start to get a feel for what that entails.

http://code.google.com/p/java-libcdrip/

I've just open sourced and released on Google code an Open API for interacting with CDDA data from Java. Right now the API does basics, only:

  • Eject a disc from a drive
  • Provide information about whether a CD is loaded
  • List the devices on the system (though this seems to be a little flaky at the moment, so we'll have to implement a strict policy of no refunds! <grin>
  • Enumerate how many tracks there
  • Rip tracks to a .WAV java.io.File object.
  • Derive the DISCID from the CD, which in turn can be used to get CDDB data

Naturally, there are many things to do be done, and the list is constantly growing.

The code itself is JNI code that exposes native code that I've built using two amazing open source projects.

On Linux, I'm using grip, cdio, and more, not to mention the GNU toolchain. On Windows, I'm using CDex.

Since the layer of code that is actually mine is very thin (just enough to normalize the two APIs so that I could get them to conform the JNI-vended header files), it would not be very much use working on this project (unless you REALLY want to!) Instead, support those projects directly.


Any feedback on the project is helpful. The C/C++ code is sort of slapdash and isn't necessarily the easiest to build unless you've had time with Eclipse CDT or Visual Studio .NET 2008, which is why there are prebuilt binaries in the lib directory in subversion.

Monday Sep 22, 2008

Getting Started with jBPM and Spring

My first article for TheServerSide.com. I am very excited to have this finally happen, and am frankly really looking forward to doing some more. The article is a discussion on setting up an architecture using worklists that depends on jBPM and Spring.


Any ideas? Suggestion? Leave a comment!

Wednesday Sep 17, 2008

Oracle Enterprise Pack for Eclipse

Dear Oracle,


You recently released
Oracle Enterprise Pack for Eclipse, which is a release of either Eclipse 3.3 (Europa) or Eclipse 3.4 (Ganymede) that supports using Weblogic as a server. This is nice because, up until now, the only way that I knew of to use WebLogic was to either use the Workshop product - which is an increasingly bad option as it's based on the equivalent of Eclipse 3.1 - or to use something like MyEclipse, which has a sort of half-hearted integration with Weblogic that misses the mark. I wanted to applaud your release. This isn't some cranked up Eclipse distro like Workshop and it's not some tightly-wound monster like JDeveloper. It's a simple solution to a simple requirement. Honestly, I'm surprised it happened after BEA got accquired! I would have thought Oracle would discontinued something like this!

I know that Oracle Enterprise Pack includes other niceties besides the integraion with Weblogic, but they are uninteresting to me, as Ganymede is a very compelling upgrade on its own strength.


Thank you, Oracle, for making development in the Enterprise a little easier.

Josh Long

Tuesday Sep 02, 2008

Google Chrome, beta

Alright, so I was really caught off guard by the announcement of Google Chrome (http://www.google.com/chrome). I’m REALLY impressed. It has every little key command I ever wanted: Ctrl+tab / ctrl + shift + tab moves you back and forward in your tabs. Ctrl + t create a new tab. Ctrl +L places the cursor in the location bar (and the location bar does double duty as your search bar, too! Nice! Even nicer: you can choose Microsoft as your search and they didn’t have to ask to get it that way!), etc. It even has the ability to drag tabs from the browser and 'attach' them, or detach them, at will. Again, very nice touch. It has every shortcut except one: F11. F11 (at least on IE, Firefox and Konqueror. Not Safari on Windows, I note!) maximizes the window and removes all the chrome. The reason for this should be stunningly obvious: it’s already as bare-minimal as you can get. But still, it’d be nice to have some way to go full screen. After all, how are the kiosk-esque apps supposed to work? What could be cooler than an entire application, full screen mode, written using GWT and the Google Gears extension library for GWT, deployed on Google Chrome, say at the library, or the airport? Who'd need the apple store? Imagine getting the Flash support up to snuff and deploying that on this crazy fast browser!

As a development tool, it’s definitely a solid third. Firefox + Firebug + Web Developer are the reigning champions, of course, then Safari and the hidden 'Developer' menu, then Chrome’s available but Spartan JavaScript debugger/ process monitor (a freaking process monitor! Awesome: Shift + Escape. Genius.)

Unlike Safari on Windows, the Chrome’s UI chrome seems to be rock solid. Of course, given the name it’d be ironic if that were anything less. If you manipulate Safari quick enough, it’ll stop painting itself and the grey brushed metal look will disappear to reveal standard blue + gray Windows 2000 chrome (you know, the minimize, maximize buttons, the title bar), but not so with Chrome. This could be because it’s very fast and I just haven’t found a way to get it to slow/falter.


I did have some issues with it, however. Flash flickers a bit for me – watching the video explaining Chrome, the faces would every so often flicker. I wonder if this is why they did a comic strip) It’s built using Webkit as the renderer, so most things work just fine, and it’s built using their own proprietary JavaScript VM, called V8. V8 is very interesting in that it means could potentially advance the state of the art with JavaScript. Or foul it up completely and introduce a 4th incompatible JS variant into the market. I tested a lot of different applications, however, and it seems to be working just fine. Great, in fact. I tried the usual suspects: Gmail, YouTube, Meebo, Flickr, Google Calendar and they all seemed to work fine. I use Roller for my blog and it in turn uses a widget for rich text editing. That rich text editor barked that it didn't support Mozilla < 1.3 when I tried to write this entry, but then insisted that it would try to materialize everything. It went ahead and sure enough everything works perfectly, even if the widget doesn't know it yet! Obviously the HTML heavy sites like Slashdot.org or Amazon.com worked just fine too, given the WebKit heritage.

I’m a little annoyed by the lack of Linux support (both from Google, and from Apple and their Safari product) given that WebKit was born of Konqueror’s source code. There does seem to be hope, though: the developer site at least has a doc explaining that Chrome doesn’t yet build/do anything useful on OS X / Linux. But at least they’re not pretending no one’s going to be looking for those builds!

All in all, bravo Google!


Update (08/03/2008) So, I wanted to install this sucker at work. I tried runninig it and sure enough it failed, bitten by the corporate firewall. Good for firewall, bad for me. I googled and with a little luck I chanced upon this revealing blog by Guru Prasath. I tried it and it works!

Tuesday Aug 19, 2008

Continous Integration Conundrum

 

[Read More]