Using third-party libraries in Eclipse RCP Tycho app
Asked Answered
C

2

14

I've created a boiler-plate project following vogella's extensive Tycho tutorial.

enter image description here

Facts:

  • There's no feature, and there's no plugin. The only plugin is the RCP app, which is also the entry-point.

Problem:

  • I have no idea in which pom.xml do I include the 3rd party dependencies.

  • I cannot include them in the RCP project, because the packaging of that pom is eclipse-plugin, and not jar. From what I've noticed, if I change the packaging to jar, then the "Maven Dependencies" library is added automatically. If I change back to eclipse-plugin, they get removed.

Questions:

  • Where do I add the dependencies? There's no pom with jar packaging in my project.
  • Should I create a separate project with the necessary JARs? How do I include that dependency to my entire project?
  • Is it really that much of a good practice to create a separate plugin and a feature for this RCP app?

Related solutions:

  • "Update projects" doesn't work, and neither do the n other solutions in the other SO questions.
  • There's also this question and that question, but I don't fully get the answers
Cadman answered 11/2, 2016 at 17:29 Comment(4)
What dependencies are you talking about? 3rd parties libraries? the simplest way is to include them in the project classpath and ask "to include them" on build in the build.properties files (via the plugin editor when you double click on plugin.xml). If you need eclipse-plugin dependencies, you can also add them with the plugin editor. also you are talking about maven, do you use tycho with maven? if so, maven with the tycho plugin will uses the dats in your plugin.xml/manifest/build.properties ...files to build your pluginScuba
There should be a MANIFEST.MF that is associated with each plugin that is where usually dependencies are mentioned.Doggish
@Scuba I don't want to add the dependencies manually.. I'm using Maven+Tycho. I just don't know in which pom.xml, of which project, should I add the dependencies.Cadman
It is not clear what you are asking. Based on some of the links to other questions I can guess it is non-OSGi bundles causing you problems? Can you give a specific example of a library you want to include?Filial
T
22

I think that you have a fundamental misunderstanding.

Maven: Maven determines all of the project dependencies via the pom.xml and resolves transitive dependencies automatically (assuming that all of the pom files and artifacts exist in repositories that you've configured and correctly declare their dependencies).

Tycho: The problem is that Eclipse already has its own project model based on product files, feature.xml files, and plug-in MANIFEST.MF files. Tycho leverages the Maven machinery for Eclipse, but the idea is that the pom.xml files just configure the Maven plug-ins and declare the packaging type. That provides an entry point for Maven, but then Tycho takes over. While Maven would normally build the dependency chain from information in the pom.xml files, Tycho is building the dependency change from information in the product, feature, and MANIFEST.MF files. You don't put any dependencies in the pom.xml files. Tycho also uses Eclipse p2 repositories (instead of normal Maven repositories) for finding dependent plug-ins that are not found in the local modules or target platform.

That's actually a benefit for many Eclipse developers since they've already set up everything properly in their Eclipse plug-ins, features, and products. They do not want to have to repeat all of the dependencies in the pom.xml.

Using Libraries in Eclipse plug-ins: In Eclipse, if you want to use a library that is not already packaged as an Eclipse plug-in, you have a few options. Your plug-in can include a set of JARs in a libs folder and then include that libs folder in the plug-in and runtime classpath (see the build.properties file). Another option is to create your own "library plug-in" that repackages a JAR library as an Eclipse plug-in. See also https://wiki.eclipse.org/FAQ_What_is_the_classpath_of_a_plug-in%3F. That's the answer that you're getting above.

The problem is that if you're trying to include a complex library with multiple JARs that is normally distributed and included in a standard Java project via Maven. We hit this problem with the Jersey JAX-RS implementation in my project. There's no p2 repository that includes all of the pieces of the libraries as plug-ins with correct dependency information.

Easy Solution: If you need a common library, check the Orbit project first to see whether the libraries have already been packaged as Eclipse plug-ins, http://www.eclipse.org/orbit/. In that case, you can download them and include them in your target platform, or you can pull them in dynamically at (Tycho) build time from their p2 repository. Your plug-ins would just include those plug-ins as dependencies (in the their MANIFEST.MF files).

Workaround / Solution: In our case, Jersey JAX-RS was not available as an Eclipse plug-in, and it had a bunch of transitive dependencies. The workaround was to create an Eclipse "library plug-in" like I mentioned above with two pom files. We initially created a skeleton plug-in with an empty libs folder. One pom file is just a standard Maven pom file with <packaging>jar</packaging> that declares the top-level dependencies required to pull in the Jersey JAX-RS implementation and all of its dependencies. The dependencies are declared with <scope>compile</scope>. We use the maven-dependency-plugin to copy all of those dependencies into the project's libs folder.

<plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>compile</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>libs</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

We actually ended up running Maven with that pom by hand from time to time to update the libs, and then we just checked the plug-in with all of its dependent JARs into source control. Checking the build later, I see that we actually populate the libs folder on-the-fly with Maven with a separate build task just before we start the Maven/Tycho part of the build. Of course, plug-in's MANIFEST-MF file's Bundle-ClassPath and Export-Package entries are coming straight from source control. We have to check those from time to time to ensure that they match the libraries and packages that we're getting from Maven. (That doesn't tend to change much unless we bump major library versions or add a new dependency at the Maven level.) The plug-in's build.properties has the libs/ folder as part of bin.includes.

In the development environment, after we first check out the code, we just run mvn (with an External Tools launch config that's also checked in with the project) on the project's "copy dependencies" pom file. That populates the libs folder with all of the JAX-RS libraries and dependencies. We only have to run it again when we update something about the dependencies or when we're jumping between branches that have different versions of the JAX-RS dependencies. We set .gitignore to ensure that we don't commit the libs to Git.

The other pom for this project is set up like a normal Tycho pom file with <packaging>eclipse-plugin</packaging>. During our automated build, we run one step early in the build process (just after check out) that calls mvn with the jar pom to populate the libs. Then we proceed with the main Maven/Tycho build using the eclipse-plugin pom. The eclipse-plugin pom has no dependency information (as I said above). It's just providing Tycho a way to recognize the Eclipse plug-in and build it based on its MANIFEST.MF and build.properties files. But the built plug-in includes and exposes all of those libs that were populated by the mvn call to the jar pom step.

So, it's a bit of a mess, but that's the best solution we found a couple of years ago when we hit this problem. I'm not sure whether Tycho is doing any work to permit some sort of hybrid Maven/Tycho build that could do this automatically as part of the build. I guess I should ask the developers. :)

Your questions:

  • Where do I add the dependencies? There's no pom with jar packaging in my project. Answer: The workaround above lets you do it with one project. You just have two pom files, like pom_deps.xml and pom.xml. You just have to invoke the pom_deps.xml separately to populate the libs folder (in the dev environment and with your automated builds).
  • Should I create a separate project with the necessary JARs? How do I include that dependency to my entire project? Answer: the workaround that I described above lets you do it with a single project. Another way to do it is to create a separate JAR project, but I don't think that your Eclipse RCP app can really include a <packaging>jar</packaging> module in a useful way. The only way I've found to do it is to use a similar workaround. You build the JAR module first, install it into the maven repository, and then have one of your plug-in projects bundle the JAR in its libs folder. (If you really want to do it that way, ask. We have a case where we have to do that, too, and I can provide the steps we do in development and the build to make it work. I think the single project workaround that I provided above makes more sense for your case.)
  • Is it really that much of a good practice to create a separate plugin and a feature for this RCP app? Answer: that's really a separate question. If you have a feature with multiple plug-ins, you have the same problem. Tycho can handle the product/feature/plug-ins, but it cannot jump across into Maven-based dependency resolution. You'll end up having to use the same workarounds

Summary: The fundamental issue is that Eclipse plug-ins can't "see" a bare JAR library. The plug-in needs to have the library included in its local libs folder (with a matching Bundle-ClassPath entry in MANIFEST.MF), or it needs to depend on some other plug-in that exports the appropriate packages. Tycho just resolves dependencies via Eclipse plug-ins, and it cannot leverage normal Maven dependency resolution directly to pull in a bunch of JARs. If all of your dependencies are already plug-ins, you're fine. If not, you may have to use the workaround above to package a set of libraries for your plug-ins to use.

Transilluminate answered 17/2, 2016 at 19:10 Comment(4)
Hi :) Your post seems to be the most substantive I've seen on the topic. Do you have any examples you could share on where you've achieved this? One of the limitations I can see is how you add an entire directory to the .classpath / MANIFEST.MF. I thought they had to reference a specific file, for example?Lamonicalamont
build.properties can reference a folder, like bin.includes = META-INF/,\ .,\ libs/ You're right that the MANIFEST.MF's Bundle-ClassPath references individual JARs. After I run the maven job to rebuild the plug-in and pull in the latest transitive dependencies, I just go to the project in Eclipse. I remove all of the runtime dependencies. Then I add..., and I multi-select everything in the libs folder. Same with exported packages. It's a couple of manual steps, but it only takes a minute. YMMV, but it work for us.Transilluminate
I should also note that I wrote that response back before pomDependencies was available (or at least not in the version of Tycho that we were using at the time). The link in the response by @Loganathan below is probably a better approach to use today.Transilluminate
Oh, and the project where we did that was on a project at work that's available outside my company. If the pomDependencies approach really doesn't work for you, let me know, and I'll see whether I can publish a skeleton example for you on GitHub.Transilluminate
M
1

Just adding the plugin to pom dependencies and including the entry <pomDependencies>consider</pomDependencies> in the configuration of target-platform-configuration makes it work.

<plugins>
    <plugin>
        <groupId>org.eclipse.tycho</groupId>
        <artifactId>target-platform-configuration</artifactId>
        <version>${tycho.version}</version>
        <configuration>
            <!-- The configuration to make tycho consider the maven dependencies -->
            <pomDependencies>consider</pomDependencies> 
            <!-- other configurations -->
        </configuartion>
    </plugin>
    <!-- other plugins-->
</plugins>
<dependencies>
    <!-- An example third-party bundle (plugin) present in maven repository-->
    <dependency>
        <groupId>org.apache.felix</groupId>
        <artifactId>org.apache.felix.gogo.shell</artifactId>
        <version>1.1.0</version>
    </dependency>
</dependencies>

Reference link here.

Methodist answered 13/8, 2018 at 11:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.