1

I am using third party code, which uses some jar (actually, this is log4j). When running my plugin, I am getting multiple errors ClassNotFoundException, NoClassDefFoundError. Since third-party code usage is limited to some ViewPart yet, then the program is running, but view is not instantiated.

At compile time in Eclipse I have added required jars into class path, as usual, and code has no any errors at compile time, including import directives for log4j.

Since I put all (many) required jars into lib subdirectory of my project directory, I thought to modify build.properties as below

source.. = src/
output.. = bin/
bin.includes = plugin.xml,\
               META-INF/,\
               lib/,\
               .

But apparently this didn't help.

Where can I see my entire bundle/plug-in compiled packed to check which jars are contained there?

UPDATE

Currently I put required jars twice.

First one -- into normal Eclipse Configure Build Path window:

enter image description here

Second one -- into Classpath section of Runtime tab of plugin.xml editor:

enter image description here

Latter config makes the following change in build.properties file:

source.. = src/
output.. = bin/
bin.includes = plugin.xml,\
               META-INF/,\
               lib/,\
               .,\
               lib/java-getopt-1.0.13.jar,\
               lib/jsp-api-2.0.jar,\
               lib/junit-4.11.jar,\
               lib/log4j-1.2.17.jar,\
               lib/rhino-1.7R4.jar,\
               lib/servlet-api-6.0.36.jar,\
               lib/tomcat-catalina-7.0.42.jar,\
               lib/commons-logging-1.1.3.jar,\
               lib/spring-beans-3.2.0.RELEASE.jar,\
               lib/spring-core-3.2.0.RELEASE.jar,\
               lib/miglayout-core-4.2.jar,\
               lib/miglayout-swt-4.2.jar,\
               conf/

So is it possible to AUTOMATE this some how? Is it possible to AUTOMATICALLY pass all conventional classpath entries to runtime?

I need SIMPLIFICATION, I don't want to wrap jars into bundles and something similar.

The question is open.

Suzan Cioc
  • 29,281
  • 63
  • 213
  • 385

2 Answers2

4

To export a plugin you can use File menu -> Export -> Plugin Development/Deployable plug-ins and fragments. Then select you plugin and it will be exported as a jar. To export a product, there is a product exporting option in .product file.

I would suggest you to created a separate plug-in by using "Plug-in from existing JAR archives" option in the "New Project" wizard. If so, then I hope you didn't forget to include it to your run configuration. Also, please check this question for more details.

Update: You are neither required, nor forced to convert your jars to bundles, but since your are not creating a pure Java project (you have an OSGI bundle, with its own classloader and lifecycle), you may want to take into consideration some best practices/rules, which could help you creating a good plugin/project.

Why you need to convert dependencies to bundles?

You already have your third party dependency (log4j, apache commons collections etc.,) as jars and all you need to do is add it to your bundle classpath. This is simple and it works as long as you are developing only one bundle or your bundles do not share common dependencies.

But, in reality, you might be creating a bunch of bundles and they all would use common dependencies. The problem here is in the way OSGi classloading works. Each bundle has it's own classloader and so if you have two bundles both using log4j as jar dependency in their classpath, and when you try to reference log4j in each of the bundles, each would try create their own instances of the log4j classes in their respective classloaders. This might cause classloader constraint violation issues or ClassCastExceptions. If you convert these dependencies to OSGi bundles, then these problems would no longer happen. This is because now each of your dependency (say log4j) has it's own classloader and so whenever your Bundle A or Bundle B want to load log4j class, it will load it from log4j bundle classloader.

Please refer to this article for more information.

Regarding the automation process: I am don't think it is possible. Since you are manually adding jars to your lib folder, you should, manually add them to the classpath (In Runtime section). However, defining lib/ in the build.includes configuration, should help at some point. Also, may be this will help. Please note, that you don't need to "Add jar to Build Path" as you would usually do! Adding it in the Runtime section (your second screenshot), will add it to the Build Path for you.

Also, please note that on your screenshot "." is not on the top of the Runtime configuration section.

Community
  • 1
  • 1
Alex K.
  • 3,294
  • 4
  • 29
  • 41
  • I have no `product` yet. Also I don't understand why to wrap into bundle first? I am coding Java, why can't I use jars then? – Suzan Cioc Jan 21 '14 at 21:08
  • Thanks for reasoning about making separate bundles for jars, but I have some already made code, and want to wrap it into. It has normal conventional dependencies. These are dependencies on external jars and entire external projects. Eclipse allows to add both in plugin project too. But I don't understand why Eclipse (1) allows them and (2) ignores them. It would be great if Eclipse either disallow entries or use them. No sense to have unused functionality. – Suzan Cioc Jan 22 '14 at 09:12
  • Plugin project is still an Eclipse project, so I believe that is why it allows same actions as for other projects. Moreover, project with the same structure could have been build in a different way, depending on project type, builders, facets etc. So, not really sure, why it confuses you that much. Each project should be configured appropriately and you just need to live with it;) – Alex K. Jan 22 '14 at 09:54
  • If it allows adding jars to Build Path then why it does not use them when building? – Suzan Cioc Jan 22 '14 at 10:05
  • 1
    Because build process is custom, as I've mentioned before, depends on many factors. For building a .war there is one approach, for building .ear another, for building eclipse plugin also different. Also, Build Path is just for eclipse to be able to pre-compile your project, assist with autocomplete, content assistant, search and so on, it is not an information to create artifacts for different types of containers (web servers, eclipse-rcp frameworks). It never was. Even with Maven you specify dependencies for your project, but then separately configure a build of an artifact, as needed. – Alex K. Jan 22 '14 at 10:43
2
  1. log4j is available as an OSGi bundle: http://ebr.springsource.com/repository/app/bundle/detail;jsessionid=66ADD0FE737BA9A5DD36A052F4A6809A.jvm1?name=com.springsource.org.apache.log4j. In general, if you want to use a third-party library which isn't published as an OSGi bundle (yet), it's worthwhile checking if SpringSource has an OSGi version.

  2. If it wasn't, you could wrap it as a bundle yourself, as Alexander Gavrilov suggests.

  3. Finally, if you really want to leave it as a non-OSGi bundle, you need to set Bundle-ClassPath: ., lib/log4j.jar in your MANIFEST.MF. Of course, this will have to be done for every plugin that needs a jar, and for every jar, as well as changing the build path in Eclipse.

Some more relevant questions and links: https://stackoverflow.com/questions/5150415/log4j-under-osgi-eclipse-rcp, https://stackoverflow.com/questions/11341627/integrating-3rd-party-jars-into-eclipse-rcp, https://stackoverflow.com/questions/6545212/add-3rd-party-library-to-an-eclipse-plugin.

I need SIMPLIFICATION, I don't want to wrap jars into bundles and something similar.

Bundles are jars with a bit extra information in MANIFEST.MF, nothing more. OSGi (and therefore Eclipse) does need this information. Most commonly used libraries either already are bundles (just check for Bundle-SymbolicName in MANIFEST.MF), or available as a bundle. Failing that, wrapping a jar only has to be done once for each jar, instead of having to change build path, build.properties and Bundle-ClassPath for every plugin which depends on the jar as well.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487