For the life of me I could not get Jython to recognize my mysql driver using JDBC. I literally spent hours trying to get it to work. Fooling with my classpath, my version of the mysql-connector and my version of Jython. Finally I gave up and wrote a really simple wrapper class.

This is the Error:

#the following line is “print sys.path”
[‘./mysql-connector-java-5.1.6-bin.jar’, ‘/Volumes/UserHome/bcx/work/istuff/iros/jar’, ‘/Volumes/UserHome/bcx/jython2.5a3/Lib’, ‘__classpath__’, ‘/Volumes/UserHome/bcx/jython2.5a3/Lib/site-packages’]
Traceback (most recent call last):
File “ss.py”, line 12, in
Class.forName(driverName)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:164)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)

java.lang.ClassNotFoundException: java.lang.ClassNotFoundException: com/mysql/jdbc/Driver

So I dealt with various version of that error for a while. Finally I gave up and wrote a wrapper class, which didn’t work until I downloaded and installed jython 2.5a3, previously I was using the latest stable, 2.2.1.

Here is my quick wrapper class:

import java.sql.*;

public class Connect
{
public static Connection getConnection(String url, String usr, String pass) throws Exception{
Class.forName (“com.mysql.jdbc.Driver”).newInstance ();
return DriverManager.getConnection(url, usr, pass);
}
}

Here is how I used it in my Jython code.

import Connect
import sys
sys.path.append(“./mysql-connector-java-5.1.6-bin.jar”)

url = “jdbc:mysql://localhost/replay”
con = Connect.getConnection(url,”root”,””) #this line uses my wrapper

stmt = con.createStatement()

In other news I implemented a mDNS enabled mysql-based indexed logger for EventHeap. The next step is to build a simple interface for replaying marked logs. I really wish I could write this interface using a language other than Jython or Java, so the next step will be fooling around with my various options. I am not sure if I am feeling adventurous enough to try out JRuby, but Ruby on Rails would be a nice way to build a really quick web front end. I am leaning towards some sort of Jython based EventHeap RPC server, that has “jobs” which can be started / stopped/ monitored/ and modified over REST or XMLRPC. This shouldn’t be that bad, but I “really” would prefer to do the network code using twisted, although I think the “goal” of this stage, is to pretty much hack this thing together asap.

I’ve recently been playing with Stanford’s EventHeap and IStuff package for some of the work we are doing here.  I am a little to spent to go into a lot of details, but the first task I tackled was trying to write some wrappers to make it easier to work with EventHeap using mDNS.  This was far harder than I thought it would be.  I kept running into a problem where I would get a serviceAdded event, but the event would not have enough information for me to actually connect to the service.

I am using the jmdns.jar package: http://jmdns.sourceforge.net/

Here is the scenario I was trying to address:

  1. Server registers it’s self using mdns using service _eheap.
  2. Sometime after this, a client application listens for services on _eheap.
  3. Client connects to server.

Unfortunately when I worked in this order I ran into the problem that the event object that mdns passes to serviceAdded did not have enough information to make a connect to the remote host.

I didn’t see any good example of how to do this.  I am sure I am probably doing something wrong.

If I did everything in this order it worked fine:

  1. A client application listens for services on _eheap.
  2. Server registers it’s self using mdns using service _eheap.
  3. Client connects to server.

However, for my purposes, I absolutely need the server to be able to start before the clients that are listening for that service.

I also just wanted to be able to write very simple code to lookup a device using mdns.  I.e. I wanted to be able to write small quick scripts, that were not event driven to connect to a service advertising itself on mDNS.

After tracing through the jmDNS code I found out that the objects actually had all the information I was trying to get, but were not providing an easy interface to it.  (There may be easier interfaces, but there is literally no documentation on jmdns that I could find)

To this end I have written a very simple Jython wrapper for mDNS which provides a few VERY simple interfaces to mDNS / ZeroConf/ Avahi / Bonjour, with the specific goal to provide authors writing very simple scripts, methods to connect to a service that is advertising itself using mDNS.

I have posted this Jython file at: http://umich.edu/~bcx/contrib/jymdns.py

DISCLAIMER: This is the first application I have ever written in Jython, and I have only been playing with mDNS for about 2 days.  Thus, this may be completely wasted effort; however, it seems to work well for my purposes.

