Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 370411

Summary: ClassNotFoundException for org/slf4j/LoggerFactory upon Xtext generation
Product: [Modeling] TMF Reporter: Alex Blewitt <alex.blewitt>
Component: XtextAssignee: Project Inbox <tmf.xtext-inbox>
Status: CLOSED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: dennis.huebner, jwbito, lorenzo.bettini, sebastian.zarnekow, sven.efftinge
Version: 2.2.1Flags: sven.efftinge: juno+
Target Milestone: RC1   
Hardware: PC   
OS: Mac OS X - Carbon (unsup.)   
Whiteboard:

Description Alex Blewitt CLA 2012-02-02 04:43:40 EST
I have a stock Eclipse SDK with 3.7.1 installed on my Mac. I was trying the basic tutorial (File -> New Xtend Project) and running the MWE2 workflow for generating the xtext, and I received this error:


1    [main] ERROR mf.mwe2.launch.runtime.Mwe2Launcher  - org/slf4j/LoggerFactory
java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
	at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:156)
	at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:132)
	at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:351)
	at org.eclipse.emf.mwe.utils.StandaloneSetup.<init>(StandaloneSetup.java:91)
	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:513)
	at java.lang.Class.newInstance0(Class.java:355)
	at java.lang.Class.newInstance(Class.java:308)
	at org.eclipse.emf.mwe2.language.factory.Mwe2ExecutionEngine.create(Mwe2ExecutionEngine.java:155)
	at org.eclipse.emf.mwe2.language.factory.Mwe2ExecutionEngine.inCase(Mwe2ExecutionEngine.java:104)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291)
	at org.eclipse.emf.mwe2.language.factory.Mwe2ExecutionEngine.internalSwitch(Mwe2ExecutionEngine.java:66)
	at org.eclipse.emf.mwe2.language.factory.Mwe2ExecutionEngine.internalApplyAssignments(Mwe2ExecutionEngine.java:142)
	at org.eclipse.emf.mwe2.language.factory.Mwe2ExecutionEngine.inCase(Mwe2ExecutionEngine.java:114)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291)
	at org.eclipse.emf.mwe2.language.factory.Mwe2ExecutionEngine.internalSwitch(Mwe2ExecutionEngine.java:66)
	at org.eclipse.emf.mwe2.language.factory.Mwe2ExecutionEngine.inCase(Mwe2ExecutionEngine.java:80)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291)
	at org.eclipse.emf.mwe2.language.factory.Mwe2ExecutionEngine.internalSwitch(Mwe2ExecutionEngine.java:66)
	at org.eclipse.emf.mwe2.language.factory.Mwe2ExecutionEngine.create(Mwe2ExecutionEngine.java:62)
	at org.eclipse.emf.mwe2.launch.runtime.Mwe2Runner.run(Mwe2Runner.java:88)
	at org.eclipse.emf.mwe2.launch.runtime.Mwe2Runner.run(Mwe2Runner.java:73)
	at org.eclipse.emf.mwe2.launch.runtime.Mwe2Runner.run(Mwe2Runner.java:64)
	at org.eclipse.emf.mwe2.launch.runtime.Mwe2Runner.run(Mwe2Runner.java:55)
	at org.eclipse.emf.mwe2.launch.runtime.Mwe2Launcher.run(Mwe2Launcher.java:74)
	at org.eclipse.emf.mwe2.launch.runtime.Mwe2Launcher.main(Mwe2Launcher.java:35)
Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
	at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
	... 40 more

The org.slf4j.LoggerFactory doesn't appear to be present in my runtime:

594	RESOLVED    org.apache.log4j_1.2.15.v201012070815
10	RESOLVED    org.apache.commons.logging_1.0.4.v201101211617

This is using OSX JDK 1.6

java.runtime.version=1.6.0_29-b11-402-11M3527

If I manually add the SLF4J to my classpath then it works. However, there's nothing in the manifest which requires it:


