WOLips adds a WOApplication launch type to Eclipse. If your application is built with Maven, don't use it: launch it as an ordinary Java Application with one VM argument added. You get the classpath Maven would give you, a debugger that reads the right code, and no dependency on a plugin.

This has been the recommendation since WOLips issue 153 in 2022. Recipe first, reasons after, from the WOLips, m2e and Eclipse sources.

1. The recipe

Right-click the class with the main method, usually Application, and choose Run As → Java Application. Then open the configuration it created, under Run → Run Configurations…, and check three things on the Arguments tab:

  • VM arguments: -DNSProjectBundleEnabled=true. Tells the frameworks the application runs from its project folder, so components and resources are read from there and a saved template is live without a build. wonder-slim sets it itself when it finds build.properties; Wonder and plain WebObjects need it set.
  • Program arguments: whatever you had on the launcher's WO Arguments tab, for example -WOPort 1200 -WOAutoOpenInBrowser false. Without a port, WebObjects picks a free one each time.
  • Working directory: leave it at Default, which is the project folder. The 2022 instructions set ${working_dir_loc_WOLips:MyApp}; for a Maven project that resolves to the same folder, but needs WOLips. ${workspace_loc:MyApp} is the explicit form without it.

Save, run or debug.

JDK arguments. HotswapAgent arguments usually belong on the JDK definition, not on each launch configuration. See the development setup guide.

2. What the WOApplication launcher did for you

  • Arguments. It appended a few dozen -WO… arguments from the WOLips preferences, mostly WebObjects' defaults restated, plus -DNSProjectBundleEnabled=true, -DWOUserDirectory, -WOApplicationClassName and -DNSProjectSearchPath. With project bundles on, the first is the only one that matters.
  • Tabs. WO Arguments becomes the plain program arguments box. Debug groups wrote -DNSDebugGroups=(…); write it yourself. Browser opened the application's URL; -WOAutoOpenInBrowser true has WebObjects do that.

Nothing else is lost. Rapid turnaround and templates read from the project are the frameworks' doing, not the launcher's.

3. Why: how Eclipse builds a launch classpath

The classpath Eclipse hands the JVM is computed by a classpath provider named in the launch configuration. The default provider walks the project's build path as the IDE sees it: output folder, libraries, containers, and every referenced project expanded the same way.

For a Maven project that's wrong, because the build path isn't the runtime classpath: the Maven Dependencies container holds everything the project can compile against, test scope included. So m2e has its own provider, which asks Maven instead: the resolved dependencies for the launched scope, exclusions applied, one version of each library. m2e installs it, with a matching source path provider for the debugger, on exactly three configuration types: Java Application, JUnit and TestNG (MavenRuntimeClasspathProvider, MavenLaunchConfigurationListener).

WOApplication isn't one of them, and WOLips wouldn't allow it anyway: its launch delegate writes its own WORuntimeClasspathProvider into every configuration, and puts it back before each launch if it's missing. For a Maven project that provider is Eclipse's default one: it resolves the build path, and Maven's resolution never runs.

4. The three symptoms

Test scope on the runtime classpath. The container's test-scoped entries are marked as such, and Eclipse drops them only when the configuration says exclude test code. Eclipse sets that flag when it creates a Java Application configuration for a non-test main class; WOLips' shortcut doesn't. Workaround within the old launcher: the Exclude test code checkbox on the Classpath tab.

Exclusions ignored, two versions of a library. This needs a framework of yours open in the workspace. m2e puts that project into the application's container in place of its jar, and Eclipse expands it like the launched project: output folder plus its whole build path, including its Maven Dependencies container. That is the framework's own resolution, from its own pom, knowing nothing of the application's exclusions or chosen versions, spliced in where the framework sits, with only exact duplicates dropped. A library you excluded is back; a library you pinned is there twice, the framework's older copy possibly first. The code is DefaultProjectClasspathEntry, which includes a referenced project's non-exported entries by default. m2e's provider adds the project's classes and skips its container, since the application's resolution already covers it.

With every dependency coming from a jar, you get the first symptom only. Open one framework in the workspace and you get all three.

Not what the build produces. Maven, and so the deployed application, uses Maven's resolution. The classpath you develop against has more on it, and a library present in Eclipse but absent on the server is found on the server.

5. Debugging

Source lookup is a second computation, by the configuration's source path provider. m2e's comes with its classpath provider, for the same three types; a WOApplication configuration gets Eclipse's default, which mirrors the classpath above, duplicates included.

The JVM loads a class from the first jar on the classpath that has it. The debugger shows the first jar on the lookup path that has sources for it. With one version of a library those agree. With two: if the loaded copy has no sources attached and the other does, you step through the other version and lines stop matching; if neither has, Source not found. That's the mechanism the code supports, consistent with what people have seen, not a bug reproduced step by step.

6. Good to know

  • Swapping only the provider doesn't work. Pointing a WOApplication configuration at m2e's provider gives the right classpath, but the application then fails to find some of its own classes, Main and DirectAction among them. Not chased down; a Java Application launch simply works.
  • Existing configurations. Nothing to convert. Make a Java Application configuration, copy over your arguments, delete the WOApplication one.
  • Entity Modeler loads your model's classes for SQL generation through the same WOLips classpath computation. Usually harmless, but if it picks up a surprising class, this is why.
  • Ant projects have no Maven resolution to miss. The WOApplication launcher is still the way to run them.
  • ng-objects applications are plain Java applications from the start. Nothing to set.