ZFS blog carnival

The Zettabyte File System (ZFS) was released yesterday as part of OpenSolaris build 27 and to celebrate, the ZFS community is having a (one time?) blog carnival, hosted by Bryan Cantrill.

UPDATED: I had the wrong link to Bora's entry about blog carnivals.


Status, CC: world


It's been a while since I did a status report, so here are some updates on the public projects I'm working on at work and in my off-hours.

Roller 1.3 released: it's been announced on the project blog and is now available on Java.Net. It's a minor bug fix release and I expect that most sites will want to wait for Roller 2.0 instead of installing 1.3.

Roller 2.0 release on the way: blogs.sun.com has been running a Roller 2.0-based build for a couple of weeks now, but the Roller project still hasn't packaged up a final release. We've been testing a release candidate of Roller 2.0, doing final testing and debugging. We may be able to release 2.0 within the next week, depending on how testing goes. Unfortunately Javalobby is running into some problems will the upgrade process and they may turn out to be 2.0 bugs. Want to know more about Roller 2.0? Check the Roller 2.0 documentation summary page.

Roller 2.1 development starting: it will focus on spam prevention/management and performance improvements, for details check the Roller 2.1 proposal page.

The Roller@Apache move: Roller has been in the Apache Software Foundation (ASF) Incubator for about five months now. Roller code is in ASF's Subversion repository, a status page is in place, dev/user discussions take place on the ASF mailing lists and our ASF mentors are listening in and advising us. The Roller dev community seems to be growing, thriving and recently, really pulling together to get 1.3 and 2.0 out the door. That's all good, but there have been some hold-ups.

Nothing is holding up Roller development, but we've been waiting for ASF's new LGPL license policy. We will eventually have to deal with our LGPL dependency, but until ASF announces its new LGPL policy, we won't know exactly what we need to do.

Recently there was some question about whether we should be allowed to make the Roller 1.3 and Roller 2.0 releases, since they contain and depend on LGPL licensed components (most notably Hibernate). We resolved that bit of controversy and are now cleared to release Roller 1.3 (which we did) and Roller 2.0 (coming soon). Since we're in the ASF Incubator, our releases are not official/endorsed ASF releases.

RSS and Atom in Action still in limbo: the book is delayed because the Atom protocol is not complete. Draft 06 wasn't bad, but it was missing important pieces, like category support. Unfortunately, Atom protocol is not just incomplete, it's also in flux. The working group is having a very hard time dealing with introspection and discovery. So, I can't finish Chapter 8, but we've have been moving the rest of the chapters through production.

Blogapps project born: I started a Java.Net project called Blogapps for the RSS and Atom in Action examples and uploaded the code, but I haven't made a release yet. I hope to release the examples bundle and the Blogapps Demo Server, which is a super easy-to-install blog/wiki server based on Tomcat, HSQLDB, Roller and JSPWiki.

Note that this blog is my personal blog and I don't claim to speak for my employer, my publisher, the Roller project or the ASF.


That's refreshing

I get the feeling a lot of people are clicking the refresh button today and seeing this message from Google Analytics:

Analytics has been successfully installed and data is being 
gathered now. Your first reports will be ready within twelve hours.

And it's not just us cheap bastards either, paying customers are also waiting. Sounds like somebody failed to plan.

I'm in ROME

ROME logo

YeeeHAI! I've been accepted as a committer on the ROME project, which is very convenient because I have a big ole chunk'o'code to commit for Atom 1.0 format support. After reviews and tweaks, Atom format 1.0 support should be available in ROME v0.8.


Today's links [November 14, 2005]

Triangle Bloggers Bash, Tuesday 7-9PM

Triangle area bloggers don't miss the Triangle Bloggers Bash, tomorrow night from 7-9PM in downtown Durham, NC.

Start at new WUNC studios for tour, talk about podcasting and reception with catered food. Short welcome messages from Joan Siefert Rose and Keith Westin of WUNC, Michael Goodmon of ATHD, Stephen Fraser of Lulu. Then move next door to Tyler’s Speakeasy for drinks and socializing. Short welcome messages from John Conway of WRAL.com and Henry Copeland of blogads.

Today's links [November 13, 2005]

Runnin' time

It's Old Reliable Run time. I ran the course last week and I'm still alive. I'm hoping to repeat that result today, so wish me luck. Check out the route. It passes every important downtown Raleigh landmark including the capitol square, Krispy Kreme, the mold-infested governor's mansion, Sadlacks and the fabulous NCSU bell tower.