Require-Bundle: org.eclipse.xtext;bundle-version="2.1.0";visibility:=reexport,
 org.eclipse.xtext.xbase;bundle-version="2.1.0";resolution:=optional;visibility:=reexport,
 org.apache.log4j;bundle-version="1.2.15";visibility:=reexport,
 org.apache.commons.logging;bundle-version="1.0.4";resolution:=optional;visibility:=reexport,
 org.eclipse.xtext.generator;resolution:=optional,
 org.eclipse.emf.codegen.ecore;resolution:=optional,
 org.eclipse.emf.mwe.utils;resolution:=optional,
 org.eclipse.emf.mwe2.launch;resolution:=optional,
 org.eclipse.xtext.util,
 org.eclipse.emf.ecore,
 org.eclipse.emf.common,
 org.antlr.runtime,
 org.eclipse.xtext.common.types
Import-Package: org.apache.log4j,
 org.apache.commons.logging,
 org.eclipse.xtext.xbase.lib,
 org.eclipse.xtend2.lib

It should be possible to reproduce this with a clean Eclipse 3.7 install on OSX, Xtext 2.2.1 and ensuring that the org.slf4j isn't in your workspace or in the classpath or OSGi runtime. I suspect either you need to add this as a required package (preferably not require-bundle!) or change the log call in the translation step.
Comment 1 Lorenzo Bettini CLA 2012-05-13 09:52:20 EDT
The same happens with the new

eclipse-SDK-4.2M7-Xtext-2.3.0M7-linux-gtk.tar.gz

