Friday, May 28, 2010

offsetHeight is 0 in Internet Explorer

Recently I had interesting issue while testing project in Internet Explorer. I have iframe burried under a long list of elements whose parent's height is updated by AJAX callback from iframe itself depending on iframe content height. In other browser everything works smoothly but in IE there is issue that document.body.offsetHeight is 0. I was digging issue and tried to debug it and finally noticed that when I stop with debug on the line that returns height - it showed correct number - and without debug still zero. I noticed that I had document.body opened on my watch list. After removing it - offsetHeight is again 0.

So there was some element in document.body that after being called, fixed offsetHeight to normal. And after small hack
    for (val in document.body) {
      var before = document.body.offsetHeight;
      document.body[val];
      if (before != document.body.offsetHeight) {
        alert(val);
      }
    }
I found that this magic element is filters and when it is called like
document.body.filters; 
it magically fixes documents offsetHeight.

Thursday, May 27, 2010

Logging in Struts 2

Struts 2 provides a lot of logging information. To enable it in debug mode, just create log4j.properties file in classpath and add the following content:

log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n 

"There is no Action mapped" error for Struts 2 in Jetty

Recently I was trying to configure Struts 2 with Jetty. Everything was running smooth untill I tried to setup Convention plugin.

This plugin provides configuration by convention rather than XML files and has several nice features like annotation mappings for methods and reasonable default mappings. Nice plugin overall but somehow it didn't wanted to work with Jetty. It was finding JSP files without problems, but totally ignored my Actions.

I had this error:

There is no Action mapped for namespace / and action name ########. - [unknown location]
    at com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:178)
    at org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:61)
...


After experimenting for some time, I found that there is some mess with Jetty class loaders and to solve it there is nice configuration property for plugin itself. If you have the same issue you can fix it by adding

  <constant name="struts.convention.exclude.parentClassLoader" value="false" />

to your struts.xml file.
Ironically, good old configuration solved convention plugin issues.

Thursday, May 20, 2010

How to create windows service from Java application

It is relatively easy with Java Service Wrapper. It is described with JBoss example at http://wrapper.tanukisoftware.org/doc/english/integrate-simple-win.html. But actually it is even easier, so I'll try to describe it here.

Let's assume there is some ready application with public static void main method in my.company.Application class.

First, you will need to download Wrapper from here. Unpack it to some folder, better in C:/ or some short folder, I had some problems with running it from deep folder hierarchy.

Second, you will need to update configuration file at "conf/wrapper.conf". Actually, it is quite long (mostly because of comments), but worth checking as it contains mostly necessary information. You will have to update:

# path to java
wrapper.java.command=java
# this is service launcher, leave it as is
wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
# jars related to wrapper
wrapper.java.classpath.1=../lib/wrappertest.jar
wrapper.java.classpath.2=../lib/wrapper.jar
# all jars related to your application
wrapper.java.classpath.3=../mylib/jetty-continuation-7.0.1.v20091125.jar
wrapper.java.classpath.4=../mylib/jetty-http-7.0.1.v20091125.jar
...
# your application class that contains main method
wrapper.app.parameter.1=my.company.Application
# all parameters, when needed
wrapper.app.parameter.2=param1
wrapper.app.parameter.3=param2
...


Update other parameters if needed, but better at least check them. There is valuable and handy stuff like service name and description.

Third, run bin/InstallTestWrapper-NT.bat.

You service is installed and ready. You can start it from Administrative tools or with bin/StartTestWrapper-NT.bat.

Intellij IDEA debugging trick

Recently discovered one nice debugging feature in Intellij IDEA.

Sometimes it is needed to stop on breakpoint after some other breakpoint was executed. For example there is next code:

1:parent.method(1);
2:parent.method(2);
3:parent.method(3);
4:parent.method(4);

5:void method(int i) {
6: init();
7: doStuff(i);
8:}

You want to stop on line 7 when parameter is 4. Using only basic breakpoints, you will have to skip 3 first stops or use some breakpoints conditions, which is not always handy for some types of parameters.

In Intellij there is nice feature, that let's you specify dependency between breakpoints. So, in this example, you will have to put breakpoint 1 on line 4 and breakpoint 2 on line 7 and configure breakpoint 2 to depend on breakpoint 1. Then breakpoint 2 will only stop after breakpoint 1 was executed.

Nice feature that saved some time for me.