wocommunity / wolips

wolips
53 stars 53 forks source link

There was no valid EOF ClassLoader factory defined. #157

Closed rgurley closed 2 years ago

rgurley commented 3 years ago

On Eclipse 2021-06, opening the SQLGenerator dialog gives me,

org.objectstyle.wolips.eomodeler.core.model.EOModelException: There was no valid EOF ClassLoader factory defined.
    at org.objectstyle.wolips.eomodeler.core.model.IEOClassLoaderFactory$Utility.createClassLoader(IEOClassLoaderFactory.java:56)
    at org.objectstyle.wolips.eomodeler.actions.GenerateSQLDialog.getEOModelClassLoader(GenerateSQLDialog.java:257)
    at org.objectstyle.wolips.eomodeler.actions.GenerateSQLDialog.generateSql(GenerateSQLDialog.java:297)
    at org.objectstyle.wolips.eomodeler.actions.GenerateSQLDialog$1.run(GenerateSQLDialog.java:279)
    at java.base/java.lang.Thread.run(Thread.java:831)

The reverse generation tool gives me the same message in a dialog, but with a different stack trace,

org.objectstyle.wolips.eomodeler.core.model.EOModelException: There was no valid EOF ClassLoader factory defined.
    at org.objectstyle.wolips.eomodeler.core.model.IEOClassLoaderFactory$Utility.createClassLoader(IEOClassLoaderFactory.java:56)
    at org.objectstyle.wolips.eomodeler.actions.ReverseEngineerAction.run(ReverseEngineerAction.java:85)
    at org.eclipse.ui.internal.PluginAction.runWithEvent(PluginAction.java:239)
    at org.eclipse.ui.internal.WWinPluginAction.runWithEvent(WWinPluginAction.java:218)
    at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:580)
    at org.eclipse.jface.action.ActionContributionItem.lambda$5(ActionContributionItem.java:453)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
    at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4441)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1512)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1535)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1520)
    at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1324)
    at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4227)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3837)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1157)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1046)
    at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
    at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:644)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
    at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:551)
    at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:156)
    at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:152)
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:654)
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:591)
    at org.eclipse.equinox.launcher.Main.run(Main.java:1462)
hprange commented 3 years ago

@rgurley can you tell us which OS, JDBC Adaptor, and driver you're using? One of my co-workers has the same issue when generating SQL from EntityModeler on Linux. The same project works for me on Mac OS. We're using the Derby plug-in with the EmbeddedDriver.

rgurley commented 3 years ago

In this case, I believe it was big sur, postgresql. I get those on a M1 MBA, but a colleague also has the problem on a new intel MBP. I also tried on linux, and perhaps this is a different issue, because it didn't work due to a class not found on NSDictionary. I haven't had much time to dig into why it fails since trying it.

nullterminated commented 3 years ago

On my linux box, I get,

java.lang.NoClassDefFoundError: com/webobjects/foundation/NSDictionary
    at org.objectstyle.wolips.eomodeler.core.sql.EOFSQLReverseEngineer53.<init>(EOFSQLReverseEngineer53.java:27)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:78)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
    at org.objectstyle.wolips.eomodeler.core.sql.EOFSQLReverseEngineerFactory.reverseEngineer(EOFSQLReverseEngineerFactory.java:18)
    at org.objectstyle.wolips.eomodeler.actions.ReverseEngineerAction.run(ReverseEngineerAction.java:86)
    at org.eclipse.ui.internal.PluginAction.runWithEvent(PluginAction.java:239)
    at org.eclipse.ui.internal.WWinPluginAction.runWithEvent(WWinPluginAction.java:218)
    at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:580)
    at org.eclipse.jface.action.ActionContributionItem.lambda$5(ActionContributionItem.java:453)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
    at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5879)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1427)
    at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:5121)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4599)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1157)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1046)
    at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
    at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:644)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
    at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:551)
    at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:156)
    at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:152)
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:654)
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:591)
    at org.eclipse.equinox.launcher.Main.run(Main.java:1462)
    at org.eclipse.equinox.launcher.Main.main(Main.java:1435)
Caused by: java.lang.ClassNotFoundException: com.webobjects.foundation.NSDictionary
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:433)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:586)
    at java.base/java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:852)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:519)
    ... 39 more

And wolips properties looking like,

#Tue Aug 24 20:30:00 JST 2021
wo.system.frameworks=/opt/WebObjects54/Library/Frameworks
wo.bootstrapjar=/System/Library/WebObjects/JavaApplications/wotaskd.woa/WOBootstrap.jar
wo.extensions=/opt/WebObjects54/Local/Library/WebObjects/Extensions
wolips.properties=wolips.properties
wo.system.root=/opt/WebObjects54/
wo.user.frameworks=/home/myuser/Library/Frameworks
wo.local.root=/opt/WebObjects54/Local/
wo.apps.root=/opt/WebObjects54/Local/Library/WebObjects/Applications
wo.api.root=/Developer/Documentation/DocSets/com.apple.ADC_Reference_Library.WebObjectsReference.docset/Contents/Resources/Documents/documentation/InternetWeb/Reference/WO542Reference
wo.local.frameworks=/opt/WebObjects54/Local/Library/Frameworks
wo.network.root=/Network
wo.network.frameworks=/Network/Library/Frameworks
wo.user.root=/home/myuser

I'll see if I can figure out how to get a wolips dev environment set up again to find the problem.

nullterminated commented 3 years ago

So far what I've found is that in the case of a maven project at least, it is not finding the WO frameworks. They must be included on the Eclipse build path. When I add

Then I get a different error, with the root cause being,

Caused by: java.lang.IllegalStateException: Unable to get the name of the class to instantiate for the adaptor framework JavaJDBCAdaptor. The possible causes for this error are: the adaptor framework is not installed on your system, the adaptor framework is not linked into your application, or the info dictionary for this adaptor is corrupted.
    at com.webobjects.eoaccess.EOAdaptor.classForAdaptorNamed(EOAdaptor.java:264)
    at com.webobjects.eoaccess.EOAdaptor.adaptorWithName(EOAdaptor.java:287)
    at org.objectstyle.wolips.eomodeler.core.sql.EOFSQLReverseEngineer53.<init>(EOFSQLReverseEngineer53.java:28)
    ... 37 more
nullterminated commented 3 years ago

And this happens, because line 527 of NSBundle calls BundlesNamesTable.objectForKey("JavaJDBCAdaptor") and returns null because BundlesNamesTable is an empty NSMutableDictionary {}

nullterminated commented 3 years ago

It appears NSBundle.CreateBundleWithPath() is the only thing that populates that private static final dict. That is called by NSBundle._bundleWithPathShouldCreateIsJar() which is public, but I can't open call hierarchy on it. I can see that is called inside NSBundle by

I assume one of these should be called by WOLips to populate the dict, but maybe they're called indirectly via some other WO methods... When I search my WOLips workspace, I don't see any of these 5 called anywhere. When I set a breakpoint in CreateBundleWithPath, it never stops.

nullterminated commented 3 years ago

InitMainBundle, LoadBundlesFromJars, LoadBundlesFromClassPath are all private and called in the static initializer. Perhaps it is failing somewhere here.

nullterminated commented 3 years ago

At NSBundle:331 FactoryURLClassLoader.getResources("Resources/Info.plist") returns an enumeration where hasNextElement is false. From there LoadBundlesFromJars is called with an empty urlArray, when it seems like it should be an array of WO jars on the classpath for the WOLips plugin. I can see them under Referenced Libraries and they do have a Resources/Info.plist file in the org.objectstyle.wolips.eomodeler as well as the org.objectstyle.wolips.eomodeler.core project.

nullterminated commented 3 years ago

As for LoadBundlesFromClassPath, the static initializer is arriving at an array of

( /opt/eclipse/plugins/org.eclipse.equinox.launcher_1.6.200.v20210416-2027.jar, , /lib/EOFSQLUtils.jar )

But the cleaned up classpath only contains the first entry. It seems like this should contain the frameworks if it were to load them.

InitMainBundle doesn't seem like the correct place to load the WO frameworks, just based on the name...

nullterminated commented 3 years ago

Summary so far, It seems like there are two separate problems here. One is the entity modeler should be looking for WO frameworks on the plugin classpath, not the project classpath. Two is the fact that those frameworks are not loading when NSBundle loads. Maybe the first is supposed to be that way to find database specific adaptors though.

Wolfy42 commented 3 years ago

I expect that this is all related to the Classloader-Workaround because of the NextStep-Classes which are used by the SQL-Generator-Tool. An explanation about the current workaround is here: https://github.com/wocommunity/wolips/pull/116

Short version of it: The SQL-Generator-Tool needs the WO-Jars. But due to the licence-problem that they cannot be shipped with the WOLips-Tool. To circumvent this some classpath-workaround is used. Based on your description this workaround seems to have a problem in your setup

nullterminated commented 3 years ago

I've tracked the origin of the classloader that comes up empty handed at NSBundle:331 down to org.objectstyle.wolips.eomodeler.core.model.IEOClassLoaderFactory.Utility.createClassLoader(). It seems like if I can help this classloader find the WO jars, then it may fix the problem.

nullterminated commented 3 years ago

While stepping through with a debugger last night I noticed the classpath loading branched on whether or not the jvm is modular. It made me think that maybe this issue is related to the jigsaw modulepath stuff from Java 9. I installed jdk8 and added that to my installed JREs in eclipse, then in the pom, set the target/source to 8 and the classloader could now find all the woframework jars in my .m2/repository. I still get a "could not find a suitable driver for jdbc:postgres..." but the main problem with wo jars being missing went away. I could clear them off the eclipse build path as they were no longer needed there either. I need to step through with the debugger and see how it is working with 8 and then try to find a way to make it work with latest java.

nullterminated commented 2 years ago

I believe I've found and fixed the cause of the issue. See https://github.com/wocommunity/wolips/pull/158

nullterminated commented 2 years ago

merged pr