from the itemis site
Comment 2 Dennis Huebner CLA 2012-05-14 08:02:48 EDT
(In reply to comment #1)
> The same happens with the new> 
> eclipse-SDK-4.2M7-Xtext-2.3.0M7-linux-gtk.tar.gz
Please describe the steps to follow.

> from the itemis site

I've tried eclipse-SDK-4.2M7-Xtext-2.3.0M7-linux-gtk-x86_64 -> New Xtext project -> run mwe2 workflow and can't reproduce it.

Please note neither Xtext nor mwe2 depends on slf4j implementation of commons logging. However org.slf4j.api_1.6.4.v20120130-2120.jar is shipped with the itemis distro, so NoClassDefFoundError can't occur in this case.
Comment 3 Lorenzo Bettini CLA 2012-05-14 09:32:11 EDT
So I tried again with a fresh install of eclipse-SDK-4.2M7-Xtext-2.3.0M7-linux-gtk-x86 and you're right, the workflow runs fine...

as soon as you install mylyn (I installed some connectors from mylyn) then the problem shows up again...

some mylyn plugins install this plugin

./plugins/org.slf4j.jcl_1.6.4.v20111214-2030.jar

which seems to be the cause of the problem (!?)

manually removing this plugin and restarting eclipse makes the problem go away...
Comment 4 Dennis Huebner CLA 2012-05-15 02:22:38 EDT
(In reply to comment #3)
> some mylyn plugins install this plugin
> 
> ./plugins/org.slf4j.jcl_1.6.4.v20111214-2030.jar
> 
... its org.apache.httpcomponents.httpclient which is required by org.eclipse.mylyn.commons.repositories.http.core and org.eclipse.mylyn.hudson.core.

> which seems to be the cause of the problem (!?)
Yes, you are right. 
org.apache.httpcomponents.httpclient depends on org.apache.commons.logging;version="1.1.1" this package is exported by org.slf4j.jcl_1.6.4.v20111214-2030 so slf4j.jcl became installed and loaded. slf4j.jcl also register o.a.c.logging.LogFactory service as org.apache.commons.logging.impl.SLF4JLogFactory. This class tries to load org/slf4j/LoggerFactory, loading fails because of missing package import org.slf4j;version=1.6.4 :(
Comment 5 Sven Efftinge CLA 2012-05-15 03:15:04 EDT
So the problem is, that the java class path is configured using PDE and PDE doesn't resolve transitive import package declarations. 

I think as long as we start the MWE workflow in a vanilla Java process we'll have to make sure that org.sl4j is pulled in somehow if present (i.e. optional require-bundle or package import).
Comment 6 Dennis Huebner CLA 2012-05-15 03:41:40 EDT
(In reply to comment #5)
> So the problem is, that the java class path is configured using PDE and PDE
> doesn't resolve transitive import package declarations. 
> 
Yes.
> I think as long as we start the MWE workflow in a vanilla Java process we'll
> have to make sure that org.sl4j is pulled in somehow if present (i.e. optional
> require-bundle or package import).
I think, we better must prevent that org.slf4j.jcl is automatically loaded if org.apache.commons.logging is available.  In my test environment, replacing org.apache.commons.logging package import with an optional bundle dependency does the trick.
In the common case, mwe2 container project uses org.apache.commons.logging, if one (e.g. Knut :)  would like to work with slf4j it can be configured with the corresponding package import org.apache.commons.logging;version="1.1.1",org.slf4j;version="1.6.4"
Comment 7 Sebastian Zarnekow CLA 2012-05-15 03:44:18 EDT
Please note that one has to provide additional information in order to configure logging via slf4j properly. Dennis' tests revealed that you'd have to make e.g. logback available along with slf4j to get it right whereas the simple optional bundle dep on commons.logging did the trick with much less effort for the common cases.
Comment 8 Alex Blewitt CLA 2012-05-15 04:45:37 EDT
(In reply to comment #5)
> So the problem is, that the java class path is configured using PDE and PDE
> doesn't resolve transitive import package declarations. 

Just a quick note - OSGi does not say anything about transitive dependencies being made avaialble on the classpath, and indeed, shouldn't do. If I import A, and A imports B, I shouldn't have a dependency on B.

If you use Require-Bundle and the 'visibility:=reexport' then it's possible to expose the transitive dependency set to the client.

http://eclipsesource.com/blogs/2008/08/22/tip-split-packages-and-visibility/

but the key premise here is that the dependency set is known (and described properly) by the bundles in question. Unfortunately for the org.slf4j.jcl bundle this does not appear to be the case.

It might be worth raising the issue with the Mylyn team as they may know of a fix, or may be able to stop bundling the SLF4J implementation. Many OSGi users are moving over to use PAX Logging instead (which again provides an interface for Log4J but does so in a slightly more sane way).
Comment 9 Dennis Huebner CLA 2012-05-15 05:28:58 EDT
Found a related bug 339004. Bugfix already introduced bundle requirement to o.a.commons.logging but was removed for unknown reasons (twice!). We really have to use commit message to describe why something was changed. "removed xyz dependency" as commit comment is not enough, everybody can see that xyz dependency was removed, at least in the diff view, but nobody knows why... Note to me: The best reference is a bugzilla bug report.  :p
Comment 10 Dennis Huebner CLA 2012-05-15 07:13:32 EDT
Fix was pushed to master
Comment 11 John Bito CLA 2012-07-23 12:20:08 EDT
When Xtext 2.3.0.v201206120633 is installed from the Juno update site into the Ecipse IDE for Java (http://www.eclipse.org/downloads/packages/eclipse-ide-java-developers/junor), the same exception stops Xtext generation. (The generation succeeds when running the Eclipse distribution that includes Xtext from http://www.eclipse.org/Xtext/download.html).

Is this a new bug?
Comment 12 Sebastian Zarnekow CLA 2012-07-23 13:36:04 EDT
You have to make sure that you don't use SLF4J but log4j instead or configure SLF4J for the Xtext project properly. The easiest way is to use require-bundle for log4j v1.2.15
Comment 13 John Bito CLA 2012-07-23 16:58:11 EDT
Thanks Sebastian, but I don't where my code is involved in the bundle configuration when invoking org.eclipse.xtext.generator.Generator. The exception occurs when I run the mwe2 script to create the Xtext artifacts. Is there a way to configure the Mwe2Launcher with the require-bundle?

I was under the impression the require-bundle is in the XText plugin. I was guessing that the mwe2 invocation doesn't pick up the configuration that's specified in the plugin (though that's only from reading this bug - I haven't looked at where the bundles are specified and loaded when running with the Java IDE).

If there's a way to change the way the dependencies are resolved when the mwe2 script is run, I'll give it a try, but it would be good if XText could work when installed from the update site into the Java IDE.

(I originally asked about this in the e-mail list: http://www.eclipse.org/forums/index.php/t/367736/ )
Comment 14 Sebastian Zarnekow CLA 2012-07-23 17:01:39 EDT
(In reply to comment #13)
> Thanks Sebastian, but I don't where my code is involved in the bundle
> configuration when invoking org.eclipse.xtext.generator.Generator. The
> exception occurs when I run the mwe2 script to create the Xtext artifacts. Is
> there a way to configure the Mwe2Launcher with the require-bundle?
> 
> I was under the impression the require-bundle is in the XText plugin. I was
> guessing that the mwe2 invocation doesn't pick up the configuration that's
> specified in the plugin (though that's only from reading this bug - I haven't
> looked at where the bundles are specified and loaded when running with the Java
> IDE).
> 
> If there's a way to change the way the dependencies are resolved when the mwe2
> script is run, I'll give it a try, but it would be good if XText could work
> when installed from the update site into the Java IDE.
> 
> (I originally asked about this in the e-mail list:
> http://www.eclipse.org/forums/index.php/t/367736/ )

Hi John,

mwe2 launch configs fully rely on the Java classpath that is configured for the project that contains the workflow. If you add a bundle dep, that will be reflected in the mwe2 launch classpath. The plugin deps container does not follow transitive import-package entries in the manifest thus a plain import-package for apache.log4j will not necessarily pick up the required bundles. If slf4j is selected, other import-package clauses in that bundle will not necessarily be used thus you end up with a NoClassDefFound. All these things work like a charm with require-bundle so I recommend to use that one.

Hope that helps,
Sebastian
Comment 15 John Bito CLA 2012-07-23 21:22:14 EDT
Thanks again, Sebastian! There must be something that I'm missing. The MANIFEST.MF for my plugin (copied below) includes log4j in its Require-Bundle header. Is that not the correct way to manipulate the project classpath with respect to OSGi bundles? Is there a way to see what OSGi configuration is used to assemble the classpath for the mwe2 launch? 

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: com.bobberinteractive.lang
Bundle-Vendor: Bobber Interactive Corp.
Bundle-Version: 1.0.1
Bundle-SymbolicName: com.bobberinteractive.lang; singleton:=true
Bundle-ActivationPolicy: lazy
Require-Bundle: org.eclipse.xtext;bundle-version="2.3.0";visibility:=reexport,
 org.apache.log4j;bundle-version="1.2.15";visibility:=reexport,
 org.apache.commons.logging;bundle-version="1.0.4";resolution:=optional;visibility:=reexport,
 org.eclipse.xtext.generator;resolution:=optional,
 org.eclipse.emf.codegen.ecore;resolution:=optional,
 org.eclipse.emf.mwe.utils;resolution:=optional,
 org.eclipse.emf.mwe2.launch;resolution:=optional,
 org.eclipse.xtext.util,
 org.eclipse.emf.ecore,
 org.eclipse.emf.common,
 org.antlr.runtime,
 org.eclipse.xtext.common.types,
 org.codehaus.groovy;bundle-version="1.8.6"
Import-Package: org.apache.commons.logging,
 org.apache.log4j
Bundle-RequiredExecutionEnvironment: JavaSE-1.6,J2SE-1.5
Export-Package: com.bobberinteractive.lang,
 com.bobberinteractive.lang.services,
 com.bobberinteractive.lang.serializer,
 com.bobberinteractive.lang.parser.antlr,
 com.bobberinteractive.lang.parser.antlr.internal,
 com.bobberinteractive.lang.validation,
 com.bobberinteractive.lang.scoping,
 com.bobberinteractive.lang.generator,
 com.bobberinteractive.lang.formatting,
 com.bobberinteractive.lang.flow,
 com.bobberinteractive.lang.flow.impl,
 com.bobberinteractive.lang.flow.util
Comment 16 Sebastian Zarnekow CLA 2012-07-24 02:29:59 EDT
(In reply to comment #15)
> Import-Package: org.apache.commons.logging,
>  org.apache.log4j

Hi John,

the import package thing seems to confuse the dep resolution. You could try to remove the package import for org.apache.commons.logging or use an explicit version in the package import.

Sorry, my comment #14 referred to log4j whereas the error message indicates a problem with commons.logging. But the issue should be the same.
Comment 17 John Bito CLA 2012-07-24 11:54:58 EDT
Thanks for helping, Sebastian: that got it working! I guess I had o.a.c.logging
in the Import-Package from some earlier effort. It didn't occur to me that the
import of o.a.c.logging would result in the attempt to load slf4j (when
Require-Bundle doesn't have that effect).
Comment 18 Eclipse Webmaster CLA 2017-10-31 11:06:49 EDT
Requested via bug 522520.

-M.
Comment 19 Eclipse Webmaster CLA 2017-10-31 11:18:14 EDT
Requested via bug 522520.

-M.