Unresolved dependencies

A while ago I created this picture:

unresolved_dependencies.jpg

For some reason I was watching my older pictures and this one struck a chord with me today. Since my last blog post a lot of things have happened. One of those things is that after nine years I will be leaving my current employer Info Support.

Also I’ve been doing a lot of soul searching and I have come to some conclusions.

There is a person I care about fighting as I write this to get well again. I sure hope that person will find the strength and will to press on and fight for all the good things this person still wants to do.

Suffice to say there are many other things as well… All coming down to the line clearly readable on this picture.

“Unresolved dependencies”

Enabling HTTP request response logging on JBoss 4.2

Today I had a bit of a fiddle with JBoss 4.2 due to IE7/IE8 compatibility differences.

When opening or downloading a file in IE7 over an SSL connection (HTTPS), IE7 requires a bit of HTTP header-fu to allow you to actually perform that action.

It’s simple really. Just add “Pragma: public” and “Cache-Control: maxage=3600” to your HTTP headers and you’re good to go.

In Java code:

response.setHeader("Pragma", "public");
response.setHeader("Cache-Control", "maxage=3600");

To check if it’s working was a different matter. How to check the HTTP header content when things get sent over an HTTPS connection… FireBug doesn’t work, and so doesn’t any other developer tooling in any browser. Tracing the network traffic is pretty useless too, it’s encrypted. Last option, trace it on the server. Simply enabling network tracing on the Java VM didn’t work. For some reason JBoss doesn’t pick up this Java VM setting, probably because they are using a NIO based stack or something. I really don’t know.

JBoss does use Catalina for it’s HTTP/HTTPS/Web container handling. Catalina is another name for Tomcat. Tomcat has this valve thing which allows you to plug into the processing pipe. Good thing there are standard Valve implementations available that do just what I needed.

Just drop the next snippet somewhere appropriate:

<!-- Enable http request/response logging.-->
<Valve className=org.apache.catalina.valves.RequestDumperValve
           prefix=localhost_access_log. suffix=.log
           pattern=common directory=${jboss.server.home.dir}/log
           resolveHosts=false />

Appropriate in my case was in the file “[JBOSS-HOME]/server/default/deploy/jboss-web.deployer/server.xml”.

And lo and behold it logged:

11:46:44,262 INFO  [[localhost]]           authType=BASIC
11:46:44,262 INFO  [[localhost]]      contentLength=48189
11:46:44,262 INFO  [[localhost]]        contentType=application/pdf
11:46:44,262 INFO  [[localhost]]             header=Pragma=public
11:46:44,262 INFO  [[localhost]]             header=Cache-Control=maxage=3600
11:46:44,262 INFO  [[localhost]]             header=Expires=Thu, 01 Jan 1970 01:00:00 CET
11:46:44,262 INFO  [[localhost]]             header=X-Powered-By=Servlet 2.4; JBoss-4.2.3.GA (build: SVNTag=JBoss_4_2_3_GA date=200807181417)/JBossWeb-2.0
11:46:44,332 INFO  [[localhost]]             header=X-Powered-By=JSF/1.2
11:46:44,332 INFO  [[localhost]]             header=X-Powered-By=Servlet 2.4; JBoss-4.2.3.GA (build: SVNTag=JBoss_4_2_3_GA date=200807181417)/JBossWeb-2.0
11:46:44,332 INFO  [[localhost]]             header=X-Powered-By=JSF/1.2
11:46:44,332 INFO  [[localhost]]             header=Content-Type=application/pdf
11:46:44,332 INFO  [[localhost]]             header=Content-Length=48189
11:46:44,332 INFO  [[localhost]]             header=Date=Thu, 26 Aug 2010 09:46:44 GMT
11:46:44,332 INFO  [[localhost]]            message=null
11:46:44,332 INFO  [[localhost]]         remoteUser=admin
11:46:44,332 INFO  [[localhost]]             status=200

-XX:-DontCompileHugeMethods

Read some stuff today about huge methods and the JVM’s JIT Compiler.

The JIT proces detects hotspots in code. If a hotspot is detected (usually 1000 to 1500 hits depending on your platform and JVM version) the JIT process marks a method for compilation to machine instructions. After compilation, method invocations are generally crazy fast on a method since the JIT process had like a thousand times to see what generally happens during the execution of a method and can optimise accordingly. (So never ever use the Xcomp option on the JVM, it forces compilation from the start, but this is generally slower, because the compilation will not be optimized in any way.)

The thing is, when performing this operation of marking methods for compilation there’s a catch. An 8k byte code instructions catch to be exact. If a method in byte code contains more then 8000 byte code instructions it will never ever be marked for compilation, period. About 2500 lines of Java code should do the trick. But believe me, I’ve seen crazy fools create monsters methods of that magnitude.

It gets even better though. When looking for methods to mark for compilation, the JIT process uses a call graph when doing it’s magic work of granting methods the privilege of optimized compilation. And here comes the catch in that, if a big fat honking pile of 8k byte code is encountered in a method while walking the call graph, JIT says: “I aint touching that!”. Thus any method called from that pile of poop not reachable in any other way through the call graph, will never ever feel the warm love of JIT optimized compilation.

Now you could use the lovely “-XX:-DontCompileHugeMethods” argument when invoking the JVM. But from what I’ve understand it’s a bad thing to do, because amongst others it forces the JVM to go digging through those 8k wonders of human creativity.

