java / my projects / photo / swing / ui — No comments
22
Jun 09
This weekend the weather was not that great so I spent it at home. Also my laptop almost run out of disk space, so I decided to do something about it. I had 50 Gb of photos in my Picasa albums (it’s because I mostly shoot RAW, I guess) which I always wanted to archive on an external drive keeping only the starred photos on the laptop, so that I can always have the best photos with me. But there is no easy way to do it in Picasa. Well, of course you can do it manually, but in my case it was not an option, because I had so many photos on my laptop.
Just improving the python script which I had been using for few years for backing up Picasa albums would not be an option, because this new tool would need a UI. The user needs first to have an overview over the albums and the disk space they consume, and then decide which one to archive.
So I decided to make a tool which would help me with it. On Saturday evening I started to code and have fun with the good old Swing, and finished it late on Sunday. And then the tool helped me to remove tens of thousands of non-starred photos which I didn’t want to have on my laptop (after backing them up) and free precious gigabytes just in few minutes.
Here it is: Picback. If you are an extensive Picasa user and photographer, I hope it can be useful for you too.

shell — No comments
19
Jun 09
If you use Subclipse, switching to another repository in a local working copy can be pain in the ass, because Subclipse (and I think svn itself) only allows to change the path of the repository if it’s still in the same repository. I had to change the path from http://.. to https://.. and couldn’t do it in Eclipse. Subclipse reported an error: “https://.. is not the same repository as http://.. “. As a last resort I decided to manually update the repository in all of the svn’s entries files using the magic xargs command. Running this command in the project root directory did the trick (works with Cygwin on Windows as well):
find . -name entries | xargs sed -i "s/http:\/\//https:\/\//g"
javascript / visualization / web — No comments
19
Mar 09
John Resig released a port of the Processing language to JavaScript. The demos are very inspiring.

db / debugging / java / web — No comments
17
Feb 09
After 8 months of development of a new project with extensive use of Hibernate I can now tell about my experiences with it. In general, Hibernate is a very useful tool. It saves a lot of time, because you don’t have to write SQL queries. If you make changes, you usually don’t have to rewrite queries, because there are only a few of them. The configuration using annotations is simple and powerful (and I personally prefer it to writing mappings in XML). Hibernate is able to generate database tables from mapped classes automatically and even update them as you add new fields to a class. Hibernate caching facilities are very useful. Finally, Hibernate allows to develop database vendor indepentent applications.
But there are few problems which I experienced:
- The most frustrating is in fact described in the Hibernate docs. An object returned by session.load() isn’t necessarily an object of the expected class:
Cat cat = (Cat) session.load(Cat.class, id); // instantiate a proxy (does not hit the db)
if (cat.isDomesticCat()) { // hit the db to initialize the proxy
DomesticCat dc = (DomesticCat) cat; // Error!
....
}
- No inheritance mapping for value objects: here is the JIRA issue that never gets fixed, and a workaround.
- The strong suggestion in the Hibernate documentation to use a join table for every unidirectional one-to-many association (in the section 2.2.5.3.2.2. “Unidirectional”). Another suggestion is discussed here.
- 2nd level caching should be used with caution: after deleting an object the stale version can still stay in cache which can lead to an ObjectNotFoundException. I found no other solution except disabling the 2nd level cache for the class.
java / my projects / piccolo / swing / ui / visualization — No comments
17
Sep 08
The CGVis project, our visualization tool for multidimensional data, is finally open-sourced. Hurrrah!

