Can't start RCP application due to OSGi bundle dependency issue
Asked Answered
M

2

6

We are using both spring-web and spring-websocket in our RCP application, which are both converted into bundles through the p2-maven-plugin. Below is the MANIFEST.MF file of our application.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Todo
Bundle-SymbolicName: com.example.e4.rcp.todo;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: EXAMPLE
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Require-Bundle: org.apache.commons.logging;bundle-version="1.2.0",
 org.springframework.spring-aop;bundle-version="4.3.3",
 org.springframework.spring-beans;bundle-version="4.3.3",
 org.springframework.spring-context;bundle-version="4.3.3",
 org.springframework.spring-core;bundle-version="4.3.3",
 org.springframework.spring-expression;bundle-version="4.3.3",
 org.springframework.spring-web;bundle-version="4.3.3",
 org.eclipse.e4.ui.css.swt;bundle-version="0.12.0",
 org.eclipse.e4.ui.css.swt.theme;bundle-version="0.10.0",
 org.eclipse.e4.ui.workbench.addons.swt;bundle-version="1.2.0",
 org.eclipse.e4.ui.workbench.renderers.swt;bundle-version="0.13.0",
 org.eclipse.e4.ui.workbench.swt;bundle-version="0.13.0",
 org.eclipse.swt;bundle-version="3.104.1",
 org.eclipse.e4.ui.di;bundle-version="1.1.0",
 org.eclipse.e4.core.services;bundle-version="2.0.100",
 org.eclipse.osgi.services;bundle-version="3.5.100",
 org.eclipse.e4.core.di.annotations;bundle-version="1.5.0",
 org.springframework.spring-websocket;bundle-version="4.3.2",
 org.springframework.spring-messaging;bundle-version="4.3.2",
 javax.inject;bundle-version="1.0.0",
 javax.annotation;bundle-version="1.2.0",
 org.apache.tomcat.embed.tomcat-embed-core;bundle-version="8.5.4",
 org.apache.tomcat.embed.tomcat-embed-websocket;bundle-version="8.5.4"

When I start the application, it popups the following error:

 !SESSION 2016-11-10 09:48:03.750 -----------------------------------------------
 eclipse.buildId=unknown
 java.version=1.8.0_101
 java.vendor=Oracle Corporation
 BootLoader constants: OS=win32, ARCH=x86_64, WS=win32, NL=en_US
 Framework arguments:  -product com.example.e4.rcp.todo.product clearPersistedState
 Command-line arguments:  -product com.example.e4.rcp.todo.product -data > :\Users\wangzen\Console_prototype/../runtime-todo.product -dev > ile:C:/Users/wangzen/Console_prototype/.metadata/.plugins/org.eclipse.pde.core/to> o.product/dev.properties -os win32 -ws win32 -arch x86_64 -consoleLog > clearPersistedState

 !ENTRY org.eclipse.equinox.app 0 0 2016-11-10 09:48:04.703
 !MESSAGE Product com.example.e4.rcp.todo.product could not be found.

 !ENTRY com.example.e4.rcp.todo 2 0 2016-11-10 09:48:04.786
 !MESSAGE Could not resolve module: com.example.e4.rcp.todo [491]
   Bundle was not resolved because of a uses contraint violation.
   org.osgi.service.resolver.ResolutionException: Uses constraint violation. nable>  to resolve resource com.example.e4.rcp.todo [osgi.identity;>  sgi.identity="com.example.e4.rcp.todo"; type="osgi.bundle";>  ersion:Version="1.0.0.qualifier"; singleton:="true"] because it is exposed to>  ackage 'javax.servlet' from resources rg.apache.tomcat.embed.tomcat-embed-core>  [osgi.identity; type="osgi.bundle"; ersion:Version="8.5.4";>  sgi.identity="org.apache.tomcat.embed.tomcat-embed-core"] and javax.servlet>  osgi.identity; type="osgi.bundle"; version:Version="3.1.0.v201410161800";>  sgi.identity="javax.servlet"] via two dependency chains.

 Chain 1:
   com.example.e4.rcp.todo [osgi.identity; sgi.identity="com.example.e4.rcp.todo";>  type="osgi.bundle"; ersion:Version="1.0.0.qualifier"; singleton:="true"]
     require:>  &(osgi.wiring.bundle=org.apache.tomcat.embed.tomcat-embed-core)(bundle-versio> >=8.5.4))
      |
     provide: osgi.wiring.bundle: org.apache.tomcat.embed.tomcat-embed-core
   org.apache.tomcat.embed.tomcat-embed-core [osgi.identity; ype="osgi.bundle";>  version:Version="8.5.4";>  sgi.identity="org.apache.tomcat.embed.tomcat-embed-core"]

 Chain 2:
   com.example.e4.rcp.todo [osgi.identity; sgi.identity="com.example.e4.rcp.todo";>  type="osgi.bundle"; ersion:Version="1.0.0.qualifier"; singleton:="true"]
     require:>  &(osgi.wiring.bundle=org.springframework.spring-web)(bundle-version>=4.3.3))
      |
     provide: osgi.wiring.bundle; bundle-version:Version="4.3.3.RELEASE";>  sgi.wiring.bundle="org.springframework.spring-web"
   org.springframework.spring-web [osgi.identity; type="osgi.bundle";>  ersion:Version="4.3.3.RELEASE"; osgi.identity="org.springframework.spring-web"]
     import: (osgi.wiring.package=javax.servlet)
      |
     export: osgi.wiring.package: javax.servlet
   javax.servlet [osgi.identity; type="osgi.bundle";>  ersion:Version="3.1.0.v201410161800"; osgi.identity="javax.servlet"]

 !ENTRY org.eclipse.osgi 4 0 2016-11-10 09:48:04.787
 !MESSAGE Application error
