... until the collector arrives ...

This "blog" is really just a scratchpad of mine. There is not much of general interest here. Most of the content is scribbled down "live" as I discover things I want to remember. I rarely go back to correct mistakes in older entries. You have been warned :)

2007-01-29

BIRT vs Script Extensions vs jTDS vs Eclipse Plug-ins

BIRT permits developers to create script extensions in Java.  These extensions can be called from a report's script to perform customized processing.  However, BIRT will not find such extensions unless you manage the classpath yourself manually.  The problem can be corrected by editing the MANIFEST.MF in the plug-in org.eclipse.birt.report.engine and adding the directive Eclipse-BuddyPolicy: dependent to the end.  This allows BIRT to find extensions in your plug-ins.

BIRT also allows you to add JDBC drivers to the report engine by dropping files into a directory in the plugin org.eclipse.birt.report.data.oda.jdbc.  This does not work, however, for drivers that require native libraries (such as ntlmauth.dll that supports the jTDS driver).  You can work around that problem by creating a plugin that contains your driver and its native library, and then adding a reference to that plugin in the manifest of BIRT's JDBC plugin.  It is not sufficient to copy the native library into BIRT's plugin if your application uses it itself because native libraries can be loaded from exactly one plugin.

This all seems nice and neat, but here is a problem.  A developer experienced a problem where the jTDS driver class could not be loaded by BIRT (even though it had been successfully loaded by the main application).  Checking the application's plug-in registry, the jTDS plug-in had been successfully resolved.  I had run into a similar problem when I had switched into a branch that lacked the jTDS plug-in and then switched back.  I found that I could fix the problem by touching the MANIFEST.MF in BIRT's org.eclipse.birt.report.data.oda.jdbc plug-in.  I chalked it up to some sort of stale plug-in cache in Eclipse.  But the other developer did no such branch switch -- Eclipse just stopped respecting the updated manifest directive.  The 'touch' trick fixed it, however.  Puzzling...

This entry was updated on 2007-02-13: the plug-in to patch with Eclipse-BuddyPolicy is org.eclipse.birt.report.engine, not org.eclipse.birt.report.viewer.  If you change only the latter, then only the BIRT viewer component will see your extensions.  If the change the former, both in-memory and viewer applications will see them.

Excel User-defined Worksheet Functions

I don't know why I keep forgetting this: if you want to use a VBA function in a worksheet formula, the function must be defined in a module (neither workbook nor worksheet functions are visible).

2007-01-23

Building esi.execute

I tried to do a build of a freshly checked out copy of esi.execute.  There were a number of problems:

- I needed to delete junit-4.1.jar from C:\esidev\eclipse3.2.x\plugins\org.apache.ant_1.6.5\lib

- I had to add the TestNG plugin (org.testng.eclipse_4.7.0.0) to C:\esidev\external_plugins\eclipse\plugins

- I had to define the Eclipse classpath variable WEBLOGIC_8_1 as C:/esidev/bea/weblogic81

Eclipse xdoclet Error

In an Eclipse project, I had this pesky error message:

The preferences for the xdoclet runtime does not point to a valid installation.

I wasn't using xdoclet in the project.  It turns out that this can occur if some tool (like the WST plug-in) had added xdoclet nature to the project and subsequently removed it.  I found a reference to this problem in the Eclipse bug tracker.  The bug entry suggested adding and removing xdoclet nature to clear up any left over problem markers.  I did this, but then I found out that my project actually had xdoclet nature, along with WST and JEM natures.  I guess at some point the project must have been opened by the WST plug-in.  The funny thing was that the project did not take on the characteristic look of a WST project in the package explorer.  I hand-deleted the various natures from the .project file and then all was well.

2007-01-17

SQL Server 2000 vs. Hibernate 3

Our Hibernate 3.1.3 application started acting up.  The symptoms were after a call to Query.list(), one of the queried tables was being locked.  This is strange, given that the operation is read-only, and that it only happened on one of the many such calls.  The problematic query was probably the largest query in the system.  We ran the application in three different environments, but it only failed in one.  The failed environment was running SQL Server Developer Edition 8.00.194 (RTM).  The two successful environments were running SQL Server Developer Edition 8.00.2039 (SP4).  Our hypothesis is that this accounts for the difference.  Early versions of MSDE had issues closing cursors -- perhaps we've been bitten by that.

2007-01-16

Hibernate Logging

With all the preliminaries out of the way, now I can talk about appropriate logging levels in Hibernate.  Setting org.hibernate.SQL to at least DEBUG/FINE shows the SQL statements that are executed.  Setting org.hibernate.type to at lest DEBUG/FINEST shows the values bound to variables in the SQL statements -- but be warned that this is very verbose.

The Hibernate manual details all of the logging properties.

JDK Logging

If I had a dollar for every time I've looked this up...

To configure JDK logging, you can either edit the file JAVA_HOME/lib/logging.properties, or you can define the system property java.util.logging.config.file to point to another file.  The file looks like this:

handlers = java.util.logging.ConsoleHandler,java.util.logging.FileHandler

java.util.logging.ConsoleHandler.level = FINEST
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter


.level = INFO
org.hibernate.SQL.level = FINE
org.hibernate.type.level = FINEST

The level specification in bold is a common gotcha - it limits the level of the messages that are shown on the console.  The levels are: FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE (and OFF).  More details can found in the javadoc for java.util.logging.LogManager.

Eclipse Applications and JConsole

To enable an Eclipse application for use with JConsole, create an .INI file for your application (e.g. myapp.ini) that contains the following lines:

-vmargs
-Dcom.sun.management.jmxremote

log4j Logging

I'd like more dollars for looking up this as well...

To configure log4j logging, the file log4j.properties must be present on the classpath.  It looks like this:

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=hibernate.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

log4j.rootLogger=debug, stdout, file

log4j.logger.org.hibernate.SQL=debug
log4j.logger.org.hibernate.type=info

Again, the level in bold limits what is written to the appenders.  The levels are TRACE, DEBUG, INFO, WARN, ERROR, and FATAL.  More information can be found in the log4j javadocs.

2007-01-15

Hibernate 3.1.3 Failed Saves

Hibernate 3.1.3 has the following buggy behaviour.  If a Session.saveOrUpdate() fails, the object being saved is still marked for saving.  Thus, the next time Hibernate tries to synchronize with the data store, the save will be retried and (probably) fail again.  The object should not be so marked until the application elects to explicitly try to save again.  This appears to be fixed in Hibernate 3.2.

2007-01-12

Eclipse Java Compiler Bug

The Eclipse Java compiler issues an inappropriate warning in the following code:

    public int zot(Object obj) {
        if (obj instanceof String) return 1;
        if (obj == null) return 2; // inappropriate warning on this line
        return 3;
    }

It complains that obj cannot possibly be null -- even though it can.  Experimentation suggests that something about the instanceof operator confuses the compiler.

2007-01-08

Eclipse Java Compiler Non-Null Warnings

The Eclipse Java compiler does some clever reasoning about the possible null state of variables.  For example, the following code will compile without complaint:

Object result = getMyObject();
result.doSomething();

However, the compiler will generate a warning that result may be null in the following:

Object result = getMyObject();
System.out.println(null == result);
result.doSomething(); // warning: result may be null

The two look the same semantically, don't they?  It would appear that the compiler, as an expediency, presumes that any object returned from a call will be non-null, until it sees evidence that there is any other possibility.  In the second instance, there is such evidence because the programmer has expressed concern explicitly.  A clever trick, to be sure.

Hibernate vs. Object.equals()

You must take care when implementing Object.equals() for Java objects being persisted using Hibernate.  Well, this is no surprise because the Hibernate documentation says so.  However, here is a subtle gotcha that is not emphasized in the current Hibernate documentation.  I ran across some classes whose equals() method tested that the other object was of exactly the same class as the target object.  This is unusual, because most equals() methods settle for instanceof.  The ones that used strict equality were broken because Hibernate's decorated versions of classes might be used in place of the actual classes.  Consider, for example this stack trace:

TBProductCatg(AbstractPersistentObject).equals(Object)
AbstractPersistentObject$$FastClassByCGLIB$$1ce0f1a2.invoke(int, Object, Object[])
MethodProxy.invoke(Object, Object[])
CGLIBLazyInitializer.intercept(Object, Method, Object[], MethodProxy)
TBProductCatg$$EnhancerByCGLIB$$ec0e8df4.equals(Object)

In this case, the initial call to equals() was passed a decorated object but you can see from the trace that it ultimately was passed to an undecorated version of the class.

2007-01-03

IE7 vs. Automatic Windows Authentication

As of IE7, any URL whose host portion contains a dot is considered to be outside the intranet zone.  Thus, automatic Windows authentication is disabled (by default).  As a workaround, you can now add individual URLs to the list of intranet sites.

I tried to add a wildcard for the local domain to the list of sites (*.mm.local).  IE complained that the URL was already listed in another zone, and that I should remove it from that zone first.  True enough, it was in the trusted sites zone.  So I removed it and tried again.  I exited and relaunched IE.  I logged out and logged back in.  I rebooted.  The same message occurred after each of these measures. I tried a different wildcard, and it worked.

There appears to be a bug where once something has been in the trusted sites zone, you can't ever add it to another zone.  I connected to a web site in the local domain, entered the requested password, and IE showed the site as still belonging to trusted sites.  But the wildcard no longer appears in the trusted sites list.

Problem solved.  The registry key

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap

contains the IE zone mapping.  It didn't show my local domain, but the corresponding key under HKLM did.  I'm not sure how the HKLM key got there, and there was no evidence of the registry setting in the IE configuration dialogs.  Deleting the key made things work as expected.

Blog Archive