Other option is to just use your sane mind and round up and terminate the morons in your project creating these 8k monsters. It’s good practice anyway to keep your methods small and task focussed in any object oriented language.

The gist is, don’t use “-XX:-DontCompileHugeMethods”. Go bananas during a code review whenever you find any method which is too big for comfort. Let’s just say that the default statement count suggested by checkstyle is a good one. So any method or constructor above 30 statements in length should be cause for investigation during a code review.

Installing MS Office for Mac frrresh

For some reason installing Office for Mac 2008 all in one go (installation, SP1 update and updates) led to a severely broken installation.

Read somewhere on the internet that I should’ve rebooted my system after every installation. That’s 5 reboots for you, once after initial install, once after SP1 update, once after a point release, once after a second point release and once for an auto updater update. Jikes!

Rebooting like a mad mad did result in a working system though. Don’t know why. Tried it n two separate clean OSX installs and it went off without a glitch. Except for the insane amount of rebooting that is.

Mac OSX Open Terminal Here Service

Mac OSX Snow Leopard has revived the Services menu.

I’ve implemented a really simple Service called “Open Terminal Here”. It’s a small service which becomes available in the context menu of every file and folder in the Finder with an entry called “Open Terminal Here”.

It’s function is really simple, it activated the Terminal application and changes the current directory to selected directory or the containing directory, depending whether you selected a file or folder.

The linked zip file contains a file named: “Open Terminal Here.workflow”
If you would like to change the name appearing in your services menu, just change the name of the file to something else. make sure the extension remains the same. For example: “Any other Name.workflow”.

After you are happy with the services name, copy the resulting file to the directory “Library/Services” in your user’s home directory. Now you can open a Terminal window at the location you’ve just selected, it works for multiple selections too.

Here’s the link to the zip file: Open Terminal Here 0.3.zip

Oh just a little tip, to open the current Terminal.app path you’re at into a Finder window, just type “open .” followed by a return. (Yes, that’s 4 characters, a space and finally a dot.)

Some people have reported some issues while installing this service. Please see the comments for a workaround by j.g. Owen.

Version 0.3:
-Fixed the multiple window problem (courtesy John-Michael Glenn)

Version 0.2:
-should fix a localization problem.

I’ve also created a SVN repository for this little bit of code: http://leenarts.net/svn/opensource/Open%20Terminal%20Here/
When asked for a username and password, just enter empty strings.

JDK 7 – Project Coin is final

Friday Joseph Darcy announced through a blog post that Project Coin is final.

Project Coin is just one of the changes coming to JDK 7. But, since the changes in Project Coin are all small changes to the Java language, every single Java developer will have to deal with these coming changes.

  • It’s looking like we can use Strings in switch statements:
    static boolean booleanFromString(String s) {  
      switch(s) {  
        case "true":  
          return true;  
        case "false":  
          return false;  
      }  
      throw new IllegalArgumentException(s);  
    }  
  • Automated Resource Blocks, Josh Bloch proposed a construct like the one below:
    try (BufferedReader br = new BufferedReader(new FileReader(path)) {
      return br.readLine();
    }

    instead of:

     BufferedReader br = new BufferedReader(new FileReader(path));
     try {
       return br.readLine();
     } finally {
       br.close();
     }
  • Improved Type Inference, the diamond operator. Instead of:

    Map <String, List <String> anagrams = new HashMap <String, List <String>();

    you can do:

    Map <String, List <String> anagrams = new HashMap <>();
  • Simplified VARARG method invocation:
    static <T> List <T> asList(T... elements) { ... }
    
    static List <Callable <String> stringFactories() {
      Callable <String> a, b, c;
      ...
      *// Warning: ** uses unchecked or unsafe operations *
      return asList(a, b, c);
    }

    After this change:

    *// Warning: ** enables unsafe generic array creation *
    static <T> List <T> asList(T... elements) { ... }
    
    static List <Callable <String> stringFactories() {
      Callable <String> a, b, c;
      ...
      return asList(a, b, c);
    }
  • Something with better literal integers, can’t seem to find the details at the moment.
  • And language support for JSR 292. But this one is only interesting when dealing with dynamic languages.

JBoss with SQL Server and EJB3 is giving me a hard time

Today I had a bit of a fuss with JBoss and SQL Server. For some reason, when I declare an entity with an Id field, the persistency layer tries to push a bad query to the database.

Let me explain.

I’ve got an entity sort of looking like this:

@Entity
public class Contract {

@Id
@GeneratedValue(strategy = GenerationType.Identity)
private int contractId;
...
}

When tryin to persist this through the entity manager SQL trace on MS SQL show a query somewhat looking like:

insert into Contract (contractid, ...) values (null, ...)

You see, a null value. Sounds reasonable, I didn’t set any value on the contractid field. BUT the persistency layer should not try to insert anything into the contractid column, because MSSQL doesn’t allow it. The above SQL results in a “DEFAULT or NULL are not allowed as explicit identity values.” I’m not sure what to try next though, everywhere I looked on the internet, all examples boil down too: “Something similar should work in MS SQL too, but I haven’t tested that…”

Better luck tomorrow. For now, I googled my brains out trying to find anything helpfull.

Anybody out there have any suggestions?

Update on the next day:
It turns out that the problem was the dialect configured in the Hibernate properties in the persistence.xml. By default our development environment enters the right value for Hypersonic DB, while it should actually be like this:

<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>

And now it all works. A default SQL Server 2005 with JBoss and the latest MSSQL JDBC driver, all running EJB3.