Thursday, November 29, 2007

Displaying a spinning wheel image during a Dynamic Faces Ajax transaction.

I am currently building a JSF application using Netbeans 6.0. For this project I use a wide range of Woodstock components and also the Dynamic Faces extension to ajaxify some of these . As some Ajax transactions may take some time to complete, I wanted to provide the user with some visual feedback that something is happening in the background.

So these are the steps you need to follow in order to display a spinning wheel gif while the client is waiting for the server response.

  • Visit the Ajax loading gif generator and create a gif. There are plenty of similar sites in the web.
  • And an image component to the web page. This must be initially hidden, so specify visibility: hidden in the style attribute of the image. I suggest this property over the display: [none/block], because the visibility property reserves the space occupied by a hidden component.
  • Create a Javascript function that toggles the image visibility and makes it visible.
    var showLoading=function(element) {
        var loadingImage = $(element);
        loadingImage.style.visibility = 'visible';
    }
    
    This function receives one string argument (the id of the image) and uses the prototype dollar function.
  • Now we need to call this method when the ajax transaction is initiated. This happens in the onClick event action method of a button or hyperlink component, by calling the DynaFaces.Tx.fire(...) function. So we just need to add a call to the showLoading function right before this.
  • The final step is to hide the image when the transaction completes. This can be done by adding the image component to the "re-render" list of components of the AjaxTransaction component. This is enough, because when the image component is re-rendered when the response is received, it uses the initial value of the visibility property, which is set to 'hidden'.

Thursday, November 15, 2007

Internationalizing Woodstock components

Project Woodstock offers a set of very useful JSF components, some of which are included by default in NetBeans 6.0. The labels, messages etc used by these components can be internationalized by following these steps:

  1. Create a new resource bundle properties file woodstock.properties. An existing one can be used, but it's better to keep things clean.
  2. Declare the bundle in web.xml.
    <context-param>
            <param-name>com.sun.webui.theme.THEME_RESOURCES</param-name>
            <param-value>my.package.woodstock</param-value>
    </context-param>
    Note that you must use the fully qualified name of the properties file (if it is placed in a package).
  3. The Woodstock Theme Doc pages include a list with all the key-value pairs for woodstock messages. You can override these in the new properties file.

Tuesday, November 13, 2007

Dynamic Faces and encoding problems

Dynamic Faces is part of the JSF extensions project, and it offers an easy way to ajaxify plain old JSF components. However, there is a problem (I would call it a bug) with international characters. Even if you specify UTF-8 as the encoding of the HTML/JSP page, the partial AJAX response is always in ISO-8859-1. This can be easily verified with the Netbeans HTTP monitor: under the Session tab, the value for the javax.faces.request.charset is UTF-8 before the request, and changes to ISO-8859-1, after the request. This results in lots of questionmarks or strange symbols in the page and it actually makes it impossible to use Dynamic Faces with an internationalized application.

The solution came from Matthias Unverzagt's comment in a number of blogs/forums, such as Hong's blog. Matthias suggests that the line

context.getExternalContext().setResponseCharacterEncoding("UTF-8");

needs to be added to the com.sun.faces.extensions.avatar.lifecycle.AsyncResponse's installOnOffResponse method.

This proved quite of a challenge for me, since it required recompilation of the jsf-extensions-dynamic-faces-0.1.jar, which was a bit tricky, as this jar appeared in a number of locations on my system:

  • ~/.netbeans/6.0beta2/config/org-netbeans-modules-visualweb-complib/installed-complibs/dynamicfaces02
  • ${netbeans_installation_dir}/visualweb1/modules/ext
The jars in these directories were different. The first directory also contained a jar with the sources, but NetBeans was using the jar from the second directory for my project.

