Tom's Blog
Deleting old Confluence backup files
Published by Tom |
September 29, 2006 03:27 PM EDT |
After I
installed
the Confluence wiki,
I discovered I need to do at least one thing to maintain it.
By default,
Confluence
makes a backup of the site every morning at 2 a.m.
The files will keep building up unless you do something about it.
On a small Confluence site like mine,
it would take a couple of years to fill the disk.
But in case your site is large and you haven't already put something in place
to prune the older backup files,
here's a simple Unix shell script you can add to your Cron configuration.
#!/bin/sh # Script to remove the older Confluence backup files. # Currently we retain at least the last two weeks worth # of backup files in order to restore if needed. BACKUP_DIR="/data/web/confluence/backups" DAYS_TO_RETAIN=14 find $BACKUP_DIR -maxdepth 1 -type f -ctime +$DAYS_TO_RETAIN -deleteConfluence backs up the site to a
backups subdirectory.
You can tell where that is (and change it if you want) under your
Administration -> Daily Backup Admin page.
I put this script on my Linux box in the
/etc/cron.weekly directory.
Since I run the script only weekly,
more files will build up than defined by the DAYS_TO_RETAIN variable,
but my Confluence site is small and this doesn't matter to me.
If your site is larger, you might want to put the script under
/etc/cron.daily.
Confluence uses Quartz to schedule backups, so if you want to change the time from 2 a.m. (or make backups less or more frequent), see the Confluence Changing time of Daily Backup page for instructions.
Friday September 29, 2006 Permalink
Concurrency the Java 1.5 way
Published by Tom |
September 27, 2006 01:09 AM EDT |
I attended a talk tonight on Java concurrency presented by
Stuart Halloway
at the
Northern Virginia JUG
that provided a refresher on the
java.util.concurrent
package.
Stuart is one of the founders of
Relevance,
author of
Component Development for the Java Platform,
a frequent speaker at
technical symposiums,
co-author of
Rails for Java Developers,
and a great technical speaker.