Update: Results are in. I did better than I'd expected.

Place Bib  Name           S City     St Chiptim Guntime Pace  
===== ==== ============== = ======== == ======= ======= ===== 
  601  395 DAVID JOHNSON  M Raleigh  NC   55:36   56:01  9:01 

Today's links [November 12, 2005]


Roller-based geo-aggregator under development

Migs Paraz has got some interesting ideas about building a geo-aware blog community aggegator, based in part on the Recovery 2.0 call to convene post and thread at Jeff Jarvis's site. And what's more, he's started a proof-of-concept site, based on Roller's built-in planet aggregator, Google Maps API and the GeoInfo RSS module. It didn't work in all my browsers, so here's a screen-shot:

Roller with geo-aggregation via Google maps integration


Thanks Max

Max Rudman just submitted a patch for Oracle support in Roller. It looked very safe, so we added it into the Roller 2.0 code base. I don't believe any of the Roller developers run Oracle at this time. That means we really can't support it very well unless Max is about, but the code is there, so there's hope for those who wish to run Roller with Oracle. Thanks Max!

Top'o'the line Java tools free (as in beer)

Both Java Studio Creator and Java Studio Enterprise are now free to Sun Developer Network members, which is also free. Judging from the wording on the page, this looks like a limited time offer. Check out the flash-demo of Studio Enterpise on the SDN free Java tools page, the UML tool looks very cool.


Today's links [November 08, 2005]


Atom protocol draft 06 for Roller, Atom format 1.0 for ROME

It took most of the weekend, but I implemented both an Atom protocol draft 06 client and a server. I committed the client to the Blogapps project and the server to Roller trunk (in the sandbox of course). Along the way, I updated my Atom 1.0 patch for ROME to support relative URI parsing and multiple authors per feed and entry. I sent that to the ROME dev list.

I hope to put together a Blogapps release this week containing both client and server. Anybody up for Atom protocol interop testing?


Old Reliable Run a week away

Old Reliable Run logo

I'm signed up for the 10K and I'm a little behind in my training, but I'm up to 5.8 miles now so I'm starting to believe that I'll be able to run it without stopping.

Yep. Low expectations... the key to success ;-)


del.icio.us links [November 03, 2005]


Scripting Roller with Groovy

A Roller developer who's just getting started wrote in with the question "what I'd like to know is what Roller API we should use for doing each of the following":

  • creating a new blog
  • creating a blog entry
  • entry comments
  • categories and blogroll

I don' really like the term "Roller API" because Roller is an application, not a toolkit. With the possible exception of a couple of plugin interfaces, we don't really promise to support a stable API from release to release. So, I'll show you how to use the Roller classes to do the things you want to do, but keep in mind that those classes are likely to change in future Roller releases.

If there is a Roller API, it's gotta be the manager interfaces in org.roller.model and the POJOS in org.roller.pojos. And if you want to learn how to use the API, the best places to look for examples are the Struts actions in all those packages under org.roller.presentation and the JUnit tests under the tests directory. I know its a pain to tromp around somebody else's code trying to figure out what's going on, so I'll give you some easy to follow examples. But I'm gonna have some fun; I'm going to present the examples in Groovy.

Get ready to groove#

First, you'll need to install Groovy, which you can get at the Codehaus. I'm using groovy-1.0-jsr-03 and I've got it installed in the directory /Applications/Java/groovy-1.0-jsr-03. Next, you'll need to install Roller 2.0. Since Roller 2.0 has not been released yet, you'll need to get it from Subversion repository and build it yourself. Follow the instructions in the Roller Developer Guide.

To prepare to run Groovy with Roller, create a directory and put the script and config files below into it. You can find examples of the files below in the Resources section at the end of this article.

  • run-groovy: UNIX sh script that adds Roller jars and Roller classes to the Groovy classpath and then runs Groovy. You'll need to edit this file to set ROLLER_HOME, GROOVY_HOME and JDBCJAR.
  • hibernate.cfg.xml: same as the Hibernate config that comes with Roller, except it contains JDBC DriverManager connection parameters instead of a JNDI DataSource reference. You'll have to add your database connection parameters in this time (i.e. username, password and connection URL).
  • ehcache.xml: just a dummy config to satisfy ~EHCache.
  • log4j.properties: just a dummy config to satisfy ~Log4J.

It may be possible to avoid that run-groovy script, but you'll probably have to the Roller jars to a ~/.groovy/lib directory or some such thing. If you want to go that route, check the docs on Running Groovy.

