Re: Problems starting Maven based WOApplication in WOLips 3.4.5503 on Windows XP

From: Lars Sonchocky-Helldorf (lars.sonchocky-helldor..amburg.de)
Date: Thu Oct 16 2008 - 15:31:08 EDT

  • Next message: Lars Sonchocky-Helldorf: "Re: WOLips maven-wolifecycle-plugin bug?"

    Am 15.10.2008 um 22:25 schrieb Lachlan Deck:

    > On 16/10/2008, at 2:30 AM, Lars Sonchocky-Helldorf wrote:
    >
    >> Am 15.10.2008 um 16:04 schrieb Lachlan Deck:
    >>
    >>> On 15/10/2008, at 10:51 AM, Lars Sonchocky-Helldorf wrote:
    >>>
    >>>> when trying to launch a Maven based WOApplication inside Eclipse
    >>>> 3.4 / WOLips 3.4.5503 on a Windows XP machine which HASN'T
    >>>> WebObjects installed at first I got some null pointer exception
    >>>> which had something to do with not being able to read certain
    >>>> environment variables (I had a stacktrace on it inside the error
    >>>> log view in Eclipse but my co-worker did hit the clear button
    >>>> when trying to work the problem out while I was at lunch :-(
    >>>
    >>> :-)
    >
    > Just to clarify, how was this working for you before? What's changed?

    Don't ask … ;-)

    before another co-worker of mine was developing the project on
    Leopard. Now he is bussy with something else and we got a freshman
    who should take over the project. My boss assigned the freshman a
    Windows PC as workstation, and I am the one to get the project
    started there. So basically what's changed is the OS the project is
    developed on.

    >
    >>> All this is doing is looking for the JavaWebObjects bundle having
    >>> been already loaded during started. i.e., it's calling
    >>> NSBundle.bundleForName("JavaWebObjects") which in turn looks up
    >>> an NSDictionary and is getting null in return... so it decides to
    >>> throws an error.
    >>>
    >>>> What makes me wonder is that even when launching a Maven based
    >>>> WOApplication a static WO installation seems to be required and
    >>>> referred (environment variables).
    >>>
    >>> I don't believe that's true.
    >>
    >> hmm, at least the NPE in the Eclipse WOApps launcher went away
    >> after setting the NEXT_ROOT env for the first time. This could -
    >> of course - be completely unrelated.
    >
    > Okay. What was the stack trace of the NPE beforehand?

    that is the famous stacktrace that got lost when my co-worked cleared
    the error log in eclipse.

    >
    >>>> Shouldn't it work out of the box without any WO installed at the
    >>>> machine at all (and loading all the dependencies from the
    >>>> local .m2/repository instead)
    >>>
    >>
    >> Our project structure looks like this:
    >
    > Cool. Sorry - had to eliminate the obvious.
    >
    >> and the project builds now (after switching to the 2.0.16-SNAPSHOT
    >> version of maven-wolifecycle-plugin like Henrique suggested.)
    >
    > Okay. Great. So if you from TankDiskAll do
    > $ mvn clean package
    >
    > What do classpath.properties, classpath.txt, and wobuild.properties
    > look like in TankDiskAdmin/target?

    like this:








    >
    >> But the exception during the launch attempt remains …
    >
    > hmm. In your LaunchConfig for your app, on the Source tab do you
    > see under the expanded Default all the jars and project
    > dependencies you expect?

    looks quite good (see screenshot below)

    >
    > Running within WOLips has some differences in that it does (perhaps
    > did... I haven't tested with more recent nightlies to see if this
    > is really still needed) have some dependencies on what it builds
    > into project/build/YourProject.[woa|framework].
    >
    > So my launchconfig for one of my apps looks like this:<Picture 1.png>

    and mine looks like this:



    Unbekannt.jpg

    >
    >
    >
    > You might want to have a look at what settings you've inherited
    > from WOlips prefs in the WO tab of your launchconfig for the app.
    > By default these are all ticked in WOLips prefs. I usually untick
    > most of them except the ones that actually make sense to set
    > manually. So you might need to play with these.<Picture 2.png>

    I tried several variations here - which had no influence at all at
    the exception during startup.

    ========================================================================
    ===============

    Now I decided to dig deeper and have some additional notes for you
    (of which I hope those might give you a clue on what's going on)

    * I use the Q4E Eclipse PlugIn for Maven stuff inside Eclipse: http://
    code.google.com/p/q4e/ http://q4e.googlecode.com/svn/trunk/
    updatesite/ this plugin is responsible for creating the Maven
    Classpath Container

    * I found out that something/someone (the co-worker who developed the
    project before when trying to help the freshman?) added the following
    classpath variables in Eclipse:



    Unbekannt.jpg

    * I installed jad/jadclipse and fired up the debugger on the startup
    exception. Here are my findings (sit down comfortable, it's a looong
    story):

    The main cause, as we found out, seems to be the difference between
    jar files and Mac OS X bundles. look at the following code (which a
    little jad gave me):

    WOResourceManager:

                public static InputStream
    __getJavaWebObjectsResourceAsStream(String name) throws
    IllegalStateException {
    /* 113*/ InputStream is = null;

    /* 115*/ String errorCause = "";
    /* 116*/ NSBundle aFrameworkBundle = NSBundle.bundleForName
    ("JavaWebObjects");
    /* 117*/ if(aFrameworkBundle != null) {
    /* 118*/ String aUserDefaultsKeysPath =
    aFrameworkBundle.resourcePathForLocalizedResourceNamed(name, "");
    /* 119*/ if(aUserDefaultsKeysPath != null) {
    /* 120*/ is =
    aFrameworkBundle.inputStreamForResourcePath(aUserDefaultsKeysPath);
                        } else {
    /* 122*/ errorCause = (new StringBuilder()).append
    ("Unable to locate \"").append(name).append("\"").toString();
    /* 123*/ is = com/webobjects/appserver/
    WOResourceManager.getClassLoader().getResourceAsStream((new
    StringBuilder())
                                      .append("com/webobjects/
    appserver/").append(name).toString());
                        }
                    } else {
    /* 126*/ errorCause = "Unable to locate the
    \"JavaWebObjects\" bundle";
    /* 127*/ is = com/webobjects/appserver/
    WOResourceManager.getClassLoader().getResourceAsStream((new
    StringBuilder())
                                  .append("com/webobjects/
    appserver/").append(name).toString());
                    }
    /* 129*/ if(is == null) {
    /* 130*/ NSLog.err.appendln((new StringBuilder()).append
    ("<WOResourceManager> ").append(errorCause).toString());
    /* 131*/ throw new IllegalStateException(errorCause);
                    } else {
    /* 133*/ return is;
                    }
                }

    in line 116 NSBundle.bundleForName("JavaWebObjects"); fails because
    in line 527 BundlesNamesTable was empty: {}

    NSBundle:

                public static synchronized NSBundle bundleForName(String
    aName) {
    /* <-MISALIGNED-> */ /* 516*/ NSBundle bundle = null;
    /* <-MISALIGNED-> */ /* 518*/ if(aName != null) {
                        String fixedName;
    /* <-MISALIGNED-> */ /* 521*/ if(aName.endsWith
    (".framework"))
    /* <-MISALIGNED-> */ /* 522*/ fixedName =
    NSPathUtilities.stringByDeletingPathExtension(aName);
    /* <-MISALIGNED-> */ /* 524*/ else
    /* <-MISALIGNED-> */ /* 524*/ fixedName = aName;
    /* <-MISALIGNED-> */ /* 527*/ bundle = (NSBundle)
    BundlesNamesTable.objectForKey(fixedName);
                    }
    /* <-MISALIGNED-> */ /* 530*/ return bundle;
                }

    this in turn was caused by the failure of LoadBundlesFromClassPath()
    during classloading of NSBundle in the static block:

                static {
    .
    .
    .
    /* <-MISALIGNED-> */ /* 349*/ NSArray classpath =
    NSArray._mutableComponentsSeparatedByString((new StringBuilder
    ()).append(System.getProperty("java.class.path")).append
    (File.pathSeparator).append(NSProperties.getProperty
    ("com.webobjects.classpath")).toString(), File.pathSeparator);
    /* <-MISALIGNED-> */ /* 352*/ NSMutableArray
    cleanedUpClassPath = new NSMutableArray();
    /* <-MISALIGNED-> */ /* 353*/ Iterator iterator =
    classpath.iterator();
    /* <-MISALIGNED-> */ /* 353*/ do {
    /* <-MISALIGNED-> */ /* 353*/ if(!iterator.hasNext())
    /* <-MISALIGNED-> */ /* 354*/ break;
    /* <-MISALIGNED-> */ /* 354*/ String fixedComponent =
    NSPathUtilities.stringByNormalizingExistingPath((String)iterator.next
    ());
    /* <-MISALIGNED-> */ /* 355*/ if(fixedComponent !=
    null && fixedComponent.length() > 0)
    /* <-MISALIGNED-> */ /* 356*/
    cleanedUpClassPath.add(fixedComponent);
                        } while(true);
    /* <-MISALIGNED-> */ /* 363*/ for(int i =
    cleanedUpClassPath.count() - 1; i >= 0; i--) {
    /* <-MISALIGNED-> */ /* 364*/ String component =
    (String)cleanedUpClassPath.objectAtIndex(i);
    /* <-MISALIGNED-> */ /* 366*/ if
    (cleanedUpClassPath.indexOfObject(component) != i)
    /* <-MISALIGNED-> */ /* 367*/
    cleanedUpClassPath.removeObjectAtIndex(i);
                        }
    /* <-MISALIGNED-> */ /* 370*/ ClassPath = cleanedUpClassPath;
    /* <-MISALIGNED-> */ /* 373*/ LoadBundlesFromClassPath
    (ClassPath);
    .
    .
    .
                }

    None of the following classpath entries was loaded …

    the value of ClassPath in line 370 was:

    ( C:\Dokumente und Einstellungen\cem\workspace\TankDiskAll
    \Applications\TankDiskServer\build\TankDiskServer.woa\Contents
    \Resources\Java,
    C:\Dokumente und Einstellungen\cem\.m2\repository\com\apple\webobjects
    \JavaXML\5.4.2\JavaXML-5.4.2.jar,
    C:\Dokumente und Einstellungen\cem\.m2\repository\com\apple\webobjects
    \JavaJDBCAdaptor\5.4.2\JavaJDBCAdaptor-5.4.2.jar,
    C:\Dokumente und Einstellungen\cem\.m2\repository\com\apple\webobjects
    \JavaEOAccess\5.4.2\JavaEOAccess-5.4.2.jar,
    C:\Dokumente und Einstellungen\cem\.m2\repository\com\apple\webobjects
    \JavaEOControl\5.4.2\JavaEOControl-5.4.2.jar,
    C:\Dokumente und Einstellungen\cem\.m2\repository\com\apple\webobjects
    \JavaWebObjects\5.4.2\JavaWebObjects-5.4.2.jar,
    C:\Dokumente und Einstellungen\cem\.m2\repository\com\apple\webobjects
    \JavaFoundation\5.4.2\JavaFoundation-5.4.2.jar,
    C:\Dokumente und Einstellungen\cem\.m2\repository\com\apple\webobjects
    \JavaWOExtensions\5.4.2\JavaWOExtensions-5.4.2.jar,
    C:\Dokumente und Einstellungen\cem\.m2\repository\postgresql
    \postgresql\7.4.1-jdbc3\postgresql-7.4.1-jdbc3.jar,
    C:\Dokumente und Einstellungen\cem\.m2\repository\javax\mail\mail
    \1.4.1\mail-1.4.1.jar,
    C:\Dokumente und Einstellungen\cem\.m2\repository\assense\shared
    \PostgreSQLPlugIn\1.5.4\PostgreSQLPlugIn-1.5.4.jar,
    C:\Dokumente und Einstellungen\cem\.m2\repository\javax\activation
    \activation\1.1\activation-1.1.jar )

    … , because the loading of bundles works like this:

    NSBundle:

                private static void LoadBundlesFromClassPath(NSArray
    array) {
    /* <-MISALIGNED-> */ /* 741*/ Enumeration en =
    array.objectEnumerator();
    /* <-MISALIGNED-> */ /* 741*/ do {
    /* <-MISALIGNED-> */ /* 741*/ if(!en.hasMoreElements())
    /* <-MISALIGNED-> */ /* 742*/ break;
    /* <-MISALIGNED-> */ /* 742*/ NSBundle b = null;
    /* <-MISALIGNED-> */ /* 743*/ String nextPathComponent =
    (String)en.nextElement();
    /* <-MISALIGNED-> */ /* 744*/ if(couldBeABundle
    (nextPathComponent))
    /* <-MISALIGNED-> */ /* 745*/ b =
    _bundleWithPathShouldCreateIsJar(nextPathComponent, true, false);
    /* <-MISALIGNED-> */ /* 747*/ if(b != null)
    /* <-MISALIGNED-> */ /* 748*/ b.postNotification();
                    } while(true);
                }

    and the check whether something at the classpath is a bundle or not
    is based on the following code:

    NSBundle:

                private static boolean couldBeABundle(String aPath) {
    /* <-MISALIGNED-> */ /* 586*/ boolean isBundle = false;
    /* <-MISALIGNED-> */ /* 587*/ NSMutableArray resourcesSubdirs
    = new NSMutableArray();
    /* <-MISALIGNED-> */ /* 589*/ int index = aPath.lastIndexOf
    (RSUFFIX);
    /* <-MISALIGNED-> */ /* 591*/ if(index == -1) {
    /* <-MISALIGNED-> */ /* 593*/ resourcesSubdirs.addObject
    (aPath.concat(RSUFFIX)); // Resources
    /* <-MISALIGNED-> */ /* 594*/ resourcesSubdirs.addObject
    (aPath.concat(CSUFFIX)); // Contents
                                          } else {
    /* <-MISALIGNED-> */ /* 596*/ resourcesSubdirs.addObject
    (aPath.substring(0, index + RSUFFIX.length()));
                                          }
    /* <-MISALIGNED-> */ /* 599*/ Iterator iterator =
    resourcesSubdirs.iterator();
    /* <-MISALIGNED-> */ /* 599*/ do {
    /* <-MISALIGNED-> */ /* 599*/ if(!iterator.hasNext())
    /* <-MISALIGNED-> */ /* 600*/ break;
    /* <-MISALIGNED-> */ /* 600*/ File file = new File((String)
    iterator.next());
    /* <-MISALIGNED-> */ /* 601*/ if(!file.exists() || !
    file.isDirectory())
    /* <-MISALIGNED-> */ /* 602*/ continue;
    /* <-MISALIGNED-> */ /* 602*/ String files[] = file.list
    (TheInfoDictFilter); // looking for info.plist named file
    /* <-MISALIGNED-> */ /* 603*/ if(files.length <= 0)
    /* <-MISALIGNED-> */ /* 604*/ continue;
    /* <-MISALIGNED-> */ /* 604*/ isBundle = true;
    /* <-MISALIGNED-> */ /* 605*/ break;
                    } while(true);
    /* <-MISALIGNED-> */ /* 610*/ return isBundle;
                }

    so this code looks for each entry in the classpath if there is a file
    named "info.plist" inside the subdirectories Resources and Resources/
    Contents . If not it isn't considered a bundle.

    is everything clear so far?

    ========================================================================
    ===============

    Because of the failure of NSBundle.bundleForName("JavaWebObjects") in
    line 116 of WOResourceManager, WOResourceManager falls back to the
    following:

                    } else {
    /* 126*/ errorCause = "Unable to locate the
    \"JavaWebObjects\" bundle";
    /* 127*/ is = com/webobjects/appserver/
    WOResourceManager.getClassLoader().getResourceAsStream((new
    StringBuilder())
                                  .append("com/webobjects/
    appserver/").append(name).toString());
                    }

    where it tries to load "com/webobjects/appserver/
    WOPropertyKeys.plist" at the first occasion from any jars in the
    classpath (it looks even in the bootclasspath).

    I found a file (next to several others) inside
    JavaWebObjects-5.4.2.jar, but there in a Folder named "Resources",
    not inside com/webobjects/appserver/

    when trying to load that Resource the something deep inside Java
    Classloading logic tried to open this path:

    \C:\Dokumente und Einstellungen\cem\.m2\repository\com\apple
    \webobjects\JavaWebObjects\5.4.2\JavaWebObjects.jar (note the leading
    backslash and the omission of the version string "-5.4.2") what
    resulted in some FileNotFoundException which was catched by the
    deeper levels of the Classloading logic.

    Because the Classloading logic was also looking inside TankDiskServer
    \build\TankDiskServer.woa\Contents\Resources\Java I just created the
    directory structure "com/webobjects/appserver/" and copied everything
    from inside the "Resource" directory of JavaWebObjects-5.4.2.jar over
    there. Now at least my first exception was gone but the trouble is
    not over yet.

    ========================================================================
    ===============

    now I am getting:

    [2008-10-16 20:25:46 CEST] <main> WebObjects version = Not Available
    [2008-10-16 20:25:46 CEST] <main> NSBundle is unable to find
    JavaWebObjects.framework -- unable to load
    "ExtensionsForResources.plist" from there. Ignoring.
    [2008-10-16 20:25:46 CEST] <main> A fatal exception occurred: null
    [2008-10-16 20:25:46 CEST] <main> java.lang.ExceptionInInitializerError
        at com.webobjects._ideservices._WOProject.ideProjectAtPath
    (_WOProject.java:85)
        at
    com.webobjects.appserver._private.WOProjectBundle._isProjectBundlePath
    (WOProjectBundle.java:225)
        at
    com.webobjects.appserver._private.WODeployedBundle.bundleWithNSBundle
    (WODeployedBundle.java:745)
        at
    com.webobjects.appserver._private.WODeployedBundle.deployedBundle
    (WODeployedBundle.java:124)
        at com.webobjects.appserver.WOResourceManager._initAppBundle
    (WOResourceManager.java:140)
        at com.webobjects.appserver.WOResourceManager.<init>
    (WOResourceManager.java:60)
        at com.webobjects.appserver.WOApplication.createResourceManager
    (WOApplication.java:2067)
        at com.webobjects.appserver.WOApplication.<init>
    (WOApplication.java:841)
        at com.assense.core.wo.AssenseApplication.<init>
    (AssenseApplication.java:25)
        at com.tankdisk.Application.<init>(Application.java:67)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
    Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance
    (NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance
    (DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
        at java.lang.Class.newInstance0(Class.java:350)
        at java.lang.Class.newInstance(Class.java:303)
        at com.webobjects.appserver.WOApplication.main(WOApplication.java:
    547)
        at com.tankdisk.Application.main(Application.java:37)
    Caused by: java.lang.IllegalStateException: Unable to find any
    resource extensions in either JavaWebObjects.framework or the main
    bundle.
        at com.webobjects._ideservices._IDEProjectPBX.<clinit>
    (_IDEProjectPBX.java:183)
        ... 18 more

    >
    >
    >
    > with regards,
    > --
    >
    > Lachlan Deck
    >

    I hope you didn't fall asleep while reading this looooong mail!

    regards,

            Lars



    This archive was generated by hypermail 2.0.0 : Thu Oct 16 2008 - 15:32:46 EDT