!STACK 1
java.lang.RuntimeException: No application id has been found.
    at org.eclipse.equinox.internal.app.EclipseAppContainer.startDefaultApp(EclipseAppContainer.java:242)
    at org.eclipse.equinox.internal.app.MainApplicationLauncher.run(MainApplicationLauncher.java:29)
    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:388)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:243)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:673)
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:610)
    at org.eclipse.equinox.launcher.Main.run(Main.java:1519)
    at org.eclipse.equinox.launcher.Main.main(Main.java:1492)
gogo: InterruptedException: sleep interrupted
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at org.apache.felix.gogo.shell.Activator.run(Activator.java:72)
    at java.lang.Thread.run(Thread.java:745)
An error has occurred. See the log file
C:\Users\wangzen\runtime-todo.product\.metadata\.log.

It seems the problem is caused by both org.apache.tomcat.embed.tomcat-embed-core and org.springframework.spring-web have dependency chain to javax.servlet. However after I removed the tomcat libraries, it tells me another error as below:

java.lang.NoClassDefFoundError: org/apache/tomcat/InstanceManagerBindings
    at org.apache.tomcat.websocket.WsSession.<init>(WsSession.java:187)
    at org.apache.tomcat.websocket.WsWebSocketContainer.connectToServer(WsWebSocketContainer.java:403)
    at org.springframework.web.socket.client.standard.StandardWebSocketClient$1.call(StandardWebSocketClient.java:150)
    at org.springframework.web.socket.client.standard.StandardWebSocketClient$1.call(StandardWebSocketClient.java:147)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: org.apache.tomcat.InstanceManagerBindings cannot be found by org.apache.tomcat.embed.tomcat-embed-websocket_8.5.4
    at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:448)
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:361)
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:353)
    at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:161)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

UPDATE

What I've tried:

  • By checking the dependencies from Plug-in Dependencies tool offered by Eclipse, which shows as following screenshot, I found that org.apache.tomcat.embed.tomcat-embed-core and org.apache.tomcat.embed.tomcat-embed-websocket might not be necessary for my application, so I removed these two bundles and restart my application.

enter image description here

However there comes another error message as below:

