Matthias Heinlein
Matthias Heinlein

Reputation: 55

Include library for JAXB into JAR file without using Maven

I have a Java project in Eclipse that uses javax.xml.bind.JAXB classes. Starting the application from inside Eclipse works perfectly. However, when I export the project as (runnable) jar file and run it using java -jar myfile.jar it terminates with a java.lang.NoClassDefFoundError: javax/xml/bin/JAXBException.

Also playing around with the three options for Library handling in Eclipse Runnable JAR File Specification (extract, package, sub-folder) does not solve the problem - in fact, no libraries are exported in any case.

It seems that the library for JAXB (it seems to be rt.jar) is not considered as required library to be included into the jar file. However, when running the jar file, it is not found nevertheless. I have read that the library must be added to the classpath but this seems strange to me as rt.jar is part of the standard libraries. Is there something special about this library?

Currently, I do not use Maven or something similar for dependency and build management and if possible I want to avoid it for the future. I think, there also must be a way without Maven.

I found several posts here on SO and in Google but was not able to work out a solution for me.

Thank you very much!

Upvotes: 1

Views: 9043

Answers (3)

Piotr P. Karwasz
Piotr P. Karwasz

Reputation: 16055

As remarked in the comments, Eclipse probably uses a different Java version than your system (by default). The JAXB API and implementation is not available in JRE 11.

To work on all versions of Java, your best option is:

  • Download the JAXB RI distribution. Nowadays I'll choose version 3.0 (which is binary incompatible with the one in Java 8, since it uses jakarta.xml instead of javax.xml for the packages name) as in Juliano's answer:

https://repo1.maven.org/maven2/com/sun/xml/bind/jaxb-ri/3.0.0/jaxb-ri-3.0.0.zip

  • Copy the 4 files jakarta.activation.jar, jakarta.xml.bind-api.jar, jaxb-core.jar and jaxb-impl.jar from the mod folder into the library folder of your project (let's say lib),
  • Add the 4 libraries to the project's "Build Path",
  • Make sure you use JAXB 3.0 throughout your code (the packages of the annotations and classes start with jakarta.xml)
  • Run the application once in Eclipse, so it updates the Run Configuration (or update the classpath of the Run Configuration yourself),
  • Export the project to a JAR file.

Among the three export options proposed by Eclipse: "extract required libraries" will create a so-called fat jar (everything in one JAR-file). It works, but it deletes the licence notices in the JAXB jars (so it can not be distributed). "copy required libraries" is your best option, but then you have to move the jar file together with the subfolder. _". "package required libraries" will not work, since jars in a jar are not read by the JVM (unlike JARs in a WAR package).


Edit by the author of the question: The above worked for me well except that I experienced small differences how the two libraries (javax.xml in Java 8 and jakarta.xml in version 3.0) handle @XmlAttribute annotations. In javax.xml, I could place an annotation without further arguments on the public getter-method, e.g.

@XmlAttribute
public String getDescription() {
   return "";
}

And this worked when the attribute name in the xml file is description. However, with jakarta.xml I had to add the name of the attribute:

@XmlAttribute(name="description")
public String getDescription() {
   return "";
}

Just in the case, that others experience the same problem.

Upvotes: 2

user2862981
user2862981

Reputation: 294

The easiest way is to use JDK 8 (or older JDK) that has embedded the required jaxb library. The hard way requires that you set your CLASSPATH variable pointing to each required jaxb jar file.

From spec at https://javaee.github.io/jaxb-v2/doc/user-guide/release-documentation.html#a-2-3-0, the following jars are required using a java version 11 or above.

  • jaxb-api.jar
  • jaxb-core.jar
  • jaxb-impl.jar

A good article on this question is https://www.jesperdj.com/2018/09/30/jaxb-on-java-9-10-11-and-beyond/

Upvotes: 1

Juliano Suman Curti
Juliano Suman Curti

Reputation: 416

I thought about this myself too, since I am new to java.

There is a description of a Extension Mechanism in the java tutorials (SE), but it is no longer used since deprecated by Oracle. See, just to know of what I am talking about: https://docs.oracle.com/javase/tutorial/ext/index.html

What was this Extension thing in a nutshell: just drop your jar files inside the jdk lib and you could use the import keyword in all your classes to use the new jar file.

However, others had to do the same thing in their computers to run a class which imported your own update to the jdk.

Maven do something like the above. It searches on the pom file which other jar files it should include in your jar when you build an application. Hence, it may run anywhere.

Another way of looking into this is the answer which you should try to do. A clunckier way of doing what Maven does without its pom structure is to create a new folder inside your src folder and copy the jakarta.xml.bind-api.jar. Just like when you create an object (aJavaBean) and need to use it in another class.

The file you need to include in your library is available at: https://repo1.maven.org/maven2/com/sun/xml/bind/jaxb-ri/3.0.0/jaxb-ri-3.0.0.zip

Finally, extract the classes inside this newly created folder and use the import keyword in the classes that depend on it just like when you create your own classes.


Another thing you should try is to use the manifest file when making your jar. https://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html

This tutorial shows how to include a classpath to the files you need to run as a dependency. Make sure that everything you need is inside the newly created jar file. Also, set the entry point in the manifest, so your application can run just using

    java -jar MyJar.jar

in the command line.

Upvotes: 1

Related Questions