I am looking for the best practice of handling inter project dependencies between mixed project types where some of the projects are eclipse plug-in/OSGI bundle projects (an RCP application) and others are just plain old java projects (web services modules). Few of the eclipse plug-ins have dependencies on Java projects.
My problem is that at least as far as I've looked, there is no way of cleanly expressing such a dependency in Eclipse PDE environment. I can have plug-in projects depend on other plug-in projects (via Import-Package or Require-Bundle manifest headers), but not of the plain java projects.
I seem to be able to have project declare a dependency on a jar from another project in a workspace, but these jar files do not get picked up by neither export nor launch configuration (although, java code editing sees the libraries just fine).
The "Java projects" are used for building services to be deployed on an J2EE container (JBoss 4.2.2 for the moment) and produce in some cases multiple jar's - one for deploying to the JBoss ear and another for use by client code (an RCP application).
The way we've "solved" this problem for now is that we have 2 more external tools launcher configurations - one for building all the jar's and another for copying these jar's to the plug-in projects. This works (sort of), but the "whole build" and "copy jars" targets incur quite a large build step, bypassing the whole eclipse incremental build feature and by copying the jars instead of just referencing the projects I am decoupling the dependency information and requesting quite a massive workspace refresh that eats up the development time like it was candy.
What I would like to have is a much more "natural" workspace setup that would manage dependencies between projects and request incremental rebuilds only as they are needed, be able to use client code from service libraries in an RCP application plug-ins and be able to launch the RCP application with all the necessary classes where they are needed.
So can I have my cake and eat it too ;)
NOTE
To be clear, this is not so much about dependency management and module management at the moment as it is about Eclipse PDE configuration.
I am well aware of products like [Maven], [Ivy] and [Buckminster] and they solve a quite different problem (once I've solved the workspace configuration issue, these products can actually come in handy for materializing the workspace and building the product)
Eclipse projects depend on each other by virtue of the checkbox in the project's properties (dependent projects?) which is how Eclipse decides which to build. You can set this yourself, but it's usually set when you change your Java build path. It stores the data in the .project file IIRC so once you've gone through the GUI and seen what changes, you can be more flexible in how you apply the others.
However, it sounds like you want to mix and match Jars and Bundles. The easy way to do that is just treat all projects as Java projects. In the PDE project, you can actually go in and tweak the Java build path; it'll complain and say that it isn't the right way to do it, but it will allow you to have a PDE project depend on a Java project without all that fluffy JARing up. Having said that, it wouldn't surprise me if there were runtime problems with this approach - the PDE runtime is likely to not see it that way.
The other approach is to make your JARs themselves PDE/OSGi bundles. After all, an OSGi bundle is nothing more than a JAR with a bit of extra cruft in the Manifest, and it will let you develop and assemble your projects trivially using automatic dependency management. That's probably the easiest one to go for, even if you don't really need the manifest to be present in your bundles. But doing this will mean your PDE app can be shipped with a more modular approach instead of embedding the libraries in each plugin as necessary.
So, PDE can generate OSGi bundles, and that's just another name for JAR + Manifest stuff. You can use a JAR in exactly the same way in other environments (e.g. for your EAR or other client uses) and you can take advantage of the OSGi layer in your app. There's really no reason not to do this given the type of hybrid bundle that you're talking about.
I never did it so this is a theoretical approach. But I'd try a dependency management system like ivy or maven2.
Since maven2 does much more, then just dependency management, I'd recommend ivy in this case.
Our solution uses an Ant builder to copy the "classes" directories of the plain Java projects directly into the top directory of the plugin project. We skip the JAR building step to save time, and it works pretty well. If the plugin project depends on external JARs that're already built, we copy those in too.
Here's exactly how to set it up in Eclipse 3.5 (sorry for the odd formatting, but that's the only way I could find to preserve indentation):
Create empty "classes" dir in plugin project
Select plugin project, hit F5 to refresh resources
Create new Ant build file in plugin project to copy dependencies (ours is shown below)
Right-click plugin project, select Properties
Select Builders
Click "New..." (brings up Edit Configuration dialog)
Select Ant Builder and click "OK"
Name your builder (ours is called "PluginProject externals")
Browse workspace for Buildfile (ours is ${workspace_loc:/PluginProject/copyDependencies.xml})
click Refresh tab
check "Refresh resources upon completion", click "Specific resources"
click "Specify Resources...", check box for the classes dir, click "Finish"
Click "OK" (closes Edit Configuration dialog)
Click "Up" to move "PluginProject externals" to top of builder list
Click "OK" (closes Properties dialog)
Open your plugin project's MANIFEST.MF
Click "Runtime" tab
Click "Add..." under "Classpath", select your the "classes" dir and JARs and click "OK"
The manual creation of the empty "classes" directory in the plugin project is so you can tell your new builder to refresh that resource (which doesn't exist yet before the new builder is run). Here's what's in our copyDependencies.xml file:
<project name="Copy dependencies" default="copyDependencies" basedir=".">
<!--
This copying is needed because it appears that Eclipse plugins can't
depend directly on external Eclipse projects.
-->
<description>
Copies external dependency class andd JAR files into this plugin's directory.
</description>
<target name="copyDependencies">
<copy file="../External/JDOM/jdom-1.0/build/jdom.jar" todir="." preservelastmodified="true"/>
<copy file="../External/Xalan/xalan-j_2_6_0/bin/xalan.jar" todir="." preservelastmodified="true"/>
<copy file="../External/Xalan/xalan-j_2_6_0/bin/xercesImpl.jar" todir="." preservelastmodified="true"/>
<copy file="../External/Xalan/xalan-j_2_6_0/bin/xml-apis.jar" todir="." preservelastmodified="true"/>
<copy todir="./classes/com/arm" preservelastmodified="true">
<fileset dir="../Utilities/src/com/arm" excludes="**/*.java"/>
</copy>
</target>
<target name="clean" description="Deletes local copies of external classes and JARs.">
<delete file="jdom.jar" quiet="true"/>
<delete file="xalan.jar" quiet="true"/>
<delete file="xercesImpl.jar" quiet="true"/>
<delete file="xml-apis.jar" quiet="true"/>
<delete dir="./classes/com/arm/utilities" quiet="true"/>
</target>
</project>
The only downside to this method seems to be that Eclipse isn't 100% perfect about invoking the external builder when it needs to be invoked, so occasionally you have to do a "Project > Clean..." in Eclipse to force it along.
You have my sympathies. I too have battled with this issue and the Wall-of-Silence from the Eclipse devs on such a simple, obvious question: how to declare a dependency from a plugin to a normal Java project (such that it works at runtime)?
I dont think they support it. The only way Ive got around the problem is to create folders inside my plugin projects that are actually links to the bin/ folders of the java projects, and then include these folders into the plugin. That at least works, but its brittle due to the absolute filesystem paths required.
maybe you can use "project properties" -> "deployment assembly" on Eclipse, and add other projects to your main project. The other projects are seeing like "jars" that automatically are added to your deployment file (war, ear or whatever). Maybe this can be works. At least it works for me. Good luck !!
Ariesandes.
There is a "Link source" option in Build path properties that allows you to define additional source folders for a project. You can selected the "src" folder of another workspace project and rename it to "src2" or whatever you want. This way classes are compiled and deployed into the plug-in project output folder and can be loaded at runtime.
With a complex set of build dependencies, I've found Maven2 and Hudson (for CI) to be a pretty nice combination. It took a while to set up the infrastructure and get my head around configuration, but after that, it just worked.
Of course, you are dependent then on Maven2 (or Hudson) support for your build mechanism. I'm not sure how well Eclipse Headless builds are supported. But if the only reason you're using Eclipse headless is to allow the dependencies to be expressed in a single place, do yourself a favour and switch.
I am having the exact same problems. We have a set of multiple normal java projects that can be built by Maven and should (currently) all share the same classpath to work properly. These projects can be used to start a server in a non-OSGi environment. Then we also have an eclipse RCP client which uses these projects as one bundle. I am perfectly able to build this one-big-bundle with Maven using the Apache Felix Maven Bundle Plugin and everything works fine. But whenever I change one class in the normal project I have to rebuild the entire bundle. Incremental build and resource linking does not work.
I tried the "solution" with linking binaries/source directories from these projects into the Manifest classpath of the one-big-bundle and it seems to work but it would be a real maintenance nightmare because I even have to link some individual files.
So ironically BECAUSE of the use of OSGi in the client I am actually thinking of collapsing our nice and modular structure with Maven modules into subpackages of only one plugin project. This is a better alternative than having extremely slow development.
The other and better alternative (according to the OSGi guys) which I will investigate first is to make all my Maven modules into OSGi bundles. But this may be a real PITA because I depend on classpath scanning and combining multiple configuration files from several bundles (with sometimes the same name) to form one configuration.
(Specifically we use the Spring framework and we merge multiple persistence.xml files into one persistence context. We also merge several spring XML context files from different modules (all providing a different ASPECT) that should together form one Spring context to be used by Spring-DM.)
Related
I have an Eclipse project that depends on several other projects from the same workspace. I know hot to create a simple Ant build script for a single independent Java project, but how to tell Ant to integrate all those project into my main JAR file so my dependent program can work?
In Ant, the simplest way is to explicitly enumerate those other projects and include them in the jar target. Something like:
<path id="all-projects">
<fileset dir="../my.other.project" includes="**/*class">
</path>
One solution : Create a master project and put all the projects into it and have a single build.xml.
Another option : Create a master project but leave everything at the same level (do not place project-components inside the project folder) Then arrange your build script to refer to the other projects via relative paths. Note that with some build tools this is not even necessary as they will look at their repository.
While you can munge together a solution with Ant, Apache Maven is a better solution for managing dependencies than Ant. If you don't want to go with a full blown Maven lifecycle management project, you can also look at using a Nexus repository to store your artifacts, and include Apache Ivy in your Ant build scripts to perform dependency management.
Ivy or Maven will provide a better, more manageable dependency management strategy which is likely to be easier to integrate into a team than anything you will be able to assemble on your own.
So I'm fairly new to Java and especially Eclipse, so please excuse my ignorance. I took a project from a server and copied it locally to my machine. When I opened the workspace, I had many errors due to it not being able to find the jars. This makes sense because I don't have the same dir structure as the server I copied from. So if I copy the same external jar's to my machine and get it to compile into a jar and copy it back to the server, will it work? Or will it fail because now the external jar's are in a different place than it is expecting?
Also, down the road should I put the external jars into regular jars to avoid this problem?
You should be OK. Java is using what is called classpath to locate dependencies. The classpath may be different on the development machines, but as long as all the dependencies are on the classpath in the production everything should work.
To avoid issues with the synchronisation of directory structures the most common way is to use Maven - it will manage all the dependencies for you (but you have to manage the pom.xml - the Maven's project descriptor). A little clumsier way is to have the dependencies in the project, however you may end up with many projects having to include same jars, and then there will be version conflicts and so on.
For small projects you can manage dependencies yourself, however larger projects will need a more thought through strategy (like Maven).
In regard to the executable jars, make sure the Class-Path entry in <jarfile>:\META-INF\MANIFEST.MF is correct, e.g. where it references other jars, those jars are going to be there in the production. For example, assume we have ourjar.jar and assume this is a snippet from its MANIFEST.MF:
Class-Path: lib/myteamjar.jar
It will then be expected that a following directory structure is in place:
lib/myteamjar.jar
ourjar.jar
No, the location of the external jars does not mater. What you want to do is put the external jars on your classpath. How you do it depends on how you are running your java code. If you are running it from the CLI using the java command, it takes the classpath as an argument. If you want your code to build/run in Eclipse, you need to right click on your project, select "Build Path" > "Configure Build Path..." Use the "Add JARs..." button to add jars that are part of a project you have open and "Add External JARs..." to add jars that reside outside of the project. See specific documentation for your tool for more details about classpaths.
I would not recommend Maven to somebody who is fairly new to Java and Eclipse. I would forget about Eclipse, too.
You have a packaging and CLASSPATH issue. Focus on that.
What kind of project are you talking about? The answer you get will depend on what type of app you're creating. Is it an executable JAR? Then the right way to do it is to package everything into a ZIP file that's laid out exactly as the CLASSPATH in the JAR manifest expects.
If it's a web app, the right thing is a WAR file, with all the JARs your app needs in the WEB-INF/lib directory.
If you package things properly, you should end up with a single package that has everything laid out the right way. You should be able to deploy it to the server and make it all work.
i was on a 2-day training introducing as to Java EE. We used there Java EE, Spring Framework, Maven, Springsource Tool Suite (Eclipse), Tomcat.
I took the Eclipse workspace we created there and run it on my work PC. I had, if i remember correctly, only to configure Tomcat properly, and it worked on my PC.
Now i want to save the created Eclipse workspace containing 5 "sub"-projects in subversion so that my work colleagues can checkout this to them and run it on their computers.
How to do this correctly? I found somewhere a svn:ignore rule:
.classpath
.project
.settings
target
Using tortoiseSVN i added to the folder with the workspace this ignore rule, but the found out that the underlying folders target were'nt deleted so i deleted them manually and "added to ignore list". But after that the project in spring source tool suite does not see the mevan dependencies (i think so) because the imports are broken. STS underlines org. in the imports and says it can not resolve this.
How do i correctly version control such a project?
In my project we are using Maven and Eclipse (Helios, currently) and the Maven plugins for Eclipse:
Maven Integration for Eclipse
Maven Integration for WTP
We only have the pom.xml file and the src/ directory tree in our version control system. We make sure not to add the eclipse files there. Then when a new developer starts in the project they do Import -> Maven -> Existing Maven Projects. The Maven plugins for Eclipse then set up perfect build paths, settings and so on.
This way it is also very easy to re-import your projects into Eclipse as needed.
So, my tip is to leave the Eclipse files out of SVN and make sure you can setup the project correctly automatically simply by importing a Maven project.
If I understand your problem the right way, you need to configure Eclipse in order to be able to launch tomcat from it. The key, here, is not maven anymore, but Eclipse, I think. As you've made modifications in your workspace that can't be put in your maven configuration file (the pom.xml), you become "Eclipse dependant".
The key here is that, as you're Eclipse dependant, you need the Eclipse configuration files to work. Consequently, I'm afraid you need to add back .classpath, .project, .settings to your versioning tool... It's not generic, because you force people who work on your project to use Eclipse. But if everybody in your team do so, it shouldn't be a problem.
As I don't use Eclipse anymore, I don't know if versioning theses files can lead to problems. However, I hope this answer will help you to configure your project back...
EDIT : to be more accurate... and maybe give a better answer.
When using a version control system, the main goal is often (always ?) to give all the keys to use the sources, and develop from them. Consequently, you need to put in your VCS your sources, and all the configurations needed to use them efficiently.
In your specific case, the key is that you've become Eclipse dependant through its Springsource Tool Suite plugin. Consequently, it becomes essential to add the configuration files for this tool, because they can't work without them, and if they can't work, you can't work.
I can tell you my way of subversioning maven eclipse projects. First, when you create the project structure you have to commit the .setting, .classpath, .project files into the subversion repository. If you can't do this the other colleagues will can not use the project structure after checkout. After you commit the project structure, the best way is not to commit these files except only when you change something important eclipse or build path settings, because the others will have conflicts due to the system dependent informations. Never commit the maven target directory. Sorry for my english. Hope it helps.
I am using Eclipse IDE and its derivative like Spring IDE for Java development.
In a web application project, I add external jars like Spring MVC jars, Apache commons jars etc to the Web App library folder, hence they are automatically added to the build path. There are many jars in the Web App library folder.
I want to create folder in the project and add all the source files (zip/jar) of the libraries included in Web App library folder, so that I can navigate through the source of libraries from the Java editor window. Whenever I add a source zip/jar file to this folder, Eclipse should detect it and use it whenever I want to navigate to the source of a library.
Is the above possible in eclipse?
Note: I know how to add source files
for each individual jar by navigating
to the build path window and
specifying the source location. But
this is very crude way, and I need to
do for every library individually.
Also the drawback is that source path
is absolute, which means if I import
the project into another computer then
I need to create the source path or
even worse I might have to add the
source files individually again.
One way to automagically get the sources for the jars would be some kind of dependency management system. Most people would scream Maven (2/3) by now, but others exist and work well. Maven does have nice Eclipse integration, so that should be a plus.
The downside is that setting up a Maven project just for it's dependency management can seem overkill. Another point is that all the jars you depend on should be "Mavenized" as well.
As far as I know Eclipse wont automatically detect/scan source archive files and link them up to libraries in your workspace in the way you described it.
I agree with #Gressie on using Maven and the Eclipse Maven plugins -- as in that case it's just a matter of ticking a few boxes and Maven will do that for you.
If however your project is not Maven-ized, you can still do this in Eclipse but it's more tedious:
for each one of the jars in your project (which appear under the dependecies section) right click on it and select properties
in the dialog that pops up you have (at least) 2 locations you can configure: java source attachment -- simply browse to your jar with the sources -- and also javadoc location (point it to the jar with javadoc if you want the javadoc to appear as a tooltip when you hover the mouse over one of the classes/methods/etc in that library).
I have two projects in eclipse, a library project producing a Jar file and a web project dependant on that Jar. How do I get the web project to export the first projects jar in its war automatically. I know this must have been answered before, but I really cant find it.
Thanks,
The mechanism to determine what goes in the war is not the build path as for "normal" applications, but the "Deployment assembly".
Right-click on the root node of the dynamic web project, and select Properties, and select Deployment assembly. Here you can add projects (which are jarred up and added to WEB-INF/lib) and individual jars in the project.
EDIT 2015-08-20: A few years later, Maven has become the standard way to build Java-based software primarily due to the script based approach to dependency management. This includes how to build WAR-files, and the three major IDE's (IntelliJ, Netbeans and Eclipse) fully support this allowing you to switch between IDE's while developing. In Eclipse the problem asked here will not apply, as this is fully controlled by the Maven plugin.