Once you've got those files in place, you're ready to groove with Roller.

Example #0: Connecting to Roller#

First, let's test our ability to connect to Roller. Open up a command-prompt window, cd to the directory where those config files live and create the following Groovy script with the name rollertest1.gy:

rollertest1.gy

println "\nCreating Roller instance... "
t0 = System.currentTimeMillis();
roller = org.roller.model.RollerFactory.getRoller();
t1 = System.currentTimeMillis();
println "   Created Roller implementation in " + (t1-t0)/1000 + " seconds";
println "Number of users in system: " + roller.getUserManager().getUsers().size();

That's a simple little script that will create a Roller instance, get the user manager and print the number of users in the system. I put the calls to System.currentTimeMillis() so we can measure the startup time. Now, let's run it with ./run-groovy rollertest1.gy. When you run it you should see something like this:

$ ./run-groovy rollertest1.gy

Creating Roller instance... 
   Created Roller implementation in 7.388 seconds
Number of users in system: 1
$ _

That's what it looks like when it works. Startup time sucks, doesn't it? I think we can blame most of the statup time on Hibernate. It might be possible to speed things up a bit with pre-compiled mapping files. Anyhow, if the example doesn't work and you see a gigantic stack trace instead, then you've got something wrong in run-groovy and/or hibernate.cfg.xml. You'll need to get this simple example working, or none of the following examples will work either.

Example #1: Creating a new blog#

You need a user to create a blog, so we'll create both. First, the user creation script. I'm going keep things simple and set the user creation parameters up front. After defining the variables, we create a UserData object and set the username, password and other parameters. We get the Roller object from the RollerFactory, begin a transaction as the SYSTEM_USER, call the UserManager.addUser() method to complete user creation, and commit the transaction. Finally, we verify that things worked by fetching the new user and printing its name and id.

Here's a script that creates a user account for Jamaican recording artist Lee "Scratch" Perry. As with example #0 you can run script with ./run-groovy.

createuser.gy

username =    "scratch;
password =    "jam342down";
fullName =    "Lee Perry";
email =       "lee.perry@upsetter.net";
locale =      "en_GB";
timeZone =    "America/Jamaica";

user = new org.roller.pojos.UserData();
user.setUserName(username);
user.setPassword(password);
user.setFullName(fullName);
user.setEmailAddress(email);
user.setLocale(locale);
user.setTimeZone(timeZone);
user.setDateCreated(new java.util.Date());

roller = org.roller.model.RollerFactory.getRoller();
roller.begin(org.roller.pojos.UserData.SYSTEM_USER);
roller.getUserManager().addUser(user);
roller.commit();

user = roller.getUserManager().getUser(username);
println "Created user ${user.userName} with id ${user.id}";

When you run that, you'll see something like this:

$ ./run-groovy createuser.gy
Created user scratch with id 402881e40751c5ec010751c5f7cd0001
$ _

To create a blog, use the UserManager's createWebsite() method. "Website" you wonder? That's historical: Roller weblogs have always been represented by WebsiteData objects and stored in the website table in the database. That's enough teary eyed reminiscence. Below is a script that rolls up a nice fresh blog for Mr. Perry. First, we define the blog creation parameters. After that we get the Roller object, begin a transaction as the SYSTEM_USER, fetch Perry's user object, call UserManager.createWebstite() to create the website and commit the transaction. Finally, we verify that creation worked by fetching the blog and print its name and id.

createblog.gy

username =    "scratch";
blogname =    "Technomajikal";
description = "Who put the voodoo pon reggae";
handle =      "scratchblog";
theme =       "basic";

roller = org.roller.model.RollerFactory.getRoller();
roller.begin(org.roller.pojos.UserData.SYSTEM_USER);
user = roller.getUserManager().getUser(username);
website = roller.getUserManager().createWebsite(
   user, 
   null, // hmm... this argument needs to go away 
   handle, 
   blogname,
   description,
   user.getEmailAddress(),
   theme,
   user.getLocale(),
   user.getTimeZone());
roller.commit();

blog = roller.getUserManager().getWebsiteByHandle(handle);
println "Created blog ${blog.name} with id ${blog.id}";

Example #2: Creating a blog entry#

Now let's create a blog entry in Mr. Perry's blog. After setting up the paramters, we get the Roller object, start a transaction as the SYSTEM_USER, fetch the objects we need, user, blog and category. Next we create the WeblogEntryData object and set the require properties, including entry title and text. Finally, we save and commit the new entry. Easy as pie, but I'll admit the Timestamp fields are a bit annoying.

