23 December 2005

Hibernate assertion failure

Q: So what is the likely cause of the following Hibernate exception:

[AssertionFailure] (JMS SessionPool Worker-2:) an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session) org.hibernate.AssertionFailure: null id in entry (don't flush the Session after an exception occurs)

A: After much scratching of heads it turns out it was as simple as a mandatory field not filled in on an object being saved.

So why did we get that message? I've no idea. Maybe its due to one or more of these factors:
* We're using MS SQL and the table had an identity column
* We're using Spring's TransactionSynchronizationManager to manage the transaction
* There is some logical explanation based on a thorough understanding of hibernate's internal mechanisms as to why this particular error means a missing mandatory field. I looked at the source code, but couldn't figure it out.

Its likely that the original error got buried somewhere and this one was a side-effect. However we couldn't see anything in our logs.

Well, now we know.

01 November 2005

Struts w/ Ajax and submitting editable dynamic content

I wanted to dynamically render a portion of a page using AJAX. I started by reading Sprinkle Some AJAX Magic in Your Struts Web Application by Paul Browne, but felt this fell short for a number of reasons:

  • I wanted to minimize the amount of Javascript I had to maintain for perform the round-trips

  • I wanted to use Struts actions and JSP to render the dynamic content

  • My dynamic content contains input elements which must be submittable and maintained across submits


I took a quick look at the prototype.js and decided to use it for performing the asynchronous stuff. It doesn't seem to have much documentation, but browsing the Javascript source helped. I found Using prototype.js v1.3.1

Modifying the main JSP page to dynamically include some content was easy. I had a select list which, when a new value was selected, would asynchronously load some data then present it in a table using displaytags. The values would be editable. Here is what it looked like:

<html:select property="configureApplicationId" styleid="configureApplicationId">
<html:optionscollection property="configureApplicationOptions">
</html:select>
<html:errors property="configureApplicationId">

<div id="configurationSettingsId">
</div>

<script type="text/javascript">
new Form.Element.EventObserver(
'configureApplicationId',
function(element, value) {
new Ajax.Updater(
'configurationSettingsId',
'myAction.do',
{parameters: Form.Element.serialize(element)}
)
}
);
</script>

This sets up an event listener on the change to the configureApplicationId which invokes an asynchronous HTTP post to myAction.do with the parameter configureApplicationId=value. On return, it replaces the content of the configurationSettingsId element with the result of the invocation.
The action is a regular Struts action which populates a form with the given parameter. The action forwards to a plain JSP page which renders the form content. Since the JSP page doesn't contain an <html:form> Struts tag, you have to add the name="formname" attribute to each <html:...> input element as so:

<html:hidden name="configureForm" property="configSettingsSerialized" />

Now when we submit the form after dynamically rendering a portion, the dynamic portion will disappear unless we take steps to re-render it. We could use some more javascript to do another asynchronous round-trip, but that usually has a noticable visual delay. I chose to render the dynamic portion in-line.
To do this we need to make available the same Struts ActionForm that is normally instantiated during the asynchronous round-trip and include the JSP page that is normally forwarded to during the asynchronous round-trip.

To do this, I added a method to the main page form which returned the ActionForm needed for the rendered portion and did a JSP include:

<div id="configurationSettingsId">
<c:set scope="request" var="configureForm" value="${mainForm.configureForm}" />
<jsp:include page="/path/to/jsp/myPage.jsp" />
</div>
<
Of course, for this to work, the main form must be able to populate the sub-form's values such that they can be rendered by the included JSP. That is simply a case of adding the appropriate setters to the main form, or including the same ability to setup the data as the other Action.

28 October 2005

Issues Upgrading from Middlegen hibernate 2 tools to hibernate 3 tools

Reason for move

The hibernate tools shipped with Middlegen 2.1 generates equals/hashcode based on the ID of the object. This is a well-known issue that makes it impossible to add multiple new objects in a Set. I haven't had this problem up to now.

I tried adding all of the following to the ant task:
  • equalsHashcode="true"
  • columnsIncEquals="true"
  • columnsIncToString="true"
It seems to generate toString() correctly, but equals() and hashcode() still do not contain all fields. The hbm files do seem to contain the correct meta-data though.

<update>
It appears the version of hibernate-tools.jar that I'm using was old. I downloaded hibernate-extensions-2.1.3 and used the hibernate-tools.jar from that. It seemed to solve the equals-hashcode issue. The remainder of this post servers as a reminder of what I need to do to upgrade to hibernate 3 tools...
</update>

I figured I'd try to move to hibernate 3 tools.

Finding Hibernate 3 tools

I went to the Hibernate Tools page and clicked Download. The version listed there is for Hibernate 3.1. (I tried it with hibernate 3, but it doesn't work; a particular class is missing a method). I'm not prepared to upgrade to Hibernate 3.1 yet as it is not officially released.

I tried the All Downloads for Hibernate page. It seems the latest Hibernate 3.0.x based tools is hibernate-tools-3.0.0.alpha4a.zip. It looks like the they're only going to release hibernate tools on 3.1 so the alpha4a is the last one for hibernate 3.0.

I had to switch out the task with a task as documented on the Hibernate Ant Tools documentation.

Problems Encountered
  1. Classes no longer have full constructors. This mainly caused problems in unit tests; I often populate composite keys using the constructor. All this code needs fixed.
  2. boolean types in the hbm file seem to get mapped to Boolean objects instead of primitives. This probably makes sense, but it is code that needs fixed and tested. The getter signatures have changed from boolean isSomething() to Boolean getSomething().
OK. So the constructor issue is mentioned on the Hibernate Forums. It looks like there are bugs in toString and equals/hashcode that have only recently been committed to CVS and probably only available in the Hibernate 3.1-based tools. Hmm... I think I'll forget about the Hibernate 3.0.x-based tools for now.


25 April 2005

Installing TIBCO on Ubuntu

Needed to install TIBCO EMS on Ubuntu (Hoary Hedgehog). However, running the installer (Installshield) failed with an error about libstdc++

The problem appears to be with Installshield wizard requiring an old version of libstdc++.

I followed the steps in the post Debian hath been defeated and it installed successfully

23 April 2005

Ubuntu Laptop - Playing DVDs

I stuck in the original Matrix DVD.
Totem DVD player started up and promptly hung.
I killed it, restarted it, tried to play disc again. It hung.

Used Synaptics package manager to install totem based on xine (it appears default totem is based on gstreamer).

Fired up Totem, went to play DVD, it told me it was copy protected and was I trying to play a protected disc without libdvdcss?

Couldn't find libdvdcss on Synaptics package manager.
Googled for libdvdcss, installed it.
Fired up totem again.
Played disc. It worked!

DVD title menu works
Plays full screen, audio works.

Success.

22 April 2005

Installing Cisco 3000 VPN Client

A. Download VPN client software for Linux
1. Download it
2. Unzip it to a temp directory

B. Get required Linux headers and gcc

1. Determine Kernel Version
uname -r
2.6.10-5-386
2. Select System --> Administration --> Synaptic Package Manager
3. Select Development from tree
4. Find linux-headers-2.6.10-5-386 (it _MUST_ match the kernel version)
5. Check it, OK any dialog boxes
6. Find gcc, check it, OK any dialog boxes
7. Click Apply, confirm dialog box
8. Close package manager

C. Compile VPN client

1. Open a console window and change directory to the unzipped VPN client
2. Run the install script as super user
sudo ./vpn_install
3. Accept the defaults. It should automatically detect the Linux headers you downloaded. They are linked from a number of places, including
/lib/modules/2.6.10-5-386/build
4. It will compile successfully
5. Change directory to where the VPN client tarball extracted the bundled profiles (*.pcf files), if any
6. Copy those files to
/etc/CiscoSystemsVPNClient/Profiles/
D. Start VPN client

1. The VPN client will start when the system boots. However, start it manually for now by executing:
sudo /etc/init.d/vpnclient_init start
2. Run the client with
vpnclient connect
where is one of the profiles, without the .pcf extension

3. Enter your username (username part only, not your full email address)
4. Enter your SecurID password+token

It will connect. That console window will remain busy. You can put the job in the background.

Ubuntu Laptop Install - Part 3

Unhibernate

Powered up the computer.
Prompted me to login.
It restored the windows I had open previously. Nice.

Summary

* Sound works
* Screen works at max resolution (still need to see up upgrading driver)
* Hibernate works
* Wired and wireless networking works

Seems pretty successful so far

21 April 2005

Ubuntu Laptop Install - Part 2

Continuing the Installation

I selected my time zone
I specified the user account
Ubuntu finished telling me the first stage of installation is complete
It ejected my CD and continued to reboot the computer

Booting

Watched all the messages scroll by on the boot. Everything said [ok]. Seems promising.
It then appeared to unpack a bunch of Debian packages Scrolls by too fast to read. This seems to be the slowest part of the installation by far. The hard drive is (quietly) working hard.

It appears to be done. I now have an Ubuntu logo taking up most of the screen and its prompting for my username. The screen resolution seems good. A good sign.

I logged in. Some kind of tree-hugging waterfall, birds and windchimes sound plays. At least the sound card works.

I went to System --> Preferences --> Screen resolution. Sure enough, 1920x1200. Nice.

Configuring Wireless

I pulled out my network cable.
I went to System --> Administration --> Networking
If I understand it correctly in order to configure multiple wireless networks (or perhaps multiple networks altogether), I need to assign each to a different location.
I selected the Location dropdown and choose Create New and called it "Home"
I clicked on Wireless Connection and clicked Properties
I checked on This device is configured
It detected my wireless network, so I selected its ESSID from the dropdown
I entered the wep key. I keep it on a USB stick which, when I plugged into the laptop, popped up on the desktop.
Selected DHCP and hit OK
The Wireless Connection was still selected so I clicked Activate; it popped up a dialog box telling me it's Activating interface "eth1". It took a minute or too before disappearing.
I switched the Default gateway device as eth1. I think this is what tells it which one to use in this profile.
Clicked OK to get rid of the Network settings dialog, although it doesn't seem to be going away. There is a spinning cursor when I hover the mouse over it, but the rest of the system seems fine. Hmm, still there after a few minutes.

I pulled up Firefox and went to google.com. It didn't work.
I clicked on the little network icon on the top-right of the screen and typed into the dropdown "eth1". It switched to that.
Firefox works now.


Standby?

I closed the lid. Opened it up. I was left with a console login prompt.
I pressed a few random function keys.
The computer powered off.
Powered it back on. Not sure what happened.
Its trying to boot. It came back up with a fresh login. It really did power off.

Hibernate?

I went to System --> Logout and selected hibernate.
It seemed to hibernate. Powered down.

Ubuntu Laptop Install

Notes on installing Ubuntu Linux (Hoary HedgeHog)

Here is what I'm installing on:
Dell Inspiron 9300
2Gb DDR2 533Mhz
2.0Ghz Pentium M
17" WUXGA (1920x1200)
60Gb 7200rpm HDD
256Mb Nvidia Go 6800
Ethernet and b/g wireless
Bluetooth

Getting started

* I download and burned Ubuntu Install CD
* Restarted computer hitting F12 to open boot menu and select boot from CDROM

Installation Process

* Answered various questions about Location, Language Keyboard

Configure the network
It found two network cards: eth0 (the 10/100 card) and eth1 (the wireless card) and wants me to pick which one to use while installing Ubuntu. Since I'm not plugged in, selecting Wireless (I have the WEP key)

It failed to find my access point, so I entered the SSID
I entered the WEP key
It tried to configure with DHCP, but failed. Hmm.. may have to plug in
I plugged into the network, hit Go Back and picked eth0; OK, that worked
I entered the hostname

Partion disks
I've been trying to decide whether to install a dual boot system or a Linux only system.
Since this is a brand new laptop, and I've not spent any time tweaking windows, I figured I'd blow away Windows and partition the whole thing for Linux.

For good measure I screwed around with resizing the existing Windows partition. I halved the size. The installer told me it shrunk, but I didn't try rebooting to see if it still worked.

I went back to guided partitioning and selected Erase entire disk
Since this is a personal machine, single user, I accepted the default of a 57Gb / ext3 partition and a 2.5Gb swap partition. I'm sure there is a superior filesystem to ext3 that I should be using, but I don't feel like researching it.

There also seem to be options for installing the Logical Volume Manager, but I'm thinking I don't need that.

I committed the partition and Ubuntu continued with the installation.