Stuart Halloway
When considering multi-threading in order to increase the speed of a process, it is important to consider whether the slowness is due to the application being suspended while waiting for an external resource (e.g. a database, user input, disk), or whether the process is suspended while waiting for free CPU cycles. If the process is waiting for an external resource, Stuart said, the language and the number of CPUs won't matter much. "Java, assembly language and PHP all wait at the same speed," he said.
Stuart's talk covered:
- Threads
- Tasks and scheduling
- Locking
- Concurrent collections
- Alternatives to threads
- Keep a user interface responsive (think Swing)
- Take advantage of multiple processors in compute-heavy applications
- Simplify code that would otherwise need to keep checking if other tasks need to be performed (implementing their own task-scheduling loop)
Thread objects as the main way to
achieve concurrency.
Developers would write a class that implements Runnable and
pass an instance to a Thread.
Two of the shortcomings of the Runnable interface is
its single method, run,
doesn't return anything and it isn't declared to throw an
exception to indicate anything went wrong.
"It's completely wrong," Stuart said.
Java 1.5 introduced higher-level classes to allow more abstraction away from Thread objects. It introduced the
Callable interface,
whose call method does return something and
is declared to throw an Exception.
Programmers write Callable classes and pass instances to one of the three
ExecutorService classes obtained by the
Executors Java factory,
or perhaps from an external library.
The ExecutorServices provided by the Executors factory
provide single-theading execution,
and execution by two types of thread pools,
a cached, expandable thread pool or a fixed-size thread pool.
When you give a Callable to an ExecutorService, you get back a
Future object containing the results of the Callable's execution.
The result can be an object or an exception that will be thrown.
Stuart demonstrated code that exercised the new threading objects
and shows how to use them.
The code and the slides from his presentation is available
online.
The Need for Locking
You don't need locks if you're just telling separate tasks to run concurrently. You need locking code when multiple threads access the same data at the same time. Java provides lock support with the:
synchronizedkeyword and blocks- Java 1.5 Lock interface objects, which offer an improvement over a straight synchronized block because you can tell the code to give up its attempt to acquire a lock after a timeout period expires.
- ReadWriteLock interface, which offers separate locks for whether the process needs to read data or alter the data.
Concurrent Collection Options
Strategies and the implications of using concurrent collections: strategy and implications:
- Do nothing
It's fast, simple, but not thread-safe - Fail-fast iterators (introduced in Java 1.2)
Fast, not thread-safe. Misuse of concurrent access probably will cause a fast failure. Fail fast uses optimistic locking: It assume everyone can access a shared resource and uses clean-up code if something goes wrong with multi-threaded writes. Java collections implement the fail-fast strategy by using version numbers that iterators use to see whether the collection has changed. - Lock the entire collection
Simple, slow, might be thread-safe (likeHashtable) - Lock partial collection
Complex, maybe faster, maybe thread-safe. - Copy on write
Fast read access, may read stale data. When you write to a collection, you get new copy, so your write can proceed. Iterators for reading threads point to older collection, so data can be stale. - Immutable
Fast, simple, thread-safe, cannot change objects. - Application-controlled locking
Difficult, allows any combination of the above strategies.
Collections and strategies
- Legacy (pre-Java 1.2): Lock entire collection
- Collections (1.2) API: Lock none, fail-fast iterators
- Synchronized wrappers (1.2): Lock entire collection
- ConcurrentHashMap: Lock partial collection
Uses "lock-striping" to allow uses of different buckets in a hash. - CopyOnWriteArrayList: Copy-on-write
Very expensive if using big arrays that are written to regularly. Every write to the collection copies it again. Only advantageous if data is read-mostly. - String: immutable
Alternatives, pros and cons:
- Container-managed threads: Simple. inflexible
Like J2EE containers. You write applications as if you are the only user of the object. Scales well because most data in server side is in the database. The DB controls concurrency. - Non-blocking I/O: Do work when available. Con is it as complex as using threads
For example, thejava.nio(1.4) package. Pro: Do multiple operations and notify me when done. Con: As complicated as threads. Oriented around blocking waits. Tends to get ignored when you're coding on the server-side. - Use multiple processes: Pro: simple. Con: inflexible
When you need to perform more work, start more processes. - Event-driven code: Con: as complex as threads
- Do nothing: Pro: simple. Con: slow (but performance might not matter for the application)
"Probably more time has been wasted by optimizing code that doesn't need to be optimized."
For Java developers interested in learning more about programming using concurrency, Stuart recommended Java Concurrency in Practice by Brian Goetz. The book mixes academic rigor on threading with practical implications for Java developers, he said.
Stuart also will be in town Wednesday night to speak at the Northern Virginia Ruby User's Group. He'll be talking about the Streamlined framework for rapidly developing CRUD applications in Rails.
Wednesday September 27, 2006 Permalink
Stopping Firefox from auto-searching from the address bar
Published by Tom |
September 26, 2006 02:03 PM EDT |
Of the many wonderful features I enjoy in the Mozilla
Firefox
browser,
the feature to automatically perform a Google "I'm feeling lucky" search
whenever I accidentally type a bad URL or
keyword
into the address bar isn't one of them.
The feature in question is Firefox's default behavior to replace the word or words it finds in the address bar with the URL
http://www.google.com/search?btnI=I%27m+Feeling+Lucky&ie=UTF-8&oe=UTF-8&q=[address bar text]when what you type in the address bar doesn't look like a valid URL or one of the "Quick Search" bookmark keywords. I really like the keyword search feature. I'm constantly typing goo <search terms> into the Firefox address bar to perform a fast Google search. Firefox comes predefined with a Google search keyword as one of the "Quick Search" bookmarks. (I shortened the default "google" keyword for simplicity.) Firefox also comes with predefined keywords to search Wikipedia (wp), an online dictionary (dict), a stock-price lookup (quote), etc.
The problem with Firefox's automatic "I'm feeling lucky" search arises when I mistype one of my keyword searches. For instance, if my Yahoo keyword search is "yah" but I accidentally type
ya spring mvcinstead of performing a Yahoo search for sites talking about Spring's MVC web framework, I end up, for instance, at one of the Spring forum pages that happens to have the word "ya'll" in it. Google's "I'm feeling lucky" search thinks that's the page I want because it has the words
ya, spring, and mvc.
(We can leave aside for now whether ya'll is a word.)
Since I don't usually want Google to select a search-result page for me, I don't often use its "I'm feeling lucky" search. Except, that is, when I have a typo in my Firefox URL or keyword search on new installations of Firefox before I disable the automatic search feature.
Here's how to tell Firefox not to perform an "I'm feeling lucky" search whenever it doesn't understand the address you type in:
- Put your cursor into the Firefox address bar (Ctrl-L is a fast way)
- Type about:config
- In the Filter text box, type "keyword" and hit Enter or wait a second.
You'll see a line that says:
keyword.enabled default boolean true
- Double click on this line. The line will become bold and the value will change from true to false to indicate the feature is now turned off.
- You're done
After you type the "about:config" and filter the results to the "keyword" configuration settings, you'll also see the "keyword.URL" preference setting. That's the URL Firefox uses to take you to the "I'm feeling lucky" Google search. If you like the Firefox auto-search feature but want to change the search URL, you can change the value by right-clicking on the line and selecting "Modify."
This level of configurability in Firefox is one of those features I really like. Instead of the typical software attitude of, "You don't like our default behavior? Tough!" Firefox lets you change many preferences to suit your own likes and dislikes.
Tuesday September 26, 2006 Permalink
JNDI error with Roller weblogger on Fedora Core 5
Published by Tom |
September 24, 2006 03:38 PM EDT |
While planning my upgrade from
Roller
2.1 to 2.3,
I ran into an unexpected snag in Tomcat 5.5 running on Fedora Core 5.
After I installed Roller 2.3 on my Fedora server and upgraded my database,
Tomcat couldn't seem to create the <Resource> for the JDBC datasource.
My catalina.log file had this unrevealing (to me) error:
Sep 22, 2006 9:23:29 AM org.apache.catalina.core.NamingContextListener addResource
WARNING: Failed to register in JMX: javax.naming.NamingException: Cannot create resource instance
Sep 22, 2006 9:23:47 AM org.apache.catalina.core.StandardContext start
SEVERE: Error filterStart
Sep 22, 2006 9:23:47 AM org.apache.catalina.core.StandardContext start
SEVERE: Context [/roller] startup failed due to previous errors
Exception in thread "Thread-9" java.lang.NullPointerException
at org.apache.roller.business.runnable.WorkerThread.run(WorkerThread.java:83)
at org.apache.roller.business.runnable.ContinuousWorkerThread.run(ContinuousWorkerThread.java:83)
The "Error filterStart" message seems to be Tomcat telling me that it
couldn't start one of Roller's servlet filters after
WorkerThread threw the NPE.
Nowhere was Tomcat telling me, however, what resource it was trying to add at the time.
The messages in the roller.log file showed more helpful information. Roller obviously couldn't pull the DataSource from JNDI using the naming context
java:comp/env/jdbc/rollerdb:
INFO 2006-09-22 09:23:30,239 RollerConfig:<clinit> - successfully loaded default properties.
INFO 2006-09-22 09:23:30,293 RollerConfig:<clinit> - successfully loaded custom properties file from classpath
INFO 2006-09-22 09:23:30,297 RollerConfig:<clinit> - no custom properties file specified via jvm option
WARN 2006-09-22 09:23:30,347 RollerContext:upgradeDatabaseIfNeeded - Unable to access DataSource
javax.naming.NamingException: Cannot create resource instance
[stack trace]
[Hibernate logging statements]
INFO 2006-09-22 09:23:41,904 NamingHelper:getInitialContext - JNDI InitialContext properties:{}
FATAL 2006-09-22 09:23:41,914 DatasourceConnectionProvider:configure - Could not find datasource:
java:comp/env/jdbc/rollerdb
javax.naming.NamingException: Cannot create resource instance
[stack trace]
ERROR 2006-09-22 09:23:41,928 RollerFactory:setRoller - Error instantiating org.apache.roller.business.hibernate.HibernateRollerImpl
java.lang.reflect.InvocationTargetException
[stack trace]
Caused by: org.apache.roller.RollerException
at org.apache.roller.business.hibernate.HibernateRollerImpl.<init>(HibernateRollerImpl.java:73)
at org.apache.roller.business.hibernate.HibernateRollerImpl.instantiate(HibernateRollerImpl.java:84)
... 31 more
FATAL 2006-09-22 09:23:41,938 RollerFactory:setRoller - Failed to instantiate fallback roller impl
java.lang.Exception: Doh! Couldn't instantiate a roller class
Still,
the log messages weren't pointing me to why the datasource wasn't getting registered.
I checked and double-checked the spelling from my Tomcat
roller.xml context file and couldn't find any
typos or bad configuration settings:
<Context
path="/roller"
docBase="/home/tom/apps/roller/2.3/roller"
debug="0"
/>
<Resource
name="jdbc/rollerdb"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/roller?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&mysqlEncoding=utf8"
username="[username]"
password="[password]"
maxActive="20"
maxIdle="3"
removeAbandoned="true"
maxWait="3000"
/>
My roller configuration seemed correct.
My initial Google search didn't turn up a solution,
and neither did my search of the Roller FAQs or the
Apache roller-user mailing list.
But I did notice that if I google the exact string,
"WARNING: Failed to register in JMX: javax.naming.NamingException: Cannot create resource instance,"
from the Tomcat log,
the two search returns both mentioned Fedora Core.
My environment:
O/S: Fedora Core 5 (Linux kernel 2.6.17)
Server: Tomcat 5.5.15 (from FC5 "core" repository)
JVM: Sun's Java 1.5 (build 1.5.0_07-b03)
Database: MySQL 5.0.22 (from FC5 repository)
I thus shortened some of my search terms and added "Fedora Core 5" into the search, and came across this message from PKR Internet's task list for its "Taskjitsu" product that pointed right at the problem. According to that message, Tomcat 5.5 is built so the default datasource naming factory is
org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory
from the naming-factory-dbcp.jar JAR file.
But the Fedora Core install package for Tomcat 5.5,
tomcat5-5.5.15-1jpp_6fc,
does not ship that JAR or its factory class in any other JAR file.
There are two ways to solve the problem. The first is to add a
factory attribute to the Roller webapp's
roller.xml context with a
<Resource> element that defines the Jakarta commons DBCP
BasicDataSourceFactory class:
factory="org.apache.commons.dbcp.BasicDataSourceFactory"
The second way is to grab a copy of
naming-factory-dbcp.jar from a binary distribution of Tomcat 5.5
and install it in Fedora Core's Tomcat common/lib directory
(default /usr/share/tomcat5/common/lib).
I don't know if one solution is preferable to the other.
Both solutions work,
and the latter solution probably will resolve the same issue for other web applications.
However,
it seems adding two JARs that might share some of the same classes could lead to
future ClassCastExceptions if for some reason the order of the JARs change
in a classpath search.
This event doesn't seem likely,
though,
as long as Tomcat controls the search order for classes in common/lib.
Comments appreciated on whether one solution is better than the other.
After I found these solutions, I was going to post it as an FYI to the roller-user mailing list. Before I did, I poked again through the list archives to see if someone else already mentioned it. Sure enough. I found this email from Conor P. Cahill, posted July 6, by searching for fedora. Conor's subject line was "MySQL Database connector problems," which is why I think I missed it on my first search.
His email detailed the problem and proposed adding the factory attribute to the <Resource> element.
Since I didn't find Conor's email on my first search for a solution, I thought I'd post the problem and solution here, with the log errors, in the hope it helps other Fedora Core users.
Sunday September 24, 2006 Permalink
Comments [3]
Atlassian Branches Into CI and SSO
Published by Tom |
September 20, 2006 05:39 PM EDT |
Last night, I attended what was billed as the first-ever Atlassian user-group meeting.
Scott Farquhar, one of the founders of
Atlassian Software Systems
in Australia,
was here in northern Virginia for the event.
One of the more interesting segments of the evening was Farquhar's roadmap of future Atlassian products and what's coming in new versions of JIRA and Confluence. In addition to those issue-tracking and wiki products, Atlassian will be releasing a continuous integration product called Bamboo (available for download in early beta form), and a single sign-on and identity management product called Crowd. Both products will be priced in the $1,000 to $5,000 range.
One of the key motivators for Bamboo was that existing CI products, like CruiseControl, are complex to install and configure, Farquhar said. A goal of Bamboo is to be up and running in five minutes.
Crowd will be Atlassian's release of Authentisoft's IDX single sign-on product, developed in J2EE. Atlassian acquired Authentisoft earlier this month. More about the IDX acquisition is available on this TSS discussion thread.
For existing products, Farquhar said coming in JIRA 3.7 will be project roles and Issue Navigator views. Version 3.8 will support hierarchical project categories. Internally, he said, JIRA 4.0 will be built using Maven 2, and more of the base functionality will be pushed into plugins for easier customization. Coming in Confluence 2.3 will be a clustered version to scale to several thousand users (with the help of Tangosol's Coherence clustered caching product), and a people directory to view and find other wiki users.
It was interesting to hear that Confluence has a bigger need to scale than does the more popular JIRA issue tracker. Most JIRA installations manage projects for a division, he said, but companies are installing Confluence to be their corporate-wide collaboration tool, so it needs to be clustered. Because more large companies are using Confluence, Farquhar said, version 3.0 will add improved WYSIWYG page editing, as well as LDAP support, better backup and restore, and a simple installer.
Also as part of the evening, Jonathan Nolen from Atlassian talked about the latest JIRA and Confluence plugins. Some of the plugins, like embedding an Excel document in a wiki page and displaying a calendar from an iCal file, look downright useful.
Wednesday September 20, 2006 Permalink