createentry.gy

username = "scratch";
handle =   "scratchblog";
title =    "Test post";
text =     "Testing 1 2 3 <em>Hello World!</em>";
catpath =  "/General";
 
roller = org.roller.model.RollerFactory.getRoller();
roller.begin(org.roller.pojos.UserData.SYSTEM_USER);

user = roller.getUserManager().getUser(username);
blog = roller.getUserManager().getWebsiteByHandle(handle);
category = roller.getWeblogManager().getWeblogCategoryByPath(blog, null, catpath);

entry = new org.roller.pojos.WeblogEntryData();
entry.setWebsite(blog);
entry.setCreator(user);
entry.setCategory(category);
entry.setPubTime(new java.sql.Timestamp(new java.util.Date().getTime()));
entry.setUpdateTime(new java.sql.Timestamp(new java.util.Date().getTime()));
entry.setTitle(title);
entry.setText(text);
entry.setStatus(org.roller.pojos.WeblogEntryData.PUBLISHED);
entry.save();

roller.commit();

Example #3: Creating entry comments#

Creating a comment is just as easy as creating an entry. Create the object and save it. The only trick here is that we use the entry anchor to fetch the entry to be commented. Each entry has an anchor, which is a unique ID for the entry within the weblog. We assume that you ran example #2 and therefore an entry exists with anchor "test_post".

createcomment.gy

handle =  "scratchblog";
name =    "Dave Johnson";
email =   "dave@example.com";
url =     "http://example.com";
anchor =  "test_post";
email =   "test@example.com";
content = "Testing 1 2 3 <em>Hello World!</em>";
 
roller = org.roller.model.RollerFactory.getRoller();
roller.begin(org.roller.pojos.UserData.SYSTEM_USER);
blog = roller.getUserManager().getWebsiteByHandle(handle);
entry = roller.getWeblogManager().getWeblogEntryByAnchor(blog, anchor);

comment = new org.roller.pojos.CommentData();
comment.setWeblogEntry(entry);
comment.setName(name);
comment.setUrl(url);
comment.setPostTime(new java.sql.Timestamp(new java.util.Date().getTime()));
comment.setContent(content);
comment.setNotify(Boolean.FALSE);
comment.save();

roller.commit();

Example #4: Creating categories and blogroll#

This Groovy Roller thing grown tiresome, so I'm going to short-change you here. Anyways, you don't really need to know how to create a blogroll for your new blogs, because Roller does that for you. The UserManager.createWebsite() method creates the bookmarks specified by the configuration property newuser.blogroll. It also creates the categories specified by newuser.categoies. Take a look at the Roller Configuration Guide to learn how to override those properies in your Roller installation.

Resources#

Example configuration files needed for running Groovy Roller examples.

run-groovy This one is setup for my computer. You'll have to edit those first three export statements to set your Grooovy and Roller homes and the path to your JDBC driver jar. Make the file executable with chmod +x run-groovy. And of course, if you're using Windows then you'll have to convert this thing to a DOS BIATCH file, or whatever it's called.

#!/bin/sh
export GROOVY_HOME=~/groovy
export ROLLER_HOME=~/roller_2.0/build/roller
export JDBCJAR=~/tomcat/common/lib/postgresql.jar

export CLASSPATH=.:\
${GROOVY_HOME}/embeddable/groovy-all-1.0-jsr-03.jar:\
${GROOVY_HOME}/lib/commons-cli-1.0.jar:\
${ROLLER_HOME}/WEB-INF/lib/rollerbeans.jar:\
${ROLLER_HOME}/WEB-INF/lib/rollercontrib.jar:\
${ROLLER_HOME}/WEB-INF/lib/rollerweb.jar:\
${ROLLER_HOME}/WEB-INF/classes:\
${JDBCJAR}:\
${ROLLER_HOME}/WEB-INF/lib/hibernate3.jar:\
${ROLLER_HOME}/WEB-INF/lib/dom4j-1.6.jar:\
${ROLLER_HOME}/WEB-INF/lib/ehcache-1.1.jar:\
${ROLLER_HOME}/WEB-INF/lib/jta.jar:\
${ROLLER_HOME}/WEB-INF/lib/cglib-2.1.jar:\
${ROLLER_HOME}/WEB-INF/lib/asm.jar:\
${ROLLER_HOME}/WEB-INF/lib/asm-attrs.jar:\
${ROLLER_HOME}/WEB-INF/lib/jdom.jar:\
${ROLLER_HOME}/WEB-INF/lib/rome-0.7.jar:\
${ROLLER_HOME}/WEB-INF/lib/rome-fetcher-0.7.jar:\
${ROLLER_HOME}/WEB-INF/lib/log4j-1.2.4.jar:\
${ROLLER_HOME}/WEB-INF/lib/commons-logging.jar:\
${ROLLER_HOME}/WEB-INF/lib/commons-collections.jar:\
${ROLLER_HOME}/WEB-INF/lib/commons-lang-2.0.jar
java -classpath ${CLASSPATH} groovy.lang.GroovyShell $1 $2 $3

