How export Java jar from Eclipse with dependencies on other jars? - java

I am trying to create a self-contained .jar file from an Eclipse project. By "self-contained" I mean that all dependenies of this project (i.e. other jars) should be included in the generated jar. I would like to use the exported jar in another project as a library.
The problem is that I get a NoClassDefFoundError for one of the classes from the dependencies. I have tried exporting both a runnable jar with all dependencies packaged into it and a "normal" jar. Neither of these works.
The manifest looks like this:
Manifest-Version: 1.0
Main-Class: com.path.to.MyMainClass
Class-Path: lib/resolver.jar lib/xercesImpl.jar lib/xml-apis.jar lib/Mac-Cocoa64/swt.jar
The .classpath look like this:
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="lib" path="lib/resolver.jar"/>
<classpathentry kind="lib" path="lib/xercesImpl.jar"/>
<classpathentry kind="lib" path="lib/xml-apis.jar"/>
<classpathentry kind="lib" path="lib/Mac-Cocoa64/swt.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
The missing class def is from the SWT.jar file.
Any idea what might be wrong or what steps I need to take in order to successfully export this jar so that it can be included elsewhere?
Cheers,
Martin

It may help someone
1.Select Export from Project Properties
2.Select Runnable Jar option
3.Finish the JAR creation (Here, you have the option to package all dependencies into the generated jar.)

Just to answer this question: In the end, we decided to include the jars of the dependencies directly in the project and avoid havign jars in jars. Using Mavin is also being considered, but would require some substantial chagnes to the way our projects are setup.

Related

How to add new jar file to existing deployed jar in server

I have a RMI application which is running on the server. Now i want to add external jar file to an existing deployed jar.
Note: It is not web application.
For example, here i mention the jar directories
MyApplication.jar
manifest.mf
.classpath
classes
My java class files
lib
test.jar
test1.jar
images
META-INF
MANIFEST.MF
.classpath has
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="lib/test.jar"/>
<classpathentry kind="lib" path="lib/test1.jar"/>
<classpathentry kind="output" path="classes"/>
</classpath>
Now i want to add test2.jar to my lib folder inside MyApplication.jar and updating .classpath file.
Is it possible to add it?
If you cannot use JRebel then you will probably have to try to write your own class loader to achieve this. There are many pitfalls. See this answer and this question for some pointers.

Use Eclipse classpath variable to replace absolute "sourcepath" path?

