Latest Posts »
Latest Comments »
Popular Posts »

Bleeding edge of development – upgrading system and ANT stops working

Written by Toomas Römer on December 28, 2009 – 5:32 pm

I run Debian Unstable as my main desktop system. I shoot myself in the foot couple of times a year with the upgrades but I like using the bleeding edge of development.

Today after my “regular” upgrade I noticed that one of the ANT tasks did not perform as I would have expected.

/home/toomasr/workspace/project/build.xml:459: The following error occurred while executing this line:
/home/toomasr/workspace/project/changelogic-build.xml:72: Please check the correctness of the root url property. The server returned HTTP response code 300 or above for the URL http://172.17.57.242/lib/changelogic-build.xml

A quick ant -debug did not help me much.

/home/toomasr/workspace/project/build.xml:459: The following error occurred while executing this line:
/home/toomasr/workspace/project/changelogic-build.xml:72: Please check the correctness of the root url property. The server returned HTTP response code 300 or above for the URL http://172.17.57.242/lib/changelogic-build.xml                                                                                                                                       
        at org.apache.tools.ant.ProjectHelper.addLocationToBuildException(ProjectHelper.java:508)                                                                                   
        at org.apache.tools.ant.taskdefs.Ant.execute(Ant.java:369)                                                                                                                  
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)                                                                                                     
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)                                                                                                              
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)                                                                                            
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)                                                                                    
        at java.lang.reflect.Method.invoke(Method.java:597)                                                                                                                         
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)                                                                                              
        at org.apache.tools.ant.Task.perform(Task.java:348)                                                                                                                         
        at org.apache.tools.ant.Target.execute(Target.java:357)                                                                                                                     
        at org.apache.tools.ant.Target.performTasks(Target.java:385)                                                                                                                
        at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
        at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
        at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
        at org.apache.tools.ant.Main.runBuild(Main.java:758)
        at org.apache.tools.ant.Main.startAnt(Main.java:217)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)
Caused by: /home/toomasr/workspace/project/changelogic-build.xml:72: Please check the correctness of the root url property. The server returned HTTP response code 300 or above for the URL http://172.17.57.242/lib/changelogic-build.xml
        at org.apache.tools.ant.taskdefs.Exit.execute(Exit.java:142)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
        at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.Target.execute(Target.java:357)
        at org.apache.tools.ant.helper.ProjectHelper2.parse(ProjectHelper2.java:142)
        at org.apache.tools.ant.ProjectHelper.configureProject(ProjectHelper.java:93)
        at org.apache.tools.ant.taskdefs.Ant.execute(Ant.java:367)
        ... 17 more
--- Nested Exception ---
/home/toomasr/workspace/project/changelogic-build.xml:72: Please check the correctness of the root url property. The server returned HTTP response code 300 or above for the URL http://172.17.57.242/lib/changelogic-build.xml
        at org.apache.tools.ant.taskdefs.Exit.execute(Exit.java:142)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
        at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.Target.execute(Target.java:357)
        at org.apache.tools.ant.helper.ProjectHelper2.parse(ProjectHelper2.java:142)
        at org.apache.tools.ant.ProjectHelper.configureProject(ProjectHelper.java:93)
        at org.apache.tools.ant.taskdefs.Ant.execute(Ant.java:367)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.Target.execute(Target.java:357)
        at org.apache.tools.ant.Target.performTasks(Target.java:385)
        at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
        at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
        at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
        at org.apache.tools.ant.Main.runBuild(Main.java:758)
        at org.apache.tools.ant.Main.startAnt(Main.java:217)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)
 
Total time: 3 seconds

The access log on the server did not show anything for the request. Browsing to the url with FireFox worked just fine. Where to even start debugging this? The simple env did not show any proxies configured either. Quite lost.

At last I decided to trace the problem with strace. strace -f ant my_target > result 2>&1 produced 35 892 lines of output. Searching for the ip showed me the message

