CGVis is available under GPL
The CGVis project, our visualization tool for multidimensional data, is finally open-sourced. Hurrrah!
The CGVis project, our visualization tool for multidimensional data, is finally open-sourced. Hurrrah!
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.
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.
If you need to render a tree-like structure here’s a way of implementing recursion in JSP/JSTL:
${node.title}
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 in the Web, so I had to invent one.
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";
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>
Few days ago we found out that passing in SQL parameters to a PreparedStatement can affect query optimization when we ran into a problem querying the database from our web app. We constantly got the following error from SQL Server: Adding a value to a ‘datetime’ column caused overflow. In the WHERE clause of the query we had something like DATEADD(month, 2, exam_date) and it went wrong, because there was an invalid exam_date entry in the database table (something like 0095-01-10).
The funny thing is that when we tried to run the very same query in Microsoft Query Analyzer it worked without an error. Then I wrote a short test that queried the database directly using PreparedStatement without Spring and iBatis to localize the problem and found out that when I passed parameters to it the error came, when I put the parameter values into the query itself it didn’t. So it seems that passing the parameters affected the order in which the conditions in the WHERE clause were evaluated: without the parameters another condition was evaluated first so that the errorneous date entry was filtered out before coming to the condition which used DATEADD.