Start from Java/Groovy

Help
2008-10-14
2013-05-23
  • Lars Soltau
    Lars Soltau
    2008-10-14

    I am trying to start a Java application contained in a one-jar file from a Groovy script. Since I am already running in a JVM, it seems cumbersome to start the application externally.

    This is what I've done:

    ----8<--------8<--------8<----

    // add one-jar file to my class path
    def loader = this.class.classLoader.rootLoader
    loader.addURL(jarfile.toURL())

    // tell one-jar where its jar file lies
    System.setProperty('one-jar.jar.path', jarfile.path)

    String[] a = [myfile.path]
    Class c = Class.forName('com.simontuffs.onejar.Boot')
    java.lang.reflect.Method m = c.getMethod('main', [a.getClass()] as Class[])
    try {
        m.invoke(null, [a] as Object[])
    }
    catch (java.lang.reflect.InvocationTargetException e) {
        e.getCause().printStackTrace()
    }

    ----8<--------8<--------8<----

    Now I get the application to start, but there is a resource file in the jar, loaded by the application. This works fine if I start the jar from the shell, but when I start it from inside my Groovy script, I get the following output:

    ----8<--------8<--------8<----

    JarClassLoader: Info: findResource(my/pkg/MyResource.properties)
    JarClassLoader: resource my/pkg/MyResource.properties resolved to my/pkg/MyResource.properties
    JarClassLoader: Info: findResource found: my/pkg/MyResource.properties
    JarClassLoader: Warning: unable to locate my/pkg/MyResource.properties due to java.net.MalformedURLException: unknown protocol: onejar

    ----8<--------8<--------8<----

    and the application fails, unable to read its resource bundle.

    So, apparently the proprietary URL protocol onejar doesn't get registered. Any idea how to fix this?

     
    • P. Simon Tuffs
      P. Simon Tuffs
      2008-10-14

      Well, I think you're almost there!  I'm not at my dev. machine right now, but the solution is contained in the source-code; look for the protocol registration mechanism in /com/simontuffs/onejar/Handler.jar, then look for how this handler is registered. 

      This should solve your problem, let me know how it goes.

       
    • Lars Soltau
      Lars Soltau
      2008-10-15

      So, after a good look at the source and the javadoc for URL and friends, it seems that the mechanism for searching for URLStreamHandlers in all packages specified in the system property doesn't work.

      I tried including the one-jar file in the classpath (although I didn't like that idea), I even preloaded com.simontuffs.onejar.Handler, but nothing worked.

      So I had to define a new URLStreamHandlerFactory in my script and install that. The script works now, but I haven't found any method for passing unknown URL protocols to already installed factories, à la chained event handlers and the like.

      Here's my snippet of code (calling the constructor for Handler statically, I'll switch this to reflection of course so I won't have to include the one-jar file in the classpath).

      ----8<--------8<--------8<----

      java.net.URL.setURLStreamHandlerFactory(new OnejarFactory())

      ...

      class OnejarFactory implements URLStreamHandlerFactory {
      public OnejarFactory() {}
      public URLStreamHandler createURLStreamHandler(String protocol) {
      if (protocol.equals('onejar')) {
      return new com.simontuffs.onejar.Handler()
      }
      return null
      }
      }

      ----8<--------8<--------8<----