Tom's Blog
Clojure's inventor and author make a case for the new language
Published by Tom |
March 18, 2010 07:55 AM EST |
Rich Hickey, inventor of the Clojure language,
and Stuart Halloway, author of "Programming Clojure,"
presented introductory and advanced concepts of the young JVM language at
Wednesday's Northern Virginia Java Users Group.
These are some of my notes from the meeting.
The session served to whet interest in learning Clojure,
thus these notes do not include a lot of code or explain Clojure's unusual syntax.
There are
many
other
sources
for that.
Clojure, a Lisp-like language that compiles to Java byte code and runs on the Java virtual machine, was created as a general-purpose programming language that embraces a functional style of software design, rather than the imperative style typical in languages like Java -- and most other general purpose languages in use today. Functional programming languages like Clojure, Scheme and Erlang have been getting a lot of attention at technology conferences over the last few years, which first brought my attention to Clojure. Its functional style and its ability to run alongside and integrate with existing Java code interested me in learning more about Clojure. The fact that its inventor and a technology instructor I highly respect were presenting a free session on Clojure compelled me to attend the JUG meeting.
Rich Hickey released the first version of Clojure in October, 2007, with version 1.0 released May 1, 2009. We are talking about a young language. Still, from what I learned last night, it looks like a powerful language with potential. Clojure is released as open source under the Eclipse Public License 1.0, which makes it easy to use in a non-open source commercial environment.
Stuart Halloway
According to Stu, some of the compelling features of Clojure are its:
- Easy interoperability with Java
- Lisp syntax
- Functional style
- Ability to run in a multi-threaded environment with no coding overhead
(defn blank? [s]
(every? #(Character/isWhitespace %) s))
I'm not a Clojure programmer (yet) but I think I captured the above syntax correctly.
Like Ruby,
Clojure uses the question mark to replace the traditional "is" prefix in boolean functions.
The # symbol introduces an anonymous function.
From what Stu described,
the functional programming paradigm in Clojure handles most (all?) corner cases for you.
There is no need to write special-case "if" statements to deal with a null parameter,
for instance.
For Clojure's interoperability with Java, Clojure code can call Java, and Java code can call Clojure functions. (According to Rich, the integration is implemented with little or no need to use Java reflection at runtime, adding less runtime overhead.)
For Clojure's advantage by using Lisp syntax, Stu referred everyone to Paul Graham's 2001 article, "What Made Lisp Different" as the best explanation. Most languages have "special forms" like imports, scopes, protection definitions, metadata, keywords. These special forms are language features you can use, but you cannot create them yourself and add them to the language. These language features are thus unavailable for reuse. Lisp abandoned this restriction. In a Lisp-like language, special forms of the language look like anything else in the language. All forms of the language are created equal. In Lisp (and Clojure), defining scope, the control flow, method calls, operators, functions, import mechanisms -- they are all lists. Stu said a language's "special forms" restrictions cause a programming language to "crap out," and joked that the restrictions bring about magical cut-and-paste reuse workarounds we call "design patterns."
For Clojure's advantage by being a functional language, Clojure encourages you to write small pieces of code that work well together. Good code has the same shape as pseudo code, he said, and Clojure's functional style lets you create more pseudo-code looking real code. According to Stu, functional languages are simpler to understand. They let you write code that eliminates or reduces what he called "incidental complexity" required by non-functional languages:
- Corner cases
- Class definitions
- Internal exit points
- Variables
- Branches
The final benefit he talked about is Clojure's inherent ability to run in a multi-threaded environment with no special concurrency-handling code from the developer. Clojure and other functional programming languages perform this feat by treating data as immutable and producing a new copy of a data structure when data needs to be changed. Two threads never look at the same data at the same time, so there is never any need to synchronize access to code that reads and writes data. Clojure's solution, Stu said, is to separate identify from value. He went on to explain what this means, but maybe the late hour caused me to miss the details.
Rich Hickey
After Stuart set the stage for why learn and use Clojure, Rich Hickey took over to talk about new features he is adding to the language. He said, quite truthfully, that for those in the audience who don't already know Clojure, what he was about to say would not make a lot of sense. These features are Protocols, Reify and Datatypes. As a result of my newness to Clojure, I will pass along what I thought Rich said and hope he and the Clojure crowd forgive my ignorance.
Rich Hickey, inventor of Clojure, speaking March 17, 2010 at the
Northern Virginia Java Users Group meeting. [taken from my phone]
Rich, for an open source programming language inventor, was a refreshingly clear advocate for his new language. Maybe I'm jaded from years of slogging through open-source code, but from my experience, most open source projects release their code with little explanation of how or even why to use it, and then treat users like they are the ones who failed if they misunderstand how to use the code correctly. Rich actually understood where most of us in the audience were coming from. "I know it's a big deal to try to learn a new programming language," he said, but he believes Clojure is worth taking the time to learn and will make our jobs as programmers easier.
Before delving into the new features he is adding, Rich provided a summary of how Clojure is implemented. Part of it is written in Java for performance, and the rest is written in Clojure itself. He said his goal is to eventually write most of Clojure in Clojure once he can get performance boosted to an equivalent level.
Clojure is built using abstractions, with those abstractions written as Java interfaces. The fundamental implementation objectives of Clojure (or at least the ones I picked up on), he said, are to leverage high-performance polymorphism mechanisms of the host environment, to write to abstractions not concrete types, and to enable extension and interoperability with Java.
From what I understood of the new language features, Protocols are named sets of generic functions. Reify allows developers to use the "cool code generation" in the built-in fn function. "I put a lot of work into 'fn' and I wanted to make it reusable," he said. Even though it went over my head, Rich said Reify allows developers to create an instance of an unnamed type that implements protocols, like proxy for protocols. For the new Datatypes feature, if I understood correctly, he said he added a new construct, deftype, to define a name for a type and list of fields in that type.
Additional details that might make sense if you know Clojure:
- Datatypes fields can be primitives
- Datatypes support metadata and value-based equality by default
- In-line method definitions are true methods, no indirection or lookup and calls can be inlined by just-in-time compilers, like Hotspot
- Keyword-style field lookups can be inlined just like (.field x) calls
Thursday March 18, 2010 Permalink
Comments [0]
Adding shutdown hooks to a desktop Griffon application
Published by Tom |
September 23, 2009 09:53 AM EDT |
Technical pride prompted me to write my first Griffon application Tuesday.
Griffon
is a Groovy-based framework to write Java desktop applications.
Groovy
takes some of the sting out of writing Java Swing applications
and Griffon relieves more of the burden.
My pride came into the picture when
Manning Publications
released its daily
Pop Quiz
yesterday asking what technique one would use to
process the shutdown of a Griffon application running on OS X.
Manning posts a new question each day of September,
and as of today,
I'm running a perfect score.
I couldn't let a little question about Griffon stop me.
However,
since Griffon is so new (its stable release is 0.1.2)
and developers are only now starting to play with it,
googling around for a simple answer didn't turn up much.
After failing to find sample Griffon code that described the application shutdown process (especially with the question's wrinkle of using OS X), I figured I'd write a simple Griffon desktop application and give the technology a spin. In the category of famous last words, "How hard could it be?" Turns out, thankfully, not that hard.
After downloading the Griffon 0.2-BETA zip file, setting my GRIFFON_HOME environment variable to point to the folder where I unzipped the files, and adding the $GRIFFON_HOME/bin directory to my PATH for convenience, I was ready to create my first Griffon application. I followed the instructions on the Griffon Quick Start page and ran the command:
griffon create-appand typed in my project name (quiz) to create all the files needed for a basic application. The
create-app command generates the application scaffolding
along the lines of other modern frameworks like
Rails,
Grails,
App Fuse
and even
Maven.
Once the create-app command created the skeletal the application files, I followed the sample code on the Griffon Quick Start page to augment the files with code to create a simple desktop application. The application provides a window that lets you type in and execute code in the Groovy shell. Griffon structures its files around the Model-View-Controller pattern, creating subdirectories for "models", "views" and "controllers". Here are the directories in the project's "griffon-app" folder:
$ ls griffon-app conf/ controllers/ i18n/ lifecycle/ models/ resources/ views/Figure 1 shows the resulting application in action, which you can build and run using the command
griffon run-app.
I typed the two Groovy statements into the window and clicked the Execute button.
Figure 1: Griffon Quick Start application window
griffon-app/views/QuizView.groovy
to define application properties for
defaultCloseOperation and
windowClosing
so the top of my QuizView.groovy now looked like this:
QuizView.groovy:
import javax.swing.WindowConstants
application(
title:'quiz',
pack:true,
locationByPlatform:true,
iconImage: imageIcon('/griffon-icon-48x48.png').image,
iconImages: [imageIcon('/griffon-icon-48x48.png').image,
imageIcon('/griffon-icon-32x32.png').image,
imageIcon('/griffon-icon-16x16.png').image],
defaultCloseOperation: WindowConstants.DO_NOTHING_ON_CLOSE, // ADDED PROPERTY HERE
windowClosing: { evt -> // AND HERE
println "QuizView.groovy: windowClosing event called!"
System.out.flush()
app.shutdown()
}
In addition to the println statement to tell me my shutdown hook was invoked,
I needed to add the call to app.shutdown() since I was now telling Java not
to end the application when its main window was closed by setting the defaultCloseOperation property
to the DO_NOTHING_ON_CLOSE.
I followed Josh's tip on editing the
griffon-app/conf/Application.groovy
file to set the autoShutdown property to false.
This flag is needed so my window-closing event code would be run instead of the default auto-shutdown behavior.
(Thanks for the tip, Josh.)
Application.groovy:
application {
title='Quiz'
startupGroups = ['quiz']
// Should Griffon exit when no Griffon created frames are showing?
autoShutdown = true
// If you want some non-standard application class, apply it here
//frameClass = 'javax.swing.JFrame'
}
mvcGroups {
// MVC Group for ""
'quiz' {
model = 'QuizModel'
controller = 'QuizController'
view = 'QuizView'
}
}
Now when I run the application and close the window,
the console shows:
$ griffon run-app Welcome to Griffon 0.2-BETA - http://griffon.codehaus.org/ Licensed under Apache Standard License 2.0 Griffon home is set to: /home/tom/Projects/Griffon/griffon-0.2-BETA Base Directory: /home/tom/Projects/ManningQuiz/quiz Running script /home/tom/Projects/Griffon/griffon-0.2-BETA/scripts/RunApp.groovy Environment set to development Warning, target causing name overwriting of name default [groovyc] Compiling 3 source files to /home/tom/.griffon/0.2-BETA/projects/quiz/classes QuizView.groovy: My windowClosing event called!That's one way to add a shutdown hook to a Griffon application, by adding a listener to fire when the application's window closes. However, this discovery didn't answer the Manning quiz. None of the available answers showed this technique.
More searching around the web pointed me to the compellingly sounding
griffon-app/lifecycle
files created by the create-app scaffolding command.
One of these auto-generated files is called Shutdown.groovy.
It couldn't get more obvious or more easy than that,
I suppose.
The contents of this file show helpful comments describing how to add shutdown hooks to your application.
griffon-app/lifecycle/Shutdown.groovy
/*
* This script is executed inside the EDT, so be sure to
* call long running code in another thread.
*
* You have the following options
* - SwingBuilder.doOutside { // your code }
* - Thread.start { // your code }
* - SwingXBuilder.withWorker( start: true ) {
* onInit { // initialization (optional, runs in current thread) }
* work { // your code }
* onDone { // finish (runs inside EDT) }
* }
*
* You have the following options to run code again inside EDT
* - SwingBuilder.doLater { // your code }
* - SwingBuilder.edt { // your code }
* - SwingUtilities.invokeLater { // your code }
*/
I thought I'd edit this file and add some custom shutdown code.
I added this to the end of the above file:
import groovy.swing.SwingBuilder
def swing = new SwingBuilder()
swing.doOutside {
println "doOutside called in the Shutdown.groovy lifecycle"
}
With these few extra lines of code, running the application (griffon run-app) and closing the window
resulted in these lines on the console.
(I eliminated the Griffon startup information.):
QuizView.groovy: My windowClosing event called! doOutside called in the Shutdown.groovy lifecycleInteresting to see that the application's window-closing event occurred before the application shutdown event. That makes perfect sense.
But Wait, There's More
Unfortunately, this solution didn't seem to satisfy any of the available options in the Manning quiz. (Except for the tantalizingly tempting "None of the above" fourth option.) I didn't want to give up yet in finding a solution. The available quiz answers that seemed worthy of looking into talked about defining event handlers for the "ShutdownStart" event or the "ShutdownEnd" event. According to the Release Notes for version 0.1, runtime events may be added to the controller class. The notes list all events that may fired by the application during its life cycle:
- BootstrapEnd
- StartupStart
- StartupEnd
- ReadyStart
- ReadyEnd
- ShutdownStart
ShutdownEnd is in the list,
I figured the Manning quiz answer was probably defining an event handler for ShutdownStart.
Since I wanted to be sure,
I added a tiny event handler,
with code borrowed from the sample in the Release Notes,
to my controller class in griffon-app/controllers/QuizController.groovy:
def onShutdownStart = { app ->
println "Controller onShutdownDown says ${app.config.application.title} is shutting down."
}
I re-ran the application and shut it down,
and the console now showed:
QuizView.groovy: My windowClosing event called! Controller onShutdownDown says Quiz is shutting down. doOutside called in the Shutdown.groovy lifecycleThe lines show all of my shutdown code successfully got called. So here's what I learned in my foray into Griffon:
- There are at least THREE ways to handle events that fire when an application is shut down
- Writing event listeners in Groovy/Griffon is a lot easier than Swing
- There is no requirement to register the runtime event with the source of the event
- Griffon (and Groovy) do their share to ease programming by defining conventions over requiring configuration
create-app
command got me started and running quickly.
I was able to create a Griffon desktop Java application,
add three ways to capture runtime events,
compile and test the application several times --
all in less time it took me to write this blog documenting these facts.
I don't know whether Griffon can win the hearts of developers who want to
write desktop applications,
but I sure think it can win the hearts of Java developers who would otherwise be stuck writing a straight Swing application.
If you're a Swing developer,
definitely check out what Groovy and now Griffon have to offer in ease of development and simpler code writing.
I look forward to seeing what Griffon becomes once it reaches the 1.0 milestone.
Wednesday September 23, 2009 Permalink
Comments [0]
Alfresco Software says freeloading corporations led them to closed-source strategy
Published by Tom |
April 01, 2009 06:59 AM EST |
Alfresco Software said Tuesday it will not release certain new enterprise features of the Alfresco
content management products,
such as high-availability clustering,
as open source as a way to persuade freeloading companies to pay up.
John Newton, CTO and co-founder of Alfresco Software Inc.,
posted notice
of this new business strategy in a blog entry that effectively says
Fortune 50 users of the free version of Alfresco are cheapskates.
He reassures everyone in his blog that core components of Alfresco will remain open
source and free.
Alfresco thus joins other commercial open source projects,
such as MySQL,
in bifurcating their source code into a core version licensed as open source,
and a version with features important to large businesses (the ones with money)
available for a fee.
In a blog last August, Andrew Lampitt called this division an "open-core licensing" model. This division is now officially reflected in Alfresco Software's release Tuesday of Alfresco Enterprise 3.1.
Newton implied in his blog that Alfresco Software was pushed to close-source enterprise features of Alfresco for financial reasons. Many "world-class companies" with "household brands" are using Alfresco's free and open source Labs version, he wrote, and not paying the annual Enterprise subscription. Enterprise subscriptions are a source of revenue for Alfresco Software. Subscribing customers receive a more stable "Enterprise Edition" of the Alfresco content management suite, dedicated support, and optional training and consulting. By releasing enterprise features of Alfresco only to paying customers, Newton said, he hopes Alfresco's largest users will see the benefit of paying Alfresco an annual subscription rather than paying their own developers to figure out how to deploy Alfresco in a high-availability environment or writing their own management tools.
If indeed Alfresco Software won't be able to survive (or at least thrive) without finding a more sustainable revenue source, this move sounds like a good strategy. It will allow Alfresco to continue to improve its already excellent enterprise content management system while allowing smaller companies to use Alfresco's core products for free. If, however, this bifurcated source code strategy is merely a way to return higher profits to Alfresco's founders and funders, the change might negatively impact how Alfresco Software is perceived by developers writing useful extensions and integrations and releasing them as free, open source. Open source developers release their code for the community's benefit as a whole, but might hesitate to do so when a corporation profits indirectly from their work.
There is nothing wrong with a corporation out to make money, and adopting the "open core" model might be the best move for Alfresco's future -- as a product and as a company. I don't know whether much or any of the Alfresco "core" code base was written by non-Alfresco employees. If not, the risk of Alfresco losing contributions from external open source developers is small. Other "community" contributions, like free technical support offered by fellow users on the Alfresco forums, likely will continue unaffected by the licensing change because much of that free exchange of information is among users of the free Labs version.
From what the privately held Alfresco Software says publicly, it isn't hurting for money. Alfresco employees I spoke with last year say the company is profitable. Matt Asay, Alfresco's vice president of business development, said in a CMS Wire story Tuesday by Barb Mosher that sales have been increasing recently by more than 27% from the quarter before. On Monday, Alfresco Software released limited financial information for its fiscal year ended Feb. 28. The news release says Alfresco Software Inc. closed the 2008 fiscal year with a 103% year-over-year revenue growth and a 92% increase in revenue from the fourth quarter of 2008 compared to the same quarter in 2007. It also added 270 paying customers during the 2008 fiscal year.
Newton wrote in his blog that Alfresco Software looked at options other than close-sourcing enterprise features. Alfresco considered "crippling" the open source version, he said, or letting the open source branch become so cutting-edge that it fell "into a destabilized state." But going that route "would make it difficult for certain governments to use our product," he said, and could cause the open source community to create competing forks to fix the crippleware.
Newton said Alfresco's new software model will adhere to these six principals:
- Alfresco extensions to create high-availability, clustered systems and provide better monitoring and and administration will be developed as closed source.
- The core system and interfaces will remain 100% open source.
- Bugs fixed for Enterprise customers will be folded into the next open source Labs release.
- Code that Alfresco Software writes for paying customers to integrate Alfresco with proprietary systems will remain closed source.
- Integrations to "ubiquitous" proprietary systems, like SharePoint, will remain open source.
- Alfresco will continue to support paying customers to the levels of their SLAs.
Wednesday April 01, 2009 Permalink
Comments [3]
Installing Groovy from RPM on Fedora
Published by Tom |
March 21, 2009 06:11 PM EST |
I installed Groovy 1.6 on Fedora from an RPM as offered on the
Groovy download
page and immediately got an exception stack trace when running groovysh or groovyConsole.
I installed the groovy-1.6.0-2.noarch.rpm file,
kindly packaged by Federico Pedemonte,
then tried to run groovyConsole:
[tom@dev ~]$ groovyConsole Exception in thread "main" java.lang.NoClassDefFoundError: org/codehaus/groovy/tools/GroovyStarter Caused by: java.lang.ClassNotFoundException: org.codehaus.groovy.tools.GroovyStarter at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:252) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) Could not find the main class: org.codehaus.groovy.tools.GroovyStarter. Program will exit.I then tried to run groovysh with no better luck:
[tom@dev ~]$ groovysh Exception in thread "main" java.lang.NoClassDefFoundError: org/codehaus/groovy/tools/GroovyStarter Caused by: java.lang.ClassNotFoundException: org.codehaus.groovy.tools.GroovyStarter at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:252) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) Could not find the main class: org.codehaus.groovy.tools.GroovyStarter. Program will exit.The problem turned out to be quite simple to solve: a missing GROOVY_HOME. The packager adds the environment variable GROOVY_HOME to the shell by adding the file /etc/profile.d/groovy.sh so bash picks it up at startup via the /etc/profile script, but my current shell hadn't had a chance to read in that file yet.
The solution was as easy as exiting and starting a new shell, or manually setting:
[tom@dev ~]$ export GROOVY_HOME=/usr/share/groovy [tom@dev ~]$ groovyConsoleand everything works.
Saturday March 21, 2009 Permalink
Comments [0]
How to modify the Alfresco Share page footer
Published by Tom |
March 18, 2009 09:18 AM EST |
Share is Alfresco Software's open source collaboration server.
It's a Java web application that stands as a free competitor to Microsoft
SharePoint.
Since I
wrote earlier
this month about how to modify the default footer text
in the Alfresco content management server's web client,
I thought I'd follow up with even simpler instructions on how to modify
the global footer in
Alfresco Share.
You don't even need to stop and restart the web application server
for this modification.
Share is part of the open source Alfresco Labs 3 and the commercial Alfresco Enterprise Edition enterprise content management server and is built using Alfresco's Surf web framework. The Share application comes fully functional out of the box (more precisely, out of the share.war file). But it also is highly customizable with a little HTML, JavaScript and FreeMarker script modifications or additions. Thus, the default footer text in Share is much easier to modify than it is in the Alfresco web client I wrote about earlier.
The web client, which is a JavaServer Faces application, embeds the footer text inside a Java tag library inside a JAR file inside the
alfresco.war
file.
You need the source code and a JDK to modify the global footer text.
The Share web application,
more simply,
places its footer text inside a properties file inside the
share.war file,
which you can customize with a plain text editor.
If you deploy Share as a WAR file instead of an exploded WAR,
you'll need to unzip the WAR, edit the text file, then rezip.
But that's about as complex as this change gets.
To customize the footer text for Share, unzip the
share.war
file if necessary to a directory of your choosing
or just find the exploded WAR file you have currently deployed.
If you run Share on Tomcat,
your deployed Share application likely is in the directory
$CATALINA_HOME/webapps/share
(or
%CATALINA_HOME%\webapps\share
under Windows).
The file to modify is in the directory
WEB-INF/classes/alfresco/site-webscripts/org/alfresco/components/footer
called
footer.get.properties.
On my version of Alfresco Share,
this default footer file looks like this (but all on one line):
label.copyright=Supplied free of charge with <a href='http://www.alfresco.com/services/support/communityterms/#support'>no support</a>, <a href='http://www.alfresco.com/services/support/communityterms/#certification'>no certification</a>, <a href='http://www.alfresco.com/services/support/communityterms/#maintenance'>no maintenance</a>, <a href='http://www.alfresco.com/services/support/communityterms/#warranty'>no warranty</a> and <a href='http://www.alfresco.com/services/support/communityterms/#indemnity'>no indemnity</a> by <a href='http://www.alfresco.com'>Alfresco</a> or its <a href='http://www.alfresco.com/partners/'>Certified Partners</a>. <a href='http://www.alfresco.com/services/support/'>Click here for support</a>.<br /> Alfresco Software Inc. © 2008-2009 All rights reserved.This text gets rendered on every Share page as a footer that looks like this:
You can see why someone might want to change this global footer text.
Change the text to anything you like and save
footer.get.properties
file.
Mine now says:
label.copyright=Alfresco Software Inc. © 2008-2009 All rights reserved.
To see your change,
you can either restart your web application server if no one is using Share,
or you can tell Share to refresh its web components cache without inconveniencing anyone
currently using the server.
Here's how.
Login to Share as the "admin" user and visit the service
/share/service
path of the Share application.
If you are running Share on your Tomcat local server,
the path is probably
http://localhost:8080/share/service/.
This page will have a button at the bottom labeled "Refresh Web Scripts".
Click it,
and your footer text change should be loaded the next time the footer component script is called.
Ahh. Much better.
If you build Share from source, you can make your footer text change there by making the change to the "slingshot" project. That apparently was the earlier name of the Share application. The file is
config/alfresco/site-webscripts/org/alfresco/components/footer/footer.get.properties
Making this footer change might whet your appetite for making other customizations to your Share application. The Surf component framework makes customization fairly easy once you get the hang of how Surf works. By being able to see your changes quickly by interactively refreshing the web scripts rather than restarting the server, your feedback comes quickly.
Wednesday March 18, 2009 Permalink
Comments [0]