The interface:

jymdns.py 0.1

  AUTHOR:
    Ben Congleton, bcx@umich.edu

  DESCRIPTION:
    Jymdns is a simple jython interface to the mdns library.

  REQUIREMENTS:
    jython.jar
    jmdns.jar

  INTRODUCTION:

  I could not for the life of me figure out how to use the JAVA mdns library, when I was trying
  to listen for hosts that were created before the mdns listener.  There is probably a way around this.

  This is really just a hack to use the local mDNS cache to find out information about services that
  are not responding to the event.getInfo() command.  With a few nice interfaces for writing really
  quick scripts in jython that need a simple way of finding a host on a network.

  REGISTERING:

    from jymdns import SimplemDNS

    simp = SimplemDNS("_eheap")
    simp.register("foo33", 1234)

    # do all the real stuff

    simp.stop()   # stop the mDNS broadcaster

  FINDING A MDNS HOST for a service (ignoring the name):

    from jymdns import SimplemDNS
    res = SimplemDNS.get_service("_eheap")

    if(res):
      (host, port) = res

  FINDING A SPECIFIC HOSTNAME:

    from jymdns import SimplemDNS
    res = simp.wait_for(None)

    if(res):
      (host, port) = res

  SIMPLE TEST:

    java -jar jython.jar jymdns.py

http://umich.edu/~bcx/contrib/jymdns.py

<script>

document.onkeydown = function(e) {
  var a = document.getElementById("test");
  a.innerHTML = a.innerHTML + String.fromCharCode(e.which);

  var a = document.getElementById("test2");
  a.innerHTML = a.innerHTML + e.which + " " ;    

  return false;
}
</script>

<div id="test"></div>
<hr>
<div id="test2"></div>

SmartButton TM –>

So I got my hands on a smartbutton from sourceforge while at today’s SOCHI/SCSI event.

I was curious how it worked, so I wrote a very simple javascript to capture all keyboard input into the browser window and print it to the display.

Interestingly the SmartButtonTM acts just like a keyboard, and sends the following keycodes to the active window, or OS:

224 82 87 87 87 190 83 79 85 82 67 69 70 79 82 71 69 190 78 69 84 13

Which is essentially APPLE_CMD+R + http://www.sourceforge.net [enter]

http://unixpapa.com/js/key.html was a very useful and very interesting read.

Error: ./port: selfupdate failed: couldn't open "/opt/local/var/db/
dports/sources/rsync.rsync.macports.org _dpupdate1/base/config/
dp_version": no such file or directory

I wanted to install something using ports today, and ran into the above problem.  Apparently when I updated /opt/local/etc/ports/ports.conf with the correct rsync location I left a trailing space.  At least one other person on the internet ran into this problem as well.  Well, if you are getting the above error, edit your ports.conf, and make sure you don’t have an extra space at the end of the configuration directive that set’s macports as the new darwin port source.

A few other Darwinport hints.  To update your port files run “port selfupdate” if that fails try, “port -d selfupdate”, which apparently tries a little harder by working from scratch.

Many universities have webproxies that let students and faculty members access restricted pages remotely. For me this mostly falls under ACM’s webportal. For the longest time I have manually typed in “.proxy.lib.umich.edu” for each URL that I have this problem with. But TODAY I solved this problem for good with JavaScript. Unfortunately I cannot add the bookmarklet directly to wordpress because they filter javascript. But. If you too want to copy this trick, create a bookmark with the following URL:

javascript:function a(){var parts = document.location.toString().split(“\/“); var url=parts[0] + “\/\/“ + parts[2] + “.proxy.lib.umich.edu“ + “\/“;parts.shift();parts.shift();parts.shift(); url += parts.join(“/“); document.location=url; }a()

Name the bookmark “Access with webproxy”, and drop it into your “Navigation toolbar”, now when you are on a webpage that you would normally need to use the proxy for just click the newly created bookmark.

I wrote a web-crawler today for one of my other projects, and ran into the above problem “OpenSSL::SSL::SSLError: certificate verify failed”, well I was just collecting websites and didn’t really care about the validity of SSL certificates, so I just wanted a quick fix.

Here it is:

require ‘openssl’
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE

Essentially, I just change the constant for VERIFY PEER to the Value of VERIFY NONE, pretty sneaky :-), and no real work required.

I don’t feel like rehashing the hours I spent today trying to get various methods of taking command line screen shots of web-pages to work, but I’ll pull out a few useful pointers here.

There are 2 ways of doing this for free. (That is, if you value your time at $0 an hour)

First: khtml2png

http://khtml2png.sourceforge.net

khtml2png2 can be installed via a debian package, and runs on any variant of linux, as long as you have KDE installed. I didn’t, and thus spent a long time downloading KDE. It uses Konquerer to render the webpages, and Konquerer will often prompt for user input when something is wrong (i.e. — a plugin is missing (FLASH), or the web site wants access to your cookies.) It also was incredibly slow on my relatively fast desktop machine. However, it does the job — alright, and fits the price — free.

Second: webkit2png

Unfortunately, I was determined to make this process a little bit faster, and spent about 4 hours trying to get http://www.paulhammond.org/webkit2png/ to work. Webkit2png will run on OSX and takes screenshots using WebKit. It is fast, and a pain in the ass to install if you are unlucky. You’ll need Python, and the PyObjC wrappers. It was trivial for me to setup the wrappers from http://pyobjc.sourceforge.net/. The whole process should be pretty straightforward, install PyObj, and grab the Python code from the above website, no problem. Of course on my computer WebKit the header files the PyObjC setup.py wanted could not be found, and because of this the PyObj was not generating some of the files that PyObjC needed to run, “_WebKit_Str.inc” in particular. I tried a few tricks to make the setup.py find these header files, and managed to completely screw up my webkit install. Long story short, the script that generates stub files for PYOBJC ONLY looks in /System/Library/Frameworks/ no matter what you specify in the setup.py, and doesn’t even look in /Library/Frameworks even though it is listed in the default setup.py.

For PYOBJC to install correctly, you must have a directory called WebKit.framework in /System/Library/Frameworks, and it MUST have a Headers directory inside of it. And these headers must match the binary version of the WebKit library. I.e. you should have a directory structure that looks like:

bcx-mbp:/System/Library/Frameworks/WebKit.framework root# ls -l
total 24
lrwxr-xr-x    1 root  wheel    27 Jun  3 23:29 Frameworks -> Versions/Current/Frameworks
drwxr-xr-x   42 root  wheel  1428 Jun  3 23:40 Headers
lrwxr-xr-x    1 root  wheel    26 Jun  3 23:29 Resources -> Versions/Current/Resources
drwxr-xr-x    4 root  wheel   136 Jun  3 23:21 Versions
lrwxr-xr-x    1 root  wheel    23 Jun  3 23:29 WebKit -> Versions/Current/WebKit
bcx-mbp:/System/Library/Frameworks/WebKit.framework root#

The problem that I faced, and caused me to waste so much time was that I was missing the Headers directory inside of /System/Library/Frameworks/WebKit.framework. To solve this problem you can try doing a find -name WebKit.h and copying the Headers directory containing this file into your WebKit.framework directory. In my case I had another copy of the WebKit headers at: /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/WebKit.framework . Copying the headers directory from the above directory did the trick.

Now I left out a lot of the indirection that I faced in solving this problem. At some point in this process I broke WebKit and had to installed the 3.1.1 Safari upgrade from apple, (As described by: http://soakedandsoaped.com/articles/read/how-to-fix-broken-webkit-framework-after-safari-3-1-upgrade ) which updated my WebKit binary, but did not give me header files. Luckily the header files from the above /Developer/SDKs/ worked with this new WebKit binary. However the WebKit binary located in /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/WebKit.framework did not work with my version of Safari, and still gave me errors when I tried to load it using import WebKit in the python code I was testing. In short, I managed to get everything working, and I believe the root of my problem was a missing Headers directory, but I might have also needed to install Safari to fix issues with my existing WebKit install so that I could install and compile PYOBJC with WebKit bindings.

It is likely that all of these problems are fixed on Leopard, so it’s unlikely anyone else will run into these problems. I believe Leopard comes with PYOBJC preinstalled, so no worries linking the two.

So anyway I got it all working and it was worth it, webkit2png.py is far superior to the konquerer based khtml2png2 even though it was a real pain to configure on Tiger.

I guess this is a little off topic.