Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Life outside the IDE

Coding in a parallel toolset has its perks -- freedom, for one

  • Print
  • Feedback

Page 3 of 4

Is it HTTPThing or HttpThing?

Using an editor that's not joined at the hip to a compiler will show how well you really know the libraries you use every day. Unfortunately, the deck is stacked against you. The proliferation of code completion has allowed some libraries to give in to baroque tendencies, burying nearly every class five packages deep and naming it with an entire sentence of camel-cased words. Java code has mutated from plain text into something that nearly requires machine assistance to edit.

This doesn't just limit options for editing verbose libraries; it makes coding in a creative flow quite impossible. Instead of translating mental logic into computer instructions with confidence, a programmer relying on command completion works like a lazy actor constantly calling out for the next line. There is some hope of reversing the trend, but for now using a simple editor will require determined typing and a ready access to API references.

And for those references, the way out of the hole is not so slippery after all. Because Maven repositories can hold not only compiled packages but their sources and Javadocs as well, it's possible to obtain documentation for a project without regressing to Internet hunting and gathering -- that is, when your builder is hackable. (Sorry, Maven.)

Listing 4. Buildr function to acquire library documentation

def doc_tasks(jar_spec)
      artifacts(jar_spec).map do |a|
        doc_a = artifact(a.to_hash.merge({:classifier=>'javadoc'}))
        doc_a.extend SoftFail
        file(_(LIB_DOCS) + '/' + a.to_spec => doc_a) do |task|
          unzip(task.name => doc_a) if File.exist? doc_a.name
        end
      end
    end

The Ruby function for Buildr illustrated in Listing 4 accepts artifact specifications and returns an array of tasks that will, if invoked, download and extract Javadocs paired with those artifacts into the project subdirectory specified by LIB_DOCS. The function could go into a Rakefile, or into another file included by it. Because Buildr's artifacts method can handle all manner of nested artifact specifications, so can lib_doc_tasks.

The procedure quickly runs into a problem: not all libraries maintain corresponding Javadoc artifacts. Normally, Buildr's artifact task will abort the build on a download failure, but we don't want to abort, nor do we want to manually purge an artifact tree of those that don't have matching Javadocs. The solution, then, is the ad hoc SoftFail module in Listing 5, which overrides the failure method to warn only.

Listing 5. Module to override a Buildr download failure

module SoftFail
      def fail_download(remote_uris)
        puts "Can't find javadoc #{to_spec}\n"
      end
    end

From inside a Buildr project, call lib_docs with some specs, and add all the created tasks as prerequisites to the new lib_docs task in Listing 6.

Listing 6. Adding the documentation tasks to a build

doc_tasks(WICKET).each { |t| task :lib_docs => t }

Now you can sit back, go offline, and really get to know those libraries you've been using for the past few years.

Contain yourself

Editing and compiling is nice, but the destiny of all software code is execution. And these days, most of it is executed in the name of serving Web pages. Here the road to a simple and flexible toolset turns away from finicky servlet containers and leads to a landscape of server embedding.

If it seems strange to serve Web requests directly from an application, that's only because the Servlet API has from its inception taken a different approach. But today the HTTP protocol is so fundamental, so much a part of the software zeitgeist, that it makes perfect sense to serve requests from an application -- just as we initiate requests internally with a library like HttpClient.

Jetty is a very popular embeddable servlet container. By linking to its JARs (under org.mortbay.jetty at the Maven repo) you can start a server from a main() function in short order, as shown in Listing 7.

Listing 7. Kickoff function for an embedded Jetty server

public static void main(String[] args) throws Exception
    {
      Server server = new Server();
      WebAppContext web = new WebAppContext();
      web.setContextPath("/");
      web.setWar("src/main/webapp");
      server.addHandler(web);
      SelectChannelConnector httpConn = new SelectChannelConnector();
      httpConn.setPort(8080);
      server.setConnectors(new Connector[] { httpConn });
      server.start();
      System.out.println("Ready at http://localhost:8080/");
      server.join();
    }

This could be run from a packaged JAR, but it's most convenient to run it before packaging from a builder that knows your classpath. To run with buildr myproj:run, add the run task in Listing 8 to a Buildr project.

Listing 8. Buildr task to run an embedded server

task :run => :compile do
      java('example.CalcServer', 
        :classpath => compile.classpath + [compile.target.to_s])
    end

Or, if the exec-maven-plugin is configured as shown in Listing 9, you could run from Maven with mvn exec:java.

Listing 9. Maven configuration for an embedded server

<plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>exec-maven-plugin</artifactId>
      <configuration>
        <mainClass>example.CalcServer</mainClass>
      </configuration>
    </plugin>

Either way, you'll want to add shortcuts for these commands to your editor. Embedding a server doesn't just make it easy to run Web apps in a builder with no plug-ins or other configuration; it also means that such apps can be run inside any IDE as plain Java applications with no container configuration, allowing for the maximum use of running code replacement. Speaking of which, aren't we going to miss code replacement in a decentralized toolset?

  • Print
  • Feedback

Resources
  • Download the source code for calc, the sample application that accompanies this article.
  • Not quite ready for life outside the IDE? Tune in to this week's JavaWorld podcast, where Andrew Binstock rounds up the top Java IDEs today and wonders aloud what impact Google could have on IDEs in 2008.
  • The Wicket Apache project helps you develop Web applications.
  • Ratpoison is an ultra-stripped-down window manager for Unix-like OSes.
  • TextMate is the text editor used in this article's examples.
  • Buildr is a Rake-based builder that's compatible with Maven's local and remote repositories.
  • Apache Maven is a software project management and comprehension tool.
  • Rake is a Ruby-based build tool, similar to make in build and purpose.
  • Apache Commons HttpClient provides HTTP client functionality beyond the basics of the java.net package.
  • Jetty is a pure Java HTTP server you can embed directly into your applications for on-the-fly testing.
  • With JavaRebel, you can change Java classes on the fly without redeploying your applications.
  • Scala is a programming language that is interoperable with Java.
  • Check out the Scala definitions that allow for syntax coloring in a variety of editors.
  • Learn more about Scala in this JavaWorld podcast with Bill Venners.
  • Visit the JavaWorld Java development tools research center for more articles about tools that can help you be more productive in your programming efforts.
  • Also see Network World's IT Buyer's Guides: Side-by-side comparison of hundreds of products in over 70 categories.