So, here are the steps I followed (with NetBeans Beta2):

  1. I extracted jsf-extensions-dynamic-faces-0.1-sources.jar, found in the first directory above.
  2. I created a new Netbeans Java project with the extracted sources.
  3. In order to compile this project a number of libraries and jars had to be added to the project's classpath:
    • libraries: JSF 1.2, Web UI Components
    • jars el-api.jar, jsp-api.jar, servlet-api.jar, shale-remoting.jar
    The first 3 jars can be found in tomcat's lib directory, while the last one is located in ~/.netbeans/6.0beta2/config/org-netbeans-modules-visualweb-complib/installed-complibs/dynamicfaces02
  4. I opened the file AsyncResponse.java file, from the com.sun.faces.extensions.avatar.lifecycle package and added the line
    context.getExternalContext().setResponseCharacterEncoding("UTF-8");
    to the installOnOfResponse method's body. It probably doesn't matter where exactly you place this line; I added it as the second line of this method, right between the other two statements of this method.
  5. I extracted the jsf-extensions-dynamic-faces-0.1.jar file from the ${netbeans_installation_dir}/visualweb1/modules/ext directory and replaced the .class files in the lifecycle subdirectory with the ones I just compiled.
  6. That's all! I then recompiled and deployed my web application (so that the patched copy of jsf-extensions-dynamic-faces-0.1.jar would be used) and I was set.

Wednesday, November 7, 2007

Turning off the system beeper

This is the magic command that turns off the system beeper:

sudo rmmod pcspkr

And just for completence, this is how to turn it on again:

sudo modprobe pcspkr

Update (Thanks to the ArsGeek site.) This only works for the current session - the beeper is only muted till the next reboot. In order to make the beeper silent for ever, you need to add the following line to the file /etc/modprobe.d/blacklist:

blacklist pcspkr

Ubuntu: Connecting to a Windows shared network drive

I got a new PC at work and I made a clean installation of Ubuntu Gutsy Gibbon 7.10, so I had to make some configuration from scratch. This is a quick note about how I connected to our file server, using samba

From the Places menu, select Connect to server. From the window that appears, select Windows share in the Type drop-down. Then provide the server's IP in the Server field and the folder's name in the Folder field and you are done.

Wednesday, October 31, 2007

Datasources, Tomcat and Netbeans

