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.

Saturday, April 24, 2010

Switching components in Swing with MigLayout

During Swing application development, I had a situation when at one location I had to display one component or another, based on third component value.

Normally, I would have to create some tricks with sizes or remove items from layout, but with MigLayout this is fantastically easy.

There is magic parameter "hidemode". If you set this value to 2 it will automatically shrink element's sizes to 0 when they are hidden.

So complete solution is to put all switchable parameters to same cell and set this "hidemode" to 2.

panel.add(inputField, "split 2,hidemode 2");
panel.add(comboField, "hidemode 2");

Now, when you need to show one element, you just hide other and vice versa.

inputField.setVisible(true);
comboField.setVisible(false);

Writing binary data between Java and Python

I have small project where server-side is done in Python and client is J2ME application and they have to talk to each other. At one time I had JSON to do it, it is quite easy on both sides, there are nice libs both for Java and Python. But recently, as traffic was growing and JSON performance on J2ME is not suitable for my tasks, I decided to try Java serialization with data streams.

For Java it is trivial:

DataOutputStream daos = new DataOutputStream(baos);
daos.writeLong(value1);
daos.writeInt(value2);
daos.writeBoolean(value3);
daos.writeUTF(value4);

In Python there is no such thing, but there is nice utility package called struct. It basically allows to read and write binary data and convert it into normal data. It is configurable and with small experimenting it is possible to find matching reading and writing functions for Java counterparts.

For example to parse example that is written above:

result = struct.unpack('>II', input1)
value1 = (result[0] << 32) + result[1]
result = struct.unpack('>i', input2)   // result[0] becomes value2
result = struct.unpack('>b', input3)   // result[0] is 1 for true and 0 for false


With strings it is a little bit trickier, because with method writeUTF, Java writes string length as 2 byte number and UTF-8 string. So in Python it is:

result = struct.unpack('>H', input4)
result = input5 // it is already acceptable for Python, just calculate result[0] bytes from input

Similar is also writing from Python to Java; same data formats are good for Java reading.

There is nice trick in Python, it allows to unpack and pack a lot of parameters simultaneously, for example this example above can be shortened to:

result = struct.unpack('>IIibH', input6)  // result array now contains all unpacked values except string