java.lang.NoClassDefFoundError: org/apache/tomcat/InstanceManagerBindings
    at org.apache.tomcat.websocket.WsSession.<init>(WsSession.java:187)
    at org.apache.tomcat.websocket.WsWebSocketContainer.connectToServer(WsWebSocketContainer.java:403)
    at org.springframework.web.socket.client.standard.StandardWebSocketClient$1.call(StandardWebSocketClient.java:150)
    at org.springframework.web.socket.client.standard.StandardWebSocketClient$1.call(StandardWebSocketClient.java:147)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: org.apache.tomcat.InstanceManagerBindings cannot be found by org.apache.tomcat.embed.tomcat-embed-websocket_8.5.4
    at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:448)
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:361)
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:353)
    at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:161)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 6 more
  • Also I tried replacing Require-Bundle with Import-Package when importing these third party libraries as following:

    Manifest-Version: 1.0
    Bundle-ManifestVersion: 2
    Bundle-Name: Todo
    Bundle-SymbolicName: com.example.e4.rcp.todo;singleton:=true
    Bundle-Version: 1.0.0.qualifier
    Bundle-Vendor: EXAMPLE
    Bundle-RequiredExecutionEnvironment: JavaSE-1.8
    Require-Bundle: org.eclipse.e4.ui.css.swt;bundle-version="0.12.0",
     org.eclipse.e4.ui.css.swt.theme;bundle-version="0.10.0",
     org.eclipse.e4.ui.workbench.addons.swt;bundle-version="1.2.0",
     org.eclipse.e4.ui.workbench.renderers.swt;bundle-version="0.13.0",
     org.eclipse.e4.ui.workbench.swt;bundle-version="0.13.0",
     org.eclipse.swt;bundle-version="3.104.1",
     org.eclipse.e4.ui.di;bundle-version="1.1.0",
     org.eclipse.e4.core.services;bundle-version="2.0.100",
     org.eclipse.osgi.services;bundle-version="3.5.100",
     org.eclipse.e4.core.di.annotations;bundle-version="1.5.0",
     javax.inject;bundle-version="1.0.0",
     javax.annotation;bundle-version="1.2.0"
    Import-Package: org.apache.tomcat,
     org.springframework.http,
     org.springframework.http.client,
     org.springframework.http.client.support,
     org.springframework.messaging.converter,
     org.springframework.messaging.simp.stomp,
     org.springframework.scheduling,
     org.springframework.scheduling.concurrent,
     org.springframework.util,
     org.springframework.web.client,
     org.springframework.web.socket.client,
     org.springframework.web.socket.client.standard,
     org.springframework.web.socket.messaging,
     org.springframework.web.socket.sockjs.client
    

However it still popup the same error notify me that org.apache.tomcat.InstanceManagerBindings cannot be found by org.apache.tomcat.embed.tomcat-embed-websocket_8.5.4

Madrepore answered 10/11, 2016 at 2:59 Comment(0)
P
1

You are facing several problems here. The first one is that you use require bundle all over the place. The problem with require bundle is that you are always exposed to all packages a bundle offers. This will increase the probability of uses chain contraint violations. You should try to use Import-Package instead.

The other problem is that spring does not support OSGi anymore. So using spring libraries in OSGi is very likely to create problems as they simply do not test their code in OSGi.

If you need websocket support then a better choice might be pax web. It runs with tomcat or jetty and wraps them in an OSGi compatbile way.

Unfortunately there is no example for pax-web or plain jetty in eclipse. To see what bundles you need you can start apache karaf and install the http feature. Then you can look into the bundles it installs and use the same in eclipse rcp.

Prevail answered 10/11, 2016 at 8:53 Comment(7)
Do you think this problem is mainly caused by Require-Bundle instead of Import-Package? If so, maybe I should figured out what are the differences between them. And for the Spring issue, since our system is heavily depends on Spring, we think Spring is our best bet, and I've converted them into bundles conforming the OSGi rules via p2-maven-plugin though. Thanks for your advice, definitely will check pax web out later.Madrepore
A lot of the spring bundles can be found at servicemix bundles. See github.com/apache/karaf/blob/master/assemblies/features/spring/…Prevail
And for your suggestion to use Import-Package instead of Require-Bundle, the problem I have is that I don't know which packages I should import in specific, especially for these libraries are loaded at run time.Madrepore
You only need to import the packages you actually use in your code. So normally the PDE will tell you if an import is missing. Btw. That is why I prefer generating the Manifest using bnd. There in most cases you do not have to tune anything by hand to make it work.Prevail
generating the Manifest using bnd, you mean the Bndtools?Madrepore
Either bndtools or using a plain maven build with maven-bundlle-plugin. Unfortunately at lest the plain maven builds do not work well for eclipse rcp projects which you are doing. So probably you have to stay with the PDE. I am doing mostly server side OSGi.Prevail
If you are interested in building your RCP project with maven you should take a look at maven-tycho and for OSGify Bundle generation p2-maven-pluginPirogue
P
1

Add a version info to your javax.servlet import package so OSGi can decide wich dependency chain to use.

javax.servlet;version="3.1.0"
Pirogue answered 18/11, 2016 at 10:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.