I would like to use an Eclipse classpath variable to resolve the attached source JAR file for a library in my classpath. This is the contents of my current ".classpath" file in Elcipse (Indigo):
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry exported="true" kind="lib" path="lib/ApacheCommons/commons-logging.jar"/>
<classpathentry exported="true" kind="lib" path="lib/Spring-WS/spring-ws-1.5.8-all.jar"/>
<!-- [other entries] -->
<classpathentry kind="output" path="bin"/>
</classpath>
When I now add a source JAR file for "spring-ws-1.5.8-all.jar", the ".classpath" files contents is:
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry exported="true" kind="lib" path="lib/ApacheCommons/commons-logging.jar"/>
<classpathentry exported="true" kind="lib" path="lib/Spring-WS/spring-ws-1.5.8-all.jar"
sourcepath="D:/dev/sources/spring-ws-1.5.8-sources.jar"/>
<!-- [other entries] -->
<classpathentry kind="output" path="bin"/>
</classpath>
As you can see, Eclipse added the "sourcepath" attribute to the "classpathentry" element with an absolute path.
Now my idea is to replace the absolute path with the classpath variable "SOURCE_PATH", which is correctly set to "D:/dev/sources".
(Please, don't ask why we have this setup or suggest we must change it; it is an old project and we are unfortunately not able/allowed to change the build structure).
I tried
sourcepath="SOURCE_PATH/spring-ws-1.5.8-sources.jar"
as well as
sourcepath="${SOURCE_PATH}/spring-ws-1.5.8-sources.jar"
but both variants do not work.
I seems, that I either use the wrong syntax or I don't understand the concept of classpath variables. Maybe the classpath variable can't be used for the "sourcepath" attribute?
Thanks a lot for your help!
I might not understand your question completely but it sounds like you added your jar file with an absolute path to begin with. Instead add it with a classpath variable.
Use the Project properties, select Java Build Path option. Then click on the Libraries tab. Then Add Variable.... If you haven't created your SOURCE_PATH classpath variable yet, you can do it from here by clicking the Configure Variables... button (just a shortcut to the proper workspace preference setting). Once configured you should see your SOURCE_PATH class path variable in the box at the top. You can click on it extend to Extend... it to a subfolder or a jar file.
Using Tod's answer above, if you have lots of jars in lots of projects, you may find it easier to edit the .classpath files directly. Using a Java Build Path variable in .classpath changes the reference from:
<classpathentry kind="lib" path="/full/pathTo/Jar.jar"/>
to:
<classpathentry kind="var" path="NEW_PATH_VARIABLE/Jar.jar"/>
You could use a symbolic link. Windows also supports paths starting with /. This is drive dependent. Try cd / on the Command Prompt to verify.

Can a java .classpath refer to a .jar file within the eclipse plugin folder independant of install location?

I have an Eclipse plugin which stores its class library at \plugins\edu.wpi.first.javadev.sunspotfrcsdk_1.0.6.5\sunspotfrcsdk\lib\WPILibJ\classes.jar within the Eclipse install directory. At present, the .classpath uses an absolute path, so breaks when the project is run on another computer.
How can I make the .classpath refer to a .jar file using a path relative to the eclipse install directory?
Plugins should generally be referenced in eclipse .classpath as Libraries not Jars.
if you look at the .classpath file you'll see this distinction:
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry kind="src" path="webdriver-tests"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
<classpathentry kind="lib" path="lib-new/test/hamcrest-all.jar"/>
The kind src is a source folder the kind con is a Library, and kind lib is regular jar.
You'll notice the kind="con" points to a static container for the library and is not dependent on a path. Plugins should provide this container and you can add them to your build path through project context menu
Build Path->Configure Build Path...->Add Library
Here's a screenshot:
Note that all developers will need the plugin installed for this to work.

Reading a file from a jar, or anywhere on the classpath?

I'm trying to build an application that builds a resource file into a jar, but I'd like to have the project runnable within eclipse. I have a basic maven 2 structure for my project, and I'm unsure how to read in the file such that it's found and used when run from the JAR or from within eclipse. Thought?
Structure:
src/main/java
src/main/resources/file.txt
Current reading method:
getClass().getResourceAsStream("/file.txt")
Is there reading method that will pick up src/main/resources/*, as well as the root level of the JAR (where resources are deployed)?
I don't understand your problem. Resources from src/main/resources are automatically copied over to target/classes and are thus available on the classpath under Maven and Eclipse relatively to the root level at the same location (unless your Eclipse project is not properly configured).
And when packaged inside a JAR, the content of target/classes is packaged "as is" so nothing is changed.
In other words, accessing your file.txt like this is perfectly fine (and this is actually how things are documented):
// Retrieve resource
InputStream is = getClass().getResourceAsStream( "/file.txt" );
// Do something with the resource
...
If you have a problem somewhere, please clarify.
Update: I did a quick test with the maven-eclipse-plugin and I can't reproduce your problem:
$ mvn archetype:generate -DgroupId=com.stackoverflow -DartifactId=q2467362 -Dversion=1.0-SNAPSHOT
...
$ cd q2467362
$ mkdir -p src/main/resources
$ mvn eclipse:eclipse
...
$ cat .classpath
<classpath>
<classpathentry kind="src" path="src/test/java" output="target/test-classes" including="**/*.java"/>
<classpathentry kind="src" path="src/main/java" including="**/*.java"/>
<classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>
<classpathentry kind="output" path="target/classes"/>
<classpathentry kind="var" path="M2_REPO/junit/junit/3.8.1/junit-3.8.1.jar" sourcepath="M2_REPO/junit/junit/3.8.1/junit-3.8.1-sources.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
</classpath>
The directory src/main/resources is added as source folder as expected. Can you show your POM (especially the resources element if you define one)?
Anything that is put in src/main/resources using maven2 will be placed in the root level of the jar. So the method you are currently using will satisfy both conditions.
From the Maven page:
http://maven.apache.org/guides/getting-started/index.html#How_do_I_add_resources_to_my_JAR

How to set build paths automatically in Eclipse

Whenever I update our project's code from the svn I have to set the build paths of the libraries I import again because the last person who made a commit has a different classpath from mine.
Is there a way in Eclipse to automatically put in the imported libraries after updating from the SVN? I have heard of build files (Ant,Maven) but I really am not sure if I am looking at the right thing.
How about this: Don't commit local classpath files to the repository as ".classpath".
I don't mean to be a smartass, but it's ridiculous to allow people to check things in which break other developers' environments.
It is fine to not add .classpath/.project files if your project is simple and has few external dependencies. In practice you often have a number of relationships to maintain, so the overhead of making your .classpath portable is much less than the cumulative overhead of redefining it each time you bring the project into a workspace. The more involved your configuration, the more subtle errors you'll be fighting against attempting to reconstitute the project configuration.
You should be able to set up your classpath so it is portable by using Variables and Libraries, this avoids the need to hard-code paths. Your team can agree on a standard set of variables (and/or Libraries) to be used. A variable would then need to be defined on each developer's machine pointing to the common resources you use in your path.
Even better than Variables are Libraries. You can define custom libraries (under Window->Preferences->Java->Build Path->User Libraries) to reference your common components, then reuse those libraries in each project. A configured library can be exported from the User Libraries page and used by your peers.
Plugins such as m2eclipse provide Libraries (also know as Classpath Containers) that can automatically generate content based on some configuration (the Maven POM in m2eclipse's case). This abstracts the paths to underlying resources and allows multiple jars to be added to the path dynamically.
If you're not using Maven, the typical .classpath issue is that you want to add all jars in a folder to the classpath. This answer shows how it is possible to define a custom plugin to contribute all jars in a folder via a Classpath Container, you can also use this approach to automatically attach sources to the discovered elements and avoid having to repeat this effort each time.
Here is a typical before on the .classpath for a project I worked on recently. The library makes the configuration much lsess verbose, more portable, allows for reuse across projects, and defines the source attachments.
Before:
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/xml-apis.jar" sourcepath="C:/apache-ant-1.7.1/src/main"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant.jar" sourcepath="C:/apache-ant-1.7.1/src/main"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-antlr.jar" sourcepath="C:/apache-ant-1.7.1/src/main"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-apache-bcel.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-apache-bsf.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-apache-log4j.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-apache-oro.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-apache-regexp.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-apache-resolver.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-commons-logging.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-commons-net.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-jai.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-javamail.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-jdepend.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-jmf.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-jsch.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-junit.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-launcher.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-netrexx.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-nodeps.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-starteam.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-stylebook.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-swing.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-testutil.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-trax.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/ant-weblogic.jar"/>
<classpathentry kind="lib" path="C:/apache-ant-1.7.1/lib/xercesImpl.jar"/>
After:
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<!--all ant jars and source attachments defined here -->
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ant"/>
The maven dependency management and maven eclipse plugin would be one solution.
Once you have a running maven setup you can create the .project and .classpath files with the eclipse plugin. These files won't be checked in (all information is in the maven pom file).
Either don't check in classpath files, or use the same directory structure on each developer's machine.
Ant + Ivy is another solution. As far as I know there is no ivy -> eclipse task. We used ant + ivy in one of our projects and created the .classpath and .project files from the ivy metadata. (This was ivy 1.x maybe ivy 2 is capable to do this already.) This is analogous to the maven approach.

Categories