Due to my recent suspicion that there is a bug in Drools I needed to monitor its guts in detail. To be more specific, I needed to see what is in the working memory after execution of all rules.
Debbuger was not a good option since there were hundruds of invocations of the problematic part and I needed to get overview of quite a large amount of data. If I inly could store all the data for each invocation in a file and then grep through it.
But wait! Of course I can. Byteman will help me! The identified point in source code was execution of fireAllRules() in org.drools.common.AbstractWorkingMemory. Ideally, just before return from the method. So here is the corresponding rule:
RULE Debug fireAllRules HELPER org.drools.planner.examples.tournaments.helper.BytemanHelper CLASS ^org.drools.common.AbstractWorkingMemory METHOD fireAllRules AT EXIT IF TRUE DO printWorkingMemory($0.getKnowledgeRuntime()); ENDRULE
Just a few notes to it:
- ^ means to apply to child classes as well
- $0 refers to this
As you can see there is a custom helper class to print the working memory content since Byteman rules are little bit limited in the supported Java syntax.
import org.drools.impl.StatefulKnowledgeSessionImpl;
import org.jboss.byteman.rule.Rule;
import org.jboss.byteman.rule.helper.Helper;
public class BytemanHelper extends Helper {
protected BytemanHelper(Rule rule) {
super(rule);
}
public void printWorkingMemory(Object obj) {
StatefulKnowledgeSessionImpl session = (StatefulKnowledgeSessionImpl) obj;
debug("vvvvvvvvvvvvvvvvvvvvvvvvvvv");
debug(session.toString());
for (Object o: session.getObjects()) {
debug(o.toString());
}
debug("^^^^^^^^^^^^^^^^^^^^^^^^^^^");
}
}
And now I was able to get some nice output of individual working memories! So the resulting bug is JBRULES-3337.
I'm a Linux user (distribution-agnostic) so I have to bolt my seat down in the airplane but once done, it is really comfortable. The same thing applies to Gimp. Today I spent some time with it on a fresh installation and found out all the good plugins I ever used. The important point here is that there are only three of them to do what I really need. And, of course, all of this can be done manually in a clean Gimp installation but it might take ages.
Contrast Blending aka HDR Photography
High dynamic range imaging is a set of techniques that allow displaying images with big differences between dark and light parts on a limited device. A limited device is a usual computer screen or a printed image. None of these media can fully display the range that a human eye is able to see. So we need to make a compromise in the scene.
There is a great Gimp plugin and tutorial for HDR blenging. The basic principle is to take three pictures with different exposure values (dark, normal and bright) and mix them together. A good algorithm can do that pretty easily for you. A sample picture can be seen below. In the left upper corner, there is the dark exposure. In the upper right corner, there is the normal exposure, the bright exposure is placed at lower left, and, eventually, the result image is at lower right. Note that you can see the background, while there is the candle wick still visible below the light.
Layer Effects
In Photoshop, layer effects are built-in. These effects can do some easy manipulation with the image and is one the most criticised lacks of Gimp. Fortunately, there is a plugin that can be easily installed and works pretty much the same way.
Shadows and Highlights
This plugin allows you to manipulate dark and light parts of the scene. It can automatically extract these parts into new layers and by using the layer opacity you can configure the light in shadows and darken the bright parts.
This is not such a miracle, but it is very useful in infrared (IR) photography.
IR Photography
The biggest issue with IR photography is that usual DSLR cameras have a fixed built-in IR filter before the image chip. This is to avoid unwanted light. But for IR photos we want it! The solution (except for camera disassembly or buying Sigma SD14 with removable filter) is to increase exposure period. It can take several minutes to get enough light with an IR filter on your lens.
Now, when we have a photo, how to process the red scene we obtained? There is a great Photoshop IR tutorial. But I wanted to do that in Gimp. There is a tutorial in a forum that resembles the Photoshop procedure. To summarize that:
- Realize what is in individual color channels - red is brightness, green is sharpness, blue is noise.
- In Gimp go to Colors, Levels and try Automatic or set a reference white point (which is something that produces most IR light - a green leaf on a sun for instance). You can also setup individual channels as you like.
- In Gimp select Colors, Components, Channel mixer and switch the red and the blue channels. This is done by setting 100% for blue and 0% for red with the red input channel and vice versa for the blue input channel.
- Now is the best time for the Shadows and Highlights plugin.
- Finally, you can try Colors, Hue/Saturation and add a little bit of Hue (+15 - +24) and possibly add some Saturation as well.
- Bonus step is to open Colors, Curves or Colors, Levels and fine tune the image colors.
Connecting to an ODBC database from Java can be a real nightmare. Most solutions suggest using a JDBC-ODBC bridge. So what are real possibilities here? Native JDBC-ODBC bridge by Sun/Oracle sun.jdbc.odbc.JdbcOdbcDriver. Well, there are some limitations like the number of concurrent connections and poor performance. I was not able to find any free (ideally open source) JDBC-ODBC bridge. There are multiple vendors but only one seems to have a de facto standard - Easysoft. They provide trial version of their bridge so you can try the solution before you buy it. Here we realized some troubles in Java Virtual Machine consuming too much memory. I do not want to blame the bridge. It was on a separate machine but we are not able to debug it and see how it works. So not being opensource killed Easysoft's chance to get a new customer.
After all I decided to write a small Java client that would be able to access an ODBC database. We needed just some basic querying capabilities anyway. But this is a little tricky, there is no ODBC communication protocol specification. Eventually, I decided to use unixODBC library using JNI. And here is beginning of the story.
First I designed a client for accessing the database. I had some previous ODBC API knowledge so I designed the client in order to write minimum code in C.
A design note: I failed passing database handles (type void*) between C and Java, so I created an array to store real handles in the C library and pass just an index to the array. This requires tha Java part to remember which handles have been used. There definitely exist a more sophisticated solution but I wanted to query an ODBC database at first. Also note that all data are returned as Strings for simplicity. There is also a shor main() method to test the client.
package org.marvec.odbc;
public class OdbcClient {
private static SortedSet usedHandles = new TreeSet();
private int handle;
public native void connect(String connection) throws IOException;
public native void execute(String statement) throws IOException;
public native int getNumCols();
public native ColumnMetadata getColMetadata(int col);
public native boolean fetch();
public native String getColData(int col) throws IOException;
public native void freeStatement();
private native void close();
public OdbcClient() throws IOException {
int i = 0;
while (usedHandles.contains(i) && i <= 1024) {
i++;
}
if (i == 1024) {
throw new IOException("All handles are currently in use. Try to free some handles by disconnecting from ODBC.");
}
usedHandles.add(i);
handle = i;
}
public void disconnect() {
close();
usedHandles.remove(handle);
}
public static class ColumnMetadata {
public String name;
public int type;
public long length;
public int digits;
this.nullable = nullable;
public String toString() {
return name + ": " + type + "(" + length + ")" + "[" + digits + "]" + (nullable ? "*" : "");
}
}
public static void main(String... args) throws Exception {
System.loadLibrary(args[0]);
OdbcClient c = new OdbcClient();
c.connect("DRIVER={PostgreSQL64};DATABASE=myodbcdb;SERVER=localhost;PORT=35432;Uid=admin;Pwd=admin;");
c.execute("select * from persons where person_id < 1000");
System.out.println("Columns: " + c.getNumCols());
for (int i = 1, j = c.getNumCols(); i <= j; i++) {
ColumnMetadata meta = c.getColMetadata(i);
System.out.println("Column " + i + ": " + meta);
}
while (c.fetch()) {
for (int i = 1, j = c.getNumCols(); i <= j; i++) {
System.out.print(c.getColData(i) + (i == j ? "\n" : ", "));
}
}
c.freeStatement();
c.disconnect();
}
}
After compilation, I neede javah utility to obtain a C header file (.h).
javah -jni org.marvec.odbc.OdbcClient
Now the hard C part begins. I'm not a C guru and my compiler reports many warnings about my code. However, it compiles and works. First I copied org_marvec_odbc_OdbcClient.h to org_marvec_odbc_OdbcClient.c and added the shared handle storage to the header file as well as necessary includes. As you can see, we need to remember three different handles for each connection.
#include#include ... SQLHENV env[1024]; SQLHDBC dbc[1024]; SQLHSTMT stmt[1024];
You might find me wasting some memory but you know, in Java world, there is always enough memory... I will show you only some parts of the solution, link to a complete package is at the end of this post. The most difficult function is getting column metadata that requires creating a new Java object from C.
JNIEXPORT jobject JNICALL Java_org_marvec_odbc_OdbcClient_getColMetadata(JNIEnv *jnienv, jobject obj, jint col) {
int h = getStaticHandle(jnienv, obj);
SQLSMALLINT nameLength, dataType, decimalDigits, nullable;
SQLULEN colSize;
jstring jstr;
char name[512];
SQLDescribeCol(stmt[h], (SQLUSMALLINT) col, name, sizeof(name), &nameLength, &dataType, &colSize, &decimalDigits, &nullable);
jstr = (*jnienv)->NewStringUTF(jnienv, name);
jclass clazz;
jmethodID cid;
jobject meta;
clazz = (*jnienv)->FindClass(jnienv, "org/marvec/odbc/OdbcClient$ColumnMetadata");
cid = (*jnienv)->GetMethodID(jnienv, clazz, "", "(Ljava/lang/String;IJIZ)V");
meta = (*jnienv)->NewObject(jnienv, clazz, cid, jstr, dataType, colSize, decimalDigits, (jboolean) (nullable == SQL_NULLABLE));
return meta;
}
In some problematic methods I also check for errors using another utility library I mostly copied from Jinput project (see function throwIOException() for example).
JNIEXPORT void JNICALL Java_org_marvec_odbc_OdbcClient_connect(JNIEnv *jnienv, jobject obj, jstring conn) {
SQLRETURN ret;
jbyte *str;
int h = getStaticHandle(jnienv, obj);
char error[10240];
jclass cls = (*jnienv)->GetObjectClass(jnienv, obj);
str = (*jnienv)->GetStringUTFChars(jnienv, conn, NULL);
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(env[h]));
SQLSetEnvAttr(env[h], SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
SQLAllocHandle(SQL_HANDLE_DBC, env[h], &(dbc[h]));
ret = SQLDriverConnect(dbc[h], NULL, str, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
if (!SQL_SUCCEEDED(ret)) {
extractError(dbc[h], SQL_HANDLE_DBC, error, sizeof(error));
throwIOException(jnienv, "SQLDriverConnect failed with return value %d:\n%s", ret, error);
}
(*jnienv)->ReleaseStringUTFChars(jnienv, conn, str);
}
Now there are some dependencies in the C project. You must have installed the following libraries in your system:
- unixODBC
- unixODBC-dev
- some ODBC driver for your target database like odbc-postgresql
- libltdl
- and some common C libraries that are likely to be already present on your computer: pthread, dl
Now you must configure ODBC to provide you the driver (see the first part of the connection string DRIVER=). This is done in /etc/odbcinst.ini and we can configure both 32- and 64-bit versions:
[PostgreSQL] Description = PostgreSQL driver for Linux & Win32 Driver = /usr/lib/odbc/psqlodbca.so Setup = /usr/lib/odbc/libodbcpsqlS.so [PostgreSQL64] Description = PostgreSQL driver for Linux & Win32 Driver = /usr/lib64/odbc/psqlodbca.so Setup = /usr/lib64/odbc/libodbcpsqlS.so
To compile the C library I created a small Makefile:
CC=gcc
CFLAGS=-shared -fPIC -w -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux
PROJECT=org_marvec_odbc_OdbcClient
all: $(PROJECT).so
$(PROJECT).so: $(PROJECT).c
$(CC) $(CFLAGS) util.c $(PROJECT).c -o $(PROJECT).so -lodbc -lpthread -lltdl -ldl
ln -sf $(PROJECT).so libjavaODBC.so
clean:
rm $(PROJECT).so libjavaODBC.so
Note the creation of a symbolic link. Java loads libraries on library path with standard name lib[name fo the library].so and only the library name is what you pass as an argument to System.loadLibrary().
Now to run the client just call:
java -Djava.library.path=. org.marvec.odbc.OdbcClient javaODBC
Feel free to download the complete source code at github. The code is provided as is, I do not take any responsibility for any damage it might cause to anybody or anything (including hardware, software, people, animals, etc). For instructions see JBoss Community document.
Because of some obvious reasons, security is a must when it comes to computers nowadays. I am not much into security but I had to deal with it anyway. Last couple of days I worked with signed JAR files, when my Java compiler suddenly said: "Invalid signature file digest for Manifest main attributes".
It was because some JAR files were not signed correctly since I needed to remove signatures and my automated tool for signatures removal was broken. Fine, but which files are in a bad condition? I was not able to make my compiler tell me. My class path was like 10kB of text and the day was almost over...
Signatures and certificates in a JAR file are in the META-INF directory. These are files with .SF, .DSA, and .RSA extensions. All one need to do to "unsign" a JAR file is to delete those files. Note that, some information are in MANIFEST.MF as well but it is not necessary to remove them until you want to sign the JAR file again.
It is pretty straight forward so what can be wrong? It was my bad, I assumed that all JAR files in my application use the same certificate file. I did not delete all .RSA files but just something like PRODUCT.RSA.
But it took me a while to realize what is wrong. And here is a command that can help you to recognize a broken JAR file:
find -name *.jar -exec echo {} \; -exec jarsigner -verify {} \;
It is definitely a pity that Java compiler (Sun JDK 1.6) does not print out the problematic file name.
My daddy told me, son, always try to avoid working with tools that have a helve. I succeeded, I would say. I do not have to work with such tools. At least not at a daily basis. I work as a software engineer. I work mainly with intellectual property. But sometimes I feel like I am working just because of those tools.
Just imagine your only job was to make a better hammer. I believed that a hammer proved to be optimal over the years. It is a mean of achieving a more complicated result. But all those software engineers working on operating systems or application middleware try to enhance tools for computer users or application developers all day long.
The software engineers use another tools to make tools for you. Those another tools like compiler must have been developed by another engineers. But this is not what I wanted to talk about...
The software engineers tend to think too much about their tools. It is good to know your tool, of course. But it should not be recognizable which tool you used. Usually, you cannot recognize a 9mm chisel trace on a sculpture. You should not design according to the tools you plan to use.
I keep asking myself how difficult is to master a programming language. Is it that easy? Is it just a syntax sugar you need to know? Let's take Java as an example. There are too many pitfalls you must know to understand complicated code clearly - thread local variables, dynamic proxy, anonymous inner classes. You can make sure that you do not know the language perfectly, just google sample questions for the Sun Certified Java Programmer exam.
I started programming in Java around 2001. I was able to develop my applications easily without studying many guides. I did not know almost nothing but the language grammar. Now, almost 10 years later, I feel like I know intuitively 95% of the language (some percents were gained very very hard).
And what now? After all, Java is just a tool. Like a software engineer's hammer. It is definitely less than 1% of my knowledge needed to do my job correctly. So big on one side and so small on the other side. What is the right side?
My biggest dilemma is whether I should ask for language specific details when having an interview with a possible new employee at my company. Or should I ask more sophisticated questions? "What are basic properties of each transaction?" or "What is an application server?". And what about assembler? Everything that works need assembler!
What makes technologies look good for the first sight? Is it a great demo showing an easy-to-implement solution? What makes you to choose a given technology? A nice graphics, open source, wide community?
Well, I have major interest in Java related technologies so my opinion may be skewed by that. Recently, I felt for some technology (let's call it Technology X) and I chose it for my project. It has the following attributes that I appreciated (not in any particular order):
- open source
- active community
- fancy demos
- great ratio of source lines/work done
- supporting tools
- usable documentation
- some books by known authors exist
- fresh post "bleeding edge" technology
Especially the last attribute was a problem. I usually wait several months before upgrading my Linux distribution to hear from the community about major problems. I waited for a year after relatively wide adoption of Technology X. Obviously it was not enough and my decision proved to be a big mistake.
What might look fancy at the beginning could become a real nightmare. My problem was that Technology X was well prepared for many standard usage scenarios keeping the above list of attributes valid. When I started looking at some specific problems I got into a trouble. And what makes your project exceptional? A specific behavior that nobody else has, in my opinion.
To make the long story short, I ended up dwelling in the Technology X's source code to realize that there are well-known bugs and design flaws that were blockers to my project.
What makes me think of this story was another blog post of a new superb glorious Technology Y that can become a panacea to your projects. As a proof of all the positive features authors demonstrated a Getting started example of nothing too fancy, but enough to give you an idea of...
But realistically, it is possible that later the authors abandon the project and no other blog will be published. It is not likely to see a blog post describing what is not possible with Technology Y. So please, before you write a Getting started blog/article, always make sure that you have tried advanced features of that technology as well.
Eventually, I used Technology Z for my project. It was a complete restart of the development phase. This time I was more cautious. I realized that with the right technology I can start doing some real work early in the technology studying phase. The documentation is precise, yet relatively short. Technology Z has a great support in my favorite IDE. I have control of what and how is done - the technology is flexible in allowing me to choose an appropriate level of granularity in different parts of my project depending on my goals.
I couldn't believe it. Technology Z offers me the same functionality as Technology X. I do not have to write any significantly bigger amount of code or configuration files. I can implement new features in my project in approximately 20% of the original time needed with Technology X. Long live Technology Z.
Today, I needed to compute an average value of a function. The problem was that the function was a chart in a .gif image.
I run across a great application called ImageJ. It has a pluggable interface, many powerful functions, it is open-source and written in Java. The platform independent distribution has only 3MB.
I opened my image in the application, cropped the unnecessary parts, and used the magic wand to selected the area under the function line. Then I just clicked on measure and got the area of 69035 pixels (btw. this is the value of the integral). I divided the number by the width of the image and got 226. Now I subtracted 226 from the image height and looked at the y-axis for the average value - 8.7...
Disclaimer: ImageJ is being developed at the National Institutes of Health by an employee of the Federal Government in the course of his official duties. Pursuant to Title 17, Section 105 of the United States Code, this software is not subject to copyright protection and is in the public domain. So long and thanks for ImageJ!

My Home Page
LinkedIn
Identi.ca
Twitter
Facebook