I am currently developing a JSF application using NetBeans 6.0 and Tomcat 6.0.14. When I tried to deploy the application on our production server (by just dumping the .war file in Tomcat's webapps directory, it didn't work properly. I could access the app's start page, but it failed to render the following pages.

A look in tomcat's log files revealed that there was a problem with the mysql driver.

Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

I tried to make sure that the mysql-connector jar is included in the project's imported libraries and that it can be found in META-INF/lib, but this didn't help. I later found out that in Netbeans, under Tools→Servers→Deployment there is a "Enable JDBC driver deployment option". Disabling this resulted in a replication of the problem on my development machine, even when using NetBeans. So I had to find out what it was that NetBeans was doing when this option was enabled and repeat it on the production server.

I started making a research on the net, based on the error message I was getting. The oslution proposed by most people was to place the mysql driver jar in tomcat's common/lib directory and nowhere else, but this just wouldn't do the trick for me. I also checked that the datasource's declarations in the web.xml and context.xml files were correct.

A final attempt to go through the steps to create and declare a datasource as described in tomcat's website revealed a small detail in step 1: the driver jar file needs to be placed in the $CATALINA_HOME/lib directory rather than $CATALINA_HOME/common/lib.

Still remains to check whether there is a difference in the directory structure in versions 5.5 and 6.0 of tomcat, since no common directory appears to exist in installations of tomcat 6.0.

Friday, September 21, 2007

Setting the time on linux.

For some reason I find the manpage for the date command a bit confusing. Here is how you can set the time in a linux box through the command line:

date MMDDhhmmYYYY
where MM is the month, DD the day, hh the hour, mm the minutes and YYYY the year.

The system's hardware clock can be synchronized with this time by executing the following command:

sudo hwclock --utc --systohc

Tuesday, September 4, 2007

Allowing ssh access with iptables.

This post describes how you can allow incoming ssh connections from a certain IP address, using iptables.

First of all, the current list of iptables rules can be viewed with the command
iptables --list

A new rule to allow access from the IP 100.100.100.100 can be appended to this list with the command

sudo iptables -A INPUT -p tcp -s 100.100.100.100 --dport 22 -j ACCEPT
As it can be seen from the command above, root access is required to alter the iptables.

However, in my case this didn't work, because the rule was appended to the end of the list, which means that it was preceded by a DROP rule that blocked ssh access to all IP addresses that did not explicitly have an ACCEPT rule. So, I had to add the rule further up in the list. This can be achieved with the -I switch.

sudo iptables -I INPUT 11 -p tcp -s 100.100.100.100 --dport 22 -j ACCEPT
In the example above, the rule will be added to the 11th position in the list.

Thursday, August 30, 2007

How to create a Datasource and a Connection Pool on Tomcat.

This post describes how you can setup a Connection Pool for a web application under Tomcat. I have been using NetBeans 5.5.1, with bundled Tomcat (version 5.5.17). NetBeans does offer some visual tools to create datasources and connection pools, but as far as I understand, these only work with the Sun Application Server.

Before doing anything else, the following jars are required:

  • mysql-connector-java-5.0.7-bin.jar
  • commons-dbcp-1.2.2.jar
  • commons-collections-3.2.jar
  • commons-pool-1.3.jar
The first one is the official mysql driver which can be downloaded from the mysql site. The other three are part of the Apache Commons collection.
They need to be placed in the WEB-INF/lib subdirectory of the webapp. (Of course this can also be done through the NetBeans IDE.) Actually, although I read on various websites about the last 3 jars, I am not absolutely sure if they are definitely required. Even after I removed them, my application continued to work fine.
Important: The MySQL Connector/J jar needs to be placed under the Tomcat common/lib/ subdirectory. (For the bundled with the NetBeans IDE version of Tomcat, this directory is $NETBEANS_HOME/enterprise3/apache-tomcat-5.5.17/common/lib.


1. Add this to the context.xml file (which is located in the META-INF directory of the web-app.

<Context path="/ePmashup">
  <Resource 
      name="jdbc/dataSource"
      auth="Container"
      type="javax.sql.DataSource"
      factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
      username="username"
      password="password"
      driverClassName="com.mysql.jdbc.Driver"
      url="jdbc:mysql://localhost:3306/databaseName"
      maxWait="1000"
      removeAbandoned="true"
      maxActive="30"
      maxIdle="10"
      removeAbandonedTimeout="60"
      logAbandoned="true"/>    
</Context>
The options in italics have to be substituted with the appropriate values.

2. Create a DataSource object in the application code.

Context initContext = new InitialContext();
Context envContext  = (Context)initContext.lookup("java:/comp/env");
datasource = (DataSource)envContext.lookup("jdbc/dataSource");
This snippet has to be wrapped in a try-catch block, because it might throw a NamingEsception. In my code, I placed this piece of code in the init() method of the Servlet that contacts the database and returns the results to the client.
 public void init() throws ServletException {
   super.init();
   try {
       Context initContext = new InitialContext();
       Context envContext  = (Context)initContext.lookup("java:/comp/env");
       datasource = (DataSource)envContext.lookup("jdbc/dataSource");
          
   } catch( NamingException ne ) {
     throw new RuntimeException( "Unable to aquire data source", ne );
  }
 }
Obviously, the string passed in the lookup method, needs to be the Resource name (in context.xml).

3. Now, a connection from the pool can be retrieved and used like this:

Connection conn = dataSource.getConnection();

Tuesday, July 31, 2007

Popup windows in JSF

Is is possible to raise a popup window in Java Server Faces (JSF) using Javascript, more or less the same way as in HTML.

This example shows how this can be done with a commandButton.

<h:commandButton value="Press me to bring up a popup window" onclick="window.open('popup.jsp', 'popup_window')" />

This exact method won't work with a commandLink, because this does not offer an onclick option. However the mouseup event can be used instead:

<h:commandLink onclick="window.open('popup.jsp', 'popup_window')">
    Press me to bring up a popup window
</h:commanndLink>

Of course, both commandButton and commandLink items need to be enclosed in a form element. This means that the form will be submitted when the commandButton or commandLink is pressed/clicked. In order to avoid it, we have to return false from within the onclick or mouseup attribute.

<h:commandButton value="Press me to bring up a popup window" onclick="window.open('popup.jsp', 'popup_window'); return false;" />

Wednesday, July 18, 2007

Javascript context menus

With Javascript it is possible to add a context menu to an object (ie a menu that displays on right-click). However, on Firefox, right-clicking on an object with a custom context menu will show both this menu and the normal Firefox context menu. The Firefox context menu is displayed on top of the custom menu, so in order to access the latter, you need to click somewhere else on the page, in order to access the custom menu.

This behaviour can be overridden by selecting the following options:
Edit → Preferences → Content → Advanced (next to Enable Javascript) → Disable or replace context menus.

Sunday, July 1, 2007

Ubuntu: Multisession DVDs

At the time of writing this, Gnomebaker supports writing multisession CDs, but not DVDs. This extra functionality is provided by K3b, but this is a KDE application, and installing KDE applications on a GNOME-based distribution is not always desirable.

There is however a very simple-to-use command line utility that can be used to create a multisession DVD disc, append data to it and finalize it (and the disc is fully-readable before finalization). This utility is called growisofs and its functionality can be summarized as follows:

Creating a multisession disc
growisofs -Z /dev/dvd -R -J /path/to/file1 /path/to/file2 ...

The -R and -J options define that the Rock-Ridge and Joliet extension should be used (whatever that means....). /dev/dvd should be substituted with the appropriate value for the DVD device (eg in my case it is /dev/cdrom).


Appending data to a multisession disc
growisofs -M /dev/dvd -R -J /path/to/file1 /path/to/file2 ...

The only point that needs caution here is that, when adding data to a multisession disc, you have to use exactly the same options as with when creating the disc.


Finalizing a multisession disc
growisofs -M /dev/dvd=/dev/zero

Tuesday, June 19, 2007

Ubuntu: Enabling USB audio

The other day, I managed to break my speaker jack plug and get one piece of it stuck in the soundcard's speaker output, thus rendering it useless. My efforts to get this piece out of there led nowhere, so I started thinking of other alternatives and I ended up getting a USB external soundcard.

The cheapest one I could find was this and there was no way that I would look for anything more expensive as there was the risk that it wouldn't work under linux. However the fact that the device supports MacOS-X was an encouraging fact towards portability. A quick research on the internet also revealed that (at least theoretically) all USB audio devices should work fine as they all use the USB protocol, so no special drivers are required.

Indeed enabling USB audio was very straightforward:

  1. I first opened the Sound Preferences (System→Preferences→Sound) and I selected 'USB Audio' where it was available.
  2. Then I double click on the speaker icon on the top right corner, which brings up the Volume Control window, I muted out all tracks for my old sound device and I closed this window.
  3. Finally, I right-clicked on the icon mentioned above, and I selected Preferences. Then I set the device that this icon controls to 'USB Audio', so that mouse scrolling over this icon will control the volume of the USB audio device.

This whole process was enough to get audio playback to work, but getting sound to work while playing movies required a little bit of additional effort. I actually had to manually change the output device on all video players. Here are the steps required for each one of them.

totem-gstreamer
The configuration for totem-gstreamer is handled by a utility called gstreamer-properties. On the Audio< tab, I set the plugin to 'ALSA' and the device to 'USB Audio'.

VLC player
Go to Settings → Preferences → Audio → Output Modules → ALSA and select USB audio: USB audio (hw:1,0) as the device name. Hitting the Refresh button might be required for this option to appear.
This whole process is important because it reveals to us the actual name for the USB audio device (hw:1,0).

mplayer
Preferences → Audio → ALSA → Configure driver
and set the Device to 'hw=1,0'.

xine
First we need to enable advanced configuration options:
Settings → Setup → GUI Configuration Experience Level
and set it to 'Master of the Universe'.
Then, in order to specify the output device, select the Audio tab and set 'hw=1,0' as the value for the fields Device used for mono/stereo... output.

The only thing I still haven't got to work is the Fn+↑ and Fn+↓ combinations, which really bothers me, since this was the main method I used to control the volume.

Update 1:
Actually these combinations suddenly started working, but I can't remember doing something that I hadn't tried before... I believe the important part is to have the correct device selected in the "Select the device and tracks to control with the keyboard" field under the Sound Preferences window, but as it can be seen in the first screenshot, I had the correct option selected right from the beginning.

Update 2:
Another problem that I forgot to mention in the main article, was that I didn't have sound in Flash, which meant that I couldn't use YouTube and all other video sites. I had tried to solve this problem quite a few times before, but I only succeeded today. The only thing I did was to check that the correct device is selected in gstreamer-properties (which I am not absolutely sure if it plays a role after all) and just re-install the Flash plugin.

Sunday, June 17, 2007

Ubuntu: Hot to add subtitles to an AVI file.

All major Linux media players (Totem, mplayer, VLC player) allow you to add subtitles to a movie while watching it. This post describes how you can permanently add the subtitles in an AVI file, which is useful if you want to burn the movie to a video DVD. (Notice however that this technique does not allow you to add more than one subtitle streams to the movie, or disable the subtitles while watching the movie; the subtitles are hard-wired to the movie).

The software package we are going to use is called avidemux and it can be easily installed through aptitude if the universe/multiverse packages are enabled.

The procedure required to add the subtitles is this:

  1. Launch avidemux.
  2. Open the .avi file. With all files I have tried so far, I get these warnings:
    It is best to let avidemux do what it wants to do - it only takes a few seconds.
  3. Select a video encoder from the pull-down menu on the left pane, where it says Video. I believe this can be anything, but it is preferable to choose the same encoder as the one used in the original movie. I normally use Xvid4 and it works just fine.
  4. Configure the encoder by clicking the "Configure" button. In my opinion, no configuration is actually require in order to get an acceptable result. Even one-pass encoding works fine. The only thing that you might want to adjust is the size of the output file.
  5. Add a subtitler filter. First click on the "Filters" button in the left pane (under Video). This brings up the following window:
    Select Subtitles→Subtitler. You can now configure your subtitles using the window shown in the image below.
    This window allows you to select the subtitles file, the encoding (it supports UTF-8, so it works fine with non-latin alphabets), and the font, color, size and position of the subtitles.
  6. It appears that there is no need to select an audio encoder; "COPY" works just fine (since we do not wish to make any changes to the sound). Make sure that the "Format" is set to "AVI". The result can be previewed by clicking on the far right icon and then pressing play.
  7. To finalize the process, click Save and type in a name for the output file. Note that the whole process can take a while. For example in my laptop it took maybe more than an hour to encode a 40min movie file, at an average speed of 16FPS (while doing other stuff as well).

Monday, June 11, 2007

Deploying web applications that use different Java versions.

If you have a Tomcat installation that uses, say, Java 1.4.2, you can only deploy web application that are built with Java <= 1.4.2. If you need to run a Java 5.0 web application, you need to set tomcat to use JRE 5.0 (by setting the JAVA_HOME or JRE_HOME enviroment variables), but this might possibly break older applications that use Java 1.4.2.

Most probably, you'll need to have a separate installation of tomcat, that will use Java 5.0. It is possible to have two or more instances of tomcat running, and these can be either the same version or different versions. However, the two instances need to listen to different ports. The server port is specified in file $CATALINA_HOME/conf/server.xml. I noticed however that in order to get it to work, we need to change all the ports and not just the server port.



This needs cleanup/rewritting

Tuesday, June 5, 2007

Javascript: Button redirect

An eas way to redirect to another page (in the same window) is through the parent.location Javascript variable.
<INPUT TYPE="button" onClick="parent.location='url'">
The URL can be either relative or absolute.
Note: Credit to this site: http://winfolinx.com/tips/howto/redirect/redirbut.htm

Thursday, May 31, 2007

Disk usage in linux

A quick summary of the used/available space for each partition of the system can be retrieved with the df command:

apapad@Zzzzz:~> df
Filesystem      1K-blocks      Used Available Use% Mounted on
/dev/hda7        15172120   4803284   9598120  34% /
varrun             517208        88    517120   1% /var/run
varlock            517208         0    517208   0% /var/lock
procbususb         517208       120    517088   1% /proc/bus/usb
udev               517208       120    517088   1% /dev
devshm             517208         0    517208   0% /dev/shm
/dev/hda8        12507868   9081380   2791120  77% /home
/dev/hda2        28653984  23529856   5124128  83% /media/windows/D
/dev/hdc          4338192   4338192         0 100% /media/cdrom0
A more comprehensive view can be obtained by using the -h switch (which stands for human readable).
apapad@Zzzzz:~> df -h
Filesystem         Size  Used Avail Use% Mounted on
/dev/hda7           15G  4.6G  9.2G  34% /
varrun             506M   88K  505M   1% /var/run
varlock            506M     0  506M   0% /var/lock
procbususb         506M  120K  505M   1% /proc/bus/usb
udev               506M  120K  505M   1% /dev
devshm             506M     0  506M   0% /dev/shm
/dev/hda8           12G  8.7G  2.7G  77% /home
/dev/hda2           28G   23G  4.9G  83% /media/windows/D
/dev/hdc           4.2G  4.2G     0 100% /media/cdrom0

This still doesn't give enough information. We might wish to know which folders are taking up the most space. This can be done with the du command:

apapad@Zzzzz:~> du -sk /home/apapad/* | sort -rn
2260396 /home/apapad/Desktop
1413532 /home/apapad/torrent
106832  /home/apapad/iexplore
10288   /home/apapad/workspace
6532    /home/apapad/mypics
6300    /home/apapad/mydocs
2236    /home/apapad/bin
880     /home/apapad/archive
428     /home/apapad/wireless
304     /home/apapad/resume
80      /home/apapad/gl2gr
12      /home/apapad/games
8       /home/apapad/dvdrip-data
4       /home/apapad/wine-src
4       /home/apapad/downloads
0       /home/apapad/Examples

The -k option tells du to use 1K-blocks. (Actually this is the default value, so it is not really required). The -s option gives a total for each directory. Piping the output of du to sort gives a nice result: -n tells sort that it should sort numbers rather than strings and -n returns the results in reverse order.

du also has a -h option for human readable results, but this wouldn't work well with sort...

Friday, May 25, 2007

mysql and external files

A mysql database can be dumped to a file with the mysqldump command.

mysqldump -uusername -ppassword database_name > file.sql
This is particularly useful for backup purposes. The dumped database can then be reloaded with this command:
mysql -uusername -ppassword database_name < file.sql
These two commands can be combined in order to replicate a database to a remote mysql server.
mysqldump -ulocal_username -plocal_password local_database_name | mysql -uremote_username -premote_password remote_database_name

If only some of the database tables need to be dumped, the --tables option can be used.

mysqldump -uusername -ppassword database_name --tables table1 table2 > file.sql

This, however, dumps not only the table data, but also the table creation commands and other information. If we just need to write a table into a CSV file or read table data from a CSV file, we can use the SELECT ... INTO OUTFILE and LOAD DATA INFILE commands.

SELECT columns into outfile 'file_name' FIELD TERMINATED BY 'char' FROM table_name; LOAD DATA INFILE 'file_name' INTO TABLE table_name FIELD TERMINATED BY 'char';
Note that the file name should be placed in quotes and it is preferable to use absolute paths, otherwise mysql will look for the file in the mysql directory (eg /var/lib/mysql/database_name). There is also a nasty complication in this point with the permissions that I haven't figured out yet.

Other interesting options for these two commands are
FIELDS TERMINATED BY 'char' OPTIONALLY ENCLOSED BY 'char'
and
LINES TERMINATED BY 'char'.

The full documentation can be found here.


Thursday, May 24, 2007

JSP: Setting and accessing variables

A new variable can be declared in JSP with the <c:set&ht; tag. Example:
<c:set var="variable_name" value="value" scope="page|session|request|application">

As the example above indicates, we can select among the four available scopes:

  • page
  • request
  • session
  • application

The variable can be printed out with the <c:out> tag. It can be accessed in EL (expression language) with the following syntax:

${pageScope.variable_name}
${requestScope.variable_name}
${sessiomScope.variable_name}
${applicationScope.variable_name}
and from within a scriptlet as follows:
<%= pageContext.getAttribute(variable_name) %>
<%= request.getAttribute(variable_name) %>
<%= session.getAttribute(variable_name) %>
<%= application.getAttribute(variable_name) %>

Wednesday, May 23, 2007

A nice-looking font for Ubuntu

I have been looking for a nice font to use as the standard 'application font' in Ubuntu for quite a long time, and finally I found a great one, thanks to this blog.

I only tried the first font-family the author suggests, called Gentium, and since this looks great on my screen (much better than the default Serif/SansSerif fonts I had been using till now), I didn't look any further. One very positive feature of the Gentium fonts for me was the support for Greek characters.

The font can be installed with the command:

sudo aptitude install ttf-gentium

Wednesday, May 16, 2007

HTML/JSP: How to pass the '#' character as an HTML request parameter

I found myself into a situation today, where I was trying to pass a string (actually a URI) as a request parameter through a URL, but my program wouldn't work. I added debug print statements and found out that although I was passing the string
http://localhost/life_event.owl#Document
the page that was processing the request only received
http://localhost/life_event.owl
It immediately became apparent that the problem was caused by the hash/pound symbol ('#'), which is used as a special character in URLs to introduce a "fragment identifier". A URL link containing a fragment identifier links to a specific section of a webpage and a browser that follows this link will set its viewport on this exact section rather than the top of the page. Escaping this character is rather easy: you just need to replace '#' with '%23'. In my case I was using JSP with JSTL, and this string was returned as a bean property (for those who are curious it is the URI for an OWL ontology resource). This substitution can be performed by using the fn:replace function:
<a href="${fn:replace(original_string,'#','%23')}">Text here</a>
I noticed that it is not necessary to "decode" the '%23' escaped character back to '#' on the request-handler side, but I am not sure if this is specific to JSP only.
Of course, in order for all this to work, you need to import the fn tag library.
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

Saturday, May 12, 2007

Ubuntu: Setting the Win+D combination to bring up the desktop.

One of the most useful keyboard shortcuts that are set-up by default on Windows (although not widely known), is the Win+D combination, which minimizes all windows and displays the desktop. Ubuntu has this little icon on the bottom-left corner, but that was not enough for me...
This shortcut can be configured to work in Ubuntu in exactly the same way as with Windows, by following these steps:

  1. First we need to make sure the Win key is mapped to 'Super'.
    System &rarr Preferences &rarr Keyboard &rarr Layout Options &rarr Alt/Win Key behaviour &rarr Super is mapped to the Win keys.

  2. Set the Win+D combination to do what we want:
    System &rarr Preferences &rarr Keyboard shortcuts &rarr Hide all windows and focus desktop (which can be found under the category 'Window management').

Friday, May 11, 2007

Linux: The replace command

The linux replace utility is a very useful command for performing string substitutions, which I find much easier to use than sed. It has a much simpler syntax, performs the substitution in place (unlike sed which leaves the input file intact) and allows you to carry out multiple string substitutions in a series of files at once.

The basic syntax for the command is:
replace from to [from to] ... -- file [file] ...
The man page can be found here, although the usage is very simple. You first specify an arbitrary number of from-to string pairs. These strings can be placed in quotes if they contain spaces and other special characters. I am not sure at the moment if replace supports regular expression (of which I am not a really big fan, so I don't really mind :P). The '--' delimiter signals the end of the list of substitution pairs and is followed by the list of files that will be edited.

Example:
replace foo bar one two -- index.html
This command will replace all occurrences of "foo" in file index.html with "bar" and all occurrences of "one" with "two".
The replace command returns a notification on which files were actually converted. It does not report how many changes were made to each file or anything more detailed, but still the piece of information it does return is quite useful.

One disadvantage I find in replace is that it doesn't have an option to recursively access and edit files. One workaround is to feed it with the output of a grep -l command, eg.
replace foo bar -- `grep -l foo *`

Unfortunately, the replace utility is not usually installed by default on linux systems; it was designed to be used by the msql2mysql utility, therefore it is installed only when mysql is installed.