« Raleigh/Cary blog... | Main | del.icio.us links... »

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>

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed

« Raleigh/Cary blog... | Main | del.icio.us links... »

Welcome

This is just one entry in the weblog Blogging Roller. You may want to visit the main page of the weblog

Related entries

Below are the most recent entries in the category Roller, some may be related to this entry.