35596 [pid 13544] connect(46, {sa_family=AF_INET6, sin6_port=htons(80), inet_pton(AF_INET6, "::ffff:172.17.57.242", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 ENETUNR      EACH (Network is unreachable)

Weehah, I’m getting somewhere! Googling a bit showed me multiple solutions. Either a system wide sysctl -w net.ipv6.bindv6only=0 or just -Djava.net.preferIPv4Stack=true will do the trick. I hope this helps somebody.


Tags: , ,
Posted in tips | No Comments »

Hacking with IDE plugins – fun art of binary patching

Written by Toomas Römer on December 11, 2009 – 6:34 pm

Today’s software is so much about integration. You can have a cool Java utility but if you don’t have an Eclipse plugin for that, a large % of Eclipse users won’t adopt (IDEA & NetBeans users require plugins just as much). In the consumer market the same goes for browser extensions and iPhone apps that support the main service with better accessibility.

There are different ways for integration. Usually it is done via an API. The host platform offers some hooks into the system and you can use them to add some custom functionality on top of the host (or maybe just integrate your own product with the host). The result of this in the IDE world is a plugin. JRebel (the product our team is spending the most development time on) has plugins for application servers, frameworks and even IDEs.

If you’re in luck you can achieve everything with the API, if not you need other tricks. If the API does not offer certain public methods or access to some internal fields you can go in with reflection and still use them (of course there are no guarantees if the internals stay the same on version changes).

One step further to the darkside is binary patching. By binary patching I mean adding/changing/removing methods/fields/classes in runtime. This is the approach that we had to take when writing the JRebel NetBeans plugin.

On NetBeans startup we lookup a debugger class and on success try to patch it. In 2009 and using the JVM (not native apps) it is quite an easy task, at least for the most part. No assembler involved (of course you could be using a bytecode generation library), no need to do jumps to correct offsets or even read assembler (or bytecode).

In our case we use the Javassist library. It is a matter of inserting Java code embedded into a String to methods looked up via reflection. For example the following code adds some new code into the beginning of a method.

ctc.getDeclaredMethod("setRequests").insertAfter(
  "org.netbeans.api.debugger.jpda.LineBreakpoint _breakpoint = getBreakpoint();" +
  "java.lang.String _className = _breakpoint.getPreferredClassName();" +
  "if (_className == null) {" +
  "  _className = reader.findCachedClassName(_breakpoint);" +
  "  if (_className == null) {" +
  "    _className = org.netbeans.modules.debugger.jpda.EditorContextBridge.getContext().getClassName (" +
  "      _breakpoint.getURL ()," +
  "      lineNumber);" +
  "    if (_className != null && _className.length() > 0) {" +
  "      reader.storeCachedClassName(_breakpoint, _className);" +
  "    }" +
  "  }" +
  "}"

For the complete source code of the patch see the src folder of the nb-plugin.

In conclusion, the best way to integrate with any system is via the API it provides. If it does not cut it then look into reflection and start using internals. You will lose on maintainability of course. Still not happy? Look into binary patching and have your fingers crossed whenever the target platform releases a new version.

Reblog this post [with Zemanta]

Tags: , , ,
Posted in cool, tips | 1 Comment »

Waiting for GMail themes? Log out and log back in

Written by Toomas Römer on November 21, 2008 – 2:40 am

I was waiting for the Gmail themes tab to appear on the settings page but it never did. I run Gmail under Prism and I hardly ever log out. Once I did do that and logged back in I finally got the themes tabs. Running terminal right now, nooooot.


Posted in tips | No Comments »

How to waste 3GB of traffic on 404 pages

Written by Toomas Römer on November 6, 2008 – 7:25 pm

The previous post on dow.ngra.de generated tons of traffic. That tons of traffic generated 120 000 requests to a style sheet file that did not exist. Wordpress will display a semi fancy page for 404 files that weighs about 25 KB. 25 KB times 120 000 is 3 000 000 KB :).

Actually the same happened to favicon.ico and a few others. So either have your referred files and favicon.ico on your server or rework Wordpress mod_rewrite configuration not to handle css/js/ico/png/gif/jpg files. This will save you money!


Posted in tips | No Comments »

Linux, Windows and exit codes – the debug story

Written by Toomas Römer on October 22, 2008 – 9:07 pm

While running a test framework I was very pleased to see all the tests pass. The problem was that I was the only one that lucky.

The logic of the framework is quite simple, ANT build.xml starts up, runs a test as a separate java task, gathers the result code and tests for equality of -1. The test was failing for no reason.

Checking the source code of the java task it was obvious that it was returning -1. Quick grep and a debugger session showed that ANT was not mangling the return code. So System.exit(-1) was returning 255. System.exit(42) then again returned 42.

Quick google shows that this is how it is supposed to work. Quoting from steve-parker.org

Exit codes are a number between 0 and 256, which is returned by any Unix command when it returns control to its parent process. Other numbers can be used, but these are treated modulo 256, so exit -10 is equivalent to exit 246, and exit 257 is equivalent to exit 1.

And then we have Windows where -1 is a valid exit code (well, at least it works). Something to remember when have to exit on multiple platforms.


Posted in tips | No Comments »