hibernate.cfg.xml This one's configured for PostgreSQL with username/password scott/tiger. You'll have to edit it to set your database connection parameters.

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
        <property name="hibernate.connection.url">jdbc:postgresql://localhost/rollerdb_20</property>
        <property name="hibernate.connection.username">scott</property>
        <property name="hibernate.connection.password">tiger</property>
        <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
        <mapping resource="org/roller/business/HitCountData.hbm.xml" />
        <mapping resource="org/roller/pojos/BookmarkData.hbm.xml" />
        <mapping resource="org/roller/pojos/CommentData.hbm.xml" />
        <mapping resource="org/roller/pojos/EntryAttributeData.hbm.xml" />
        <mapping resource="org/roller/pojos/FolderAssoc.hbm.xml" />
        <mapping resource="org/roller/pojos/FolderData.hbm.xml" />
        <mapping resource="org/roller/pojos/WeblogTemplate.hbm.xml" />
        <mapping resource="org/roller/pojos/PingCategoryRestrictionData.hbm.xml" />
        <mapping resource="org/roller/pojos/AutoPingData.hbm.xml" />
        <mapping resource="org/roller/pojos/PingQueueEntryData.hbm.xml" />
        <mapping resource="org/roller/pojos/PingTargetData.hbm.xml" />
        <mapping resource="org/roller/pojos/RefererData.hbm.xml" />
        <mapping resource="org/roller/pojos/RoleData.hbm.xml" />
        <mapping resource="org/roller/pojos/RollerConfigData.hbm.xml" />
        <mapping resource="org/roller/pojos/UserData.hbm.xml" />
        <mapping resource="org/roller/pojos/UserCookieData.hbm.xml" />
        <mapping resource="org/roller/pojos/WeblogCategoryData.hbm.xml" />
        <mapping resource="org/roller/pojos/WeblogCategoryAssoc.hbm.xml" />
        <mapping resource="org/roller/pojos/WeblogEntryData.hbm.xml" />
        <mapping resource="org/roller/pojos/WebsiteData.hbm.xml" />
        <mapping resource="org/roller/pojos/RollerPropertyData.hbm.xml" />
        <mapping resource="org/roller/pojos/PermissionsData.hbm.xml" />
        <mapping resource="org/roller/pojos/PlanetConfigData.hbm.xml" />
        <mapping resource="org/roller/pojos/PlanetGroupData.hbm.xml" />
        <mapping resource="org/roller/pojos/PlanetEntryData.hbm.xml" />
        <mapping resource="org/roller/pojos/PlanetSubscriptionData.hbm.xml" />
        <mapping resource="org/roller/pojos/PlanetGroupSubscriptionAssoc.hbm.xml" />
    </session-factory>
</hibernate-configuration>

log4j.propeties No need to edit this unless you want to change loggging levels.

log4j.rootCategory=ERROR, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss,SSS} | %C{1}:%M | %m%n
log4j.category.org.roller=ERROR
log4j.category.org.hibernate=ERROR
log4j.category.org.apache.struts=ERROR
log4j.category.org.apache.velocity=FATAL

ehcache.xml No need to change this either, unless you know something about EHCache.

<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        overflowToDisk="true"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120"
        />
</ehcache>

Raleigh/Cary blog meetup tonight

It's that time again folks. Time to come on down to Cafe Cyclo in Cameron Village, enjoy your favorite beverage (and they've got 'em all) and meet your fellow Raleigh bloggers. YO! News and Observer bloggers, come on down. Ryan and Rafe and Raleighing? SAS, IBM and VSNC bloggers join us!

As usual, Josh has the details.

Cool JDIC embedded native browser screenshot

Geertjan's got a very cool screenshot of (what looks like) Mozilla embedded in Netbeans via the JDIC project's Embedded Browser Component.

« Previous page | Main | Next page »