python / web — No comments
12
May 08
At the Grazer Linuxtage I liked most the Armin Ronacher’s talk about Werkzeug which is a Python library for building web applications that doesn’t limit you in the way you build your web app (like many of the existing frameworks do). Werkzeug is rather a handy set of tools and utilities for making web apps than a framework.
The most impressive part of the talk was when Armin demonstrated the “online” debugging feature on a standard error page generated by Werkzeug. Upon each error the context in which it happens is stored on the server (only if the app is in the debug mode). Thus on the error page itself you can directly interact with the Python interpreter which is “frozen” in the very state in which the error happened. So you can use the full power of the interactive Python interpreter directly on the standard error page. That’s awesome.
shell — No comments
21
Apr 08
I didn’t know that it’s so simple to make directory aliases on Windows 2000+. There is an undocumented utility for it: linkd.exe (part of Windows Server Resource Kit), which is roughly equivalent to ln -d in UNIX. So you can write:
LINKD Docs C:\Documents and Settings\Ilya\My Documents
And voila! You have now C:\Docs which links to My Documents.
More here
java / web — 5 comments
21
Nov 07
If you need to render a tree-like structure here’s a way of implementing recursion in JSP/JSTL:
${node.title}
<div class="children">
<c:foreach var="node" items="${node.children}">
<c:set var="node" value="${node}" scope="request"/>
<jsp:include page="node.jsp"/>
</c:foreach>
</div>
The tricky thing is that when you use jsp:include (and for recursion you have to use the dynamic inclusion), normally, you loose all the variables defined in the parent JSP. But if you redefine the variables you need in the “request” scope, then they will be visible in the included JSP too. I assumed that this very JSP is named “node.jsp” and omitted the declarations. Surprisingly, I found neither this nor any other solution on the Web, so I had to invent one.
perl / web — No comments
05
Nov 07
I needed to write a script which runs on the server, gets daily statistics from our rolling log files and sends them by email. The log is splitted into 64Mb files and the total size is limited by 1GB. I didn’t want to parse the whole gigabyte of logs, so I decided to start from the most recent file and read it in the backward order till the previous date. I found two approaches to read file backwards with perl. The first approach is slower but requires a fixed amount of memory (in my case about 2 mins and up to 16Mb RAM):
tie(@lines, "Tie::File", $fname, mode => 0) or die "Can't tie $fname: $!";
$max_lines = $#lines;
for ($i = $max_lines; $i; $i--) {
if (not &$apply($lines[$i])) {
return 0;
}
}
The second approach is faster but requires at least as much available memory as the size of the log file, in fact more than twice as much when processing several files one by one (in my case, 1:02 min and up to 150Mb RAM):
open(LOG, $fname) or die "Can't open $fname: $!";;
@lines = reverse <LOG>;
foreach $line (@lines) {
chomp $line;
if (not &$apply($line)) {
close(LOG);
return 0;
}
}
close(LOG);
So I chose the first approach, because I thought that stable memory footprint on the server is more important than the time the script takes to complete. Here is the full code for the package I wrote that provides handy functions for scanning rolling logfiles forwards and backwards: logscan_pl.txt
And here is a usage sample:
require 'logscan.pl';
$errors = 0;
logscan::scan("Joanna", sub {
$_ = shift;
if (/(.*) INFO.*Returning error by [([^]]*)].*user=[([^]]*)].*roles=[([^]]*)]/) {
my ($time, $uri, $user, $role) = ($1, $2, $3);
$errors++;
print "$time $uri $user $rolen";
}
return 1;
});
print "\\n\\nTotal errors: $errors\\n";
java / spring — No comments
15
Sep 07
If you make a web application that supports several languages with Spring you are definitely familiar with the handy locale resolvers Spring provides. Unfortunately, none of them allows to restrict the number of locales that can be set. We needed such restriction, because some of our database queries depended on the locale. So I wrote a wrapper locale resolver for it:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.LocaleResolver;
/**
* A wrapper for LocaleResolver. Allows to set only one of the predefined set of locales.
*
* @author Ilya Boyandin
*/
public class RestrictiveLocaleResolver implements LocaleResolver {
private final LocaleResolver localeResolver;
private final Locale defaultLocale;
private final List<Locale> supportedLocales;
private RestrictiveLocaleResolver(
LocaleResolver localeResolver, Locale defaultLocale,
Collection<String> supportedLocales) {
this.localeResolver = localeResolver;
this.defaultLocale = defaultLocale;
final List<Locale> locales = new ArrayList<Locale>();
for (String loc : supportedLocales) {
locales.add(new Locale(loc));
}
this.supportedLocales = locales;
}
public LocaleResolver getLocaleResolver() {
return localeResolver;
}
public Locale getDefaultLocale() {
return defaultLocale;
}
public Collection<Locale> getSupportedLocales() {
return Collections.unmodifiableCollection(supportedLocales);
}
@Override
public Locale resolveLocale(HttpServletRequest request) {
final Locale resolved = localeResolver.resolveLocale(request);
final Locale supported = findSupportedLocale(resolved); // this ensures that a locale with one
// of the predefined names will be used
if (supported != null) {
return supported;
} else {
return defaultLocale;
}
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
final Locale supported = findSupportedLocale(locale); // this ensures that a locale with one
// of the predefined names will be used
if (supported != null) {
localeResolver.setLocale(request, response, supported);
} else {
localeResolver.setLocale(request, response, defaultLocale);
}
}
private Locale findSupportedLocale(Locale locale) {
for (int i = 0, len = supportedLocales.size(); i < len; i++) {
final Locale loc = supportedLocales.get(i);
if (loc.equals(locale)) return loc;
}
return null;
}
}
And then you must have something like this in your config file (of course, you can use any other locale resolver instead of SessionLocaleResolver here):
<bean id="localeResolver" class="org.fhj.joanna.web.utils.RestrictiveLocaleResolver">
<constructor-arg><bean class="org.springframework.web.servlet.i18n.SessionLocaleResolver"/></constructor-arg>
<constructor-arg value="de"/>
<constructor-arg><set><value>de</value><value>en</value></set></constructor-arg>
</bean>