Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

There was no valid EOF ClassLoader factory defined. #157

Closed
rgurley opened this issue Aug 19, 2021 · 15 comments
Closed

There was no valid EOF ClassLoader factory defined. #157

rgurley opened this issue Aug 19, 2021 · 15 comments

Comments

@rgurley
Copy link

rgurley commented Aug 19, 2021

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
Copy link
Contributor

hprange commented Aug 23, 2021

@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
Copy link
Author

rgurley commented Aug 23, 2021

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
Copy link
Member

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
Copy link
Member

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

  • JavaJDBCAdaptor
  • JavaEOControl
  • JavaEOAccess
  • JavaFoundation

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
Copy link
Member

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

@nullterminated
Copy link
Member

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

  • BundleWithPath
  • InitMainBundle
  • LoadBundlesFromJars
  • LoadBundlesFromClassPath

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
Copy link
Member

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

@nullterminated
Copy link
Member

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
Copy link
Member

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
Copy link
Member

nullterminated commented Oct 10, 2021

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
Copy link
Contributor

Wolfy42 commented Oct 10, 2021

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: #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
Copy link
Member

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
Copy link
Member

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
Copy link
Member

I believe I've found and fixed the cause of the issue. See #158

@nullterminated
Copy link
Member

merged pr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants