Mixed class loading in Spring Boot causes java.lang.NoSuchMethodError - java

I have a fairly complex spring boot application with uses a bunch of 3:rd part packages, among others the org.ejml math library. This library is used by several jar files in my application, for instance by the stanford-nlp and my own tsne library and my own LDA library. The lda and tsne are built as fat JARs and include the entire ejml while the stanford-nlp packages it some other way. There are different versions of the EJML library, but all use a version of EJML library that implements a method called subtract(DMatrixD1,DMatrixD1,DMatrixD1) but when I run my Spring Boot application it throws an java.lang.NoSuchMethodError: 'void org.ejml.dense.row.CommonOps_DDRM.subtract(org.ejml.data.DMatrixD1, org.ejml.data.DMatrixD1, org.ejml.data.DMatrixD1)' how can this be?
I used the -verbose:class to try to figure out where the offending code was loaded, which it seems are from the LDA library (which uses ejml-0.41), but my code path starts in the tsne library (which uses the ejml-0.39), is this the cause of the problem? Can the 0.41 version of ejml not use a DMatrix1D object from the 0.39 version although they both implement the subtract method? If so how do I fix the problem, so that (spring/java) uses the correct (0.39 version I guess) for the subtract operation...

I think you have 2 options here. You could exclude the ejml-0.41 dependency from the LDA library, so it will use ejml-0.39, but this option it is not grantee to work. The second option, which is the correct one in my opinion, is to use a version of the LDA that uses ejml-0.39 or a version of the tsne library that uses ejml-0.41 in a way that there aren't different versions of the same dependency.

Related

How best to provide JAXB components in an RCP application

My RCP application makes calls to SOAP web services and has been using the built-in JAXB/JEE components in Java 1.8. I have set up the build process to force the use of Java 1.8 and this had been working well.
Recently, the build stopped working because the builder (Tycho) now has a component which only works with later Java versions. If I compile with the later version I get 100's of JEE-related errors such as JaxbElement not found or #WebMethod not found.
At some point we will have to move away from Java 1.8 and use a Java version which does not provide those JEE components, so forcing the use of 1.8 can only be a short-term solution.
Is there an eclipse plugin which already provides those missing components? (I have searched but not found anything) Or do I need to create my own helper plugin which contains the necessary libraries? Is there perhaps a JAXB alternative which I could use for the SOAP calls?
The JAXB plugins/bundles are available on Eclipse Orbit: the plugins/bundles starting with javax..
In the plugins/bundles where they are needed, add the dependency in the MANIFEST.MF file via Import-Package (using Require-Bundle would require that these plugins/bundles are available even when using Java 8).
See also this answer.

Packaging a particular version of java with my code

I've built a standalone Java Maven app. I need a particular version of java for running my code e.g. 1.8.0.155. My target environment has an older version. E.g. 1.8.0.45.
For various reasons I'm unable to get the target system to update their version of java.
How do I just bundle a version of the jdk along with my jar?
What you're looking for is how ot create a self-contained application, this link is how you do it without any third part assistance. Another option is Launch4j, a third party wrapper.

integrating org.apache.poi and the javax.xml.stream.* package (stax-api) in android - how to set the --core-library argument in Android Studio?

I'm using Android studio 1.5.1
I'd like to include the org.apache.poi-ooxml library in my android project. To include that library I needed to include some other library dependencies, among which the stax-api library.
The problem with stax api is that it has all the packages in javax.* which is a "core library". Java jdk has all these libraries included, so if I were to use it in Java SE, I wouldn't need that stax-api library. Android, on the other hand, has a "partial" stax-api library. For android I only need the javax.xml.stream.* package. That means that I need to extract the stax-api, remove everything except the javax.xml.stram package, and repackage it again.
So I guess it is safe to use this modified library in Android. But, it has the javax.* package, which, according to Android studio is a core library, so Android Studio (or whatever component in Android Studio) gives me a warning:
trouble processing "javax/xml/stream/EventFilter.class":
Ill-advised or mistaken usage of a core class (java.* or javax.*) when
not building a core library.
This is often due to inadvertently including a core library file in
your application's project, when using an IDE (such as Eclipse). If
you are sure you're not intentionally defining a core class, then this
is the most likely explanation of what's going on.
However, you might actually be trying to define a class in a core
namespace, the source of which you may have taken, for example, from a
non-Android virtual machine project. This will most assuredly not
work. At a minimum, it jeopardizes the compatibility of your app with
future versions of the platform. It is also often of questionable
legality.
If you really intend to build a core library -- which is only
appropriate as part of creating a full virtual machine distribution,
as opposed to compiling an application -- then use the
"--core-library" option to suppress this error message.
If you go ahead and use "--core-library" but are in fact building an
application, then be forewarned that your application will still fail
to build or run, at some point. Please be prepared for angry customers
who find, for example, that your application ceases to function once
they upgrade their operating system. You will be to blame for this
problem.
If you are legitimately using some code that happens to be in a core
package, then the easiest safe alternative you have is to repackage
that code. That is, move the classes in question into your own package
namespace. This means that they will never be in conflict with core
system classes. JarJar is a tool that may help you in this endeavor.
If you find that you cannot do this, then that is an indication that
the path you are on will ultimately lead to pain, suffering, grief,
and lamentation.
So, I'd like to use this --core-library option. But where to set it?
I already looked at Android Studio ignore --core-library flag which didn't help me. I think those answers are outdated, and that's why I'm asking a new question.
What I did try:
build.gradle:
dexOptions {
coreLibrary true;
}
build.gradle:
dexOptions {
preDexLibraries = false
}
project.tasks.withType(com.android.build.gradle.tasks.Dex) {
additionalParameters=['--core-library']
}
File --> Other Settings --> Default Settings --> Compilers --> Android Compilers
and check the 'Add --core-library flag'
None of these worked. Is there any way to set that option?
EDIT: Why do I need STAX:
I'm doing some stuff with Workbook, Sheet, Columns, Cells for .xlsx files.
When I include only poi-ooxml-3.14-beta1-20151223.jar I get an error in build time saying class file for org.apache.poi.ss.usermodel.Workbook not found.
Upon including poi-3.14-beta1-20151223.jar on runtime I get, among others, Could not find method org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook.isSetBookViews, referenced from method org.apache.poi.xssf.usermodel.XSSFWorkbook.
Upon including poi-ooxml-schemas-3.14-beta1-20151223.jar during runtime I get , among others, Failed resolving Lorg/openxmlformats/schemas/spreadsheetml/x2006/main/CTWorkbook; interface 59 'Lorg/apache/xmlbeans/XmlObject; and java.lang.VerifyError: org/apache/poi/xssf/usermodel/XSSFWorkbook
Upon including xmlbeans-2.6.0.jar during runtime I get, among others, Could not find method javax.xml.stream.events.Namespace.getPrefix, referenced from method org.apache.poi.openxml4j.opc.internal.marshallers.PackagePropertiesMarshaller.getQName and java.lang.NoClassDefFoundError: javax.xml.stream.XMLEventFactory at org.apache.poi.openxml4j.opc.internal.marshallers.PackagePropertiesMarshaller.<clinit>(PackagePropertiesMarshaller.java:41)
UPDATE
So, from http://poi.apache.org/faq.html#faq-N1017E
18. Why do I get a java.lang.NoClassDefFoundError: javax/xml/stream/XMLEventFactory.newFactory()
This error indicates
that the class XMLEventFactory does not provide functionality which
POI is depending upon. There can be a number of different reasons for
this:
Outdated xml-apis.jar, stax-apis.jar or xercesImpl.jar:
These libraries were required with Java 5 and lower, but are not actually required with spec-compliant Java 6 implementations, so try
removing those libraries from your classpath. If this is not possible,
try upgrading to a newer version of those jar files.
Running IBM Java 6 (potentially as part of WebSphere Application Server): IBM Java 6 does not provide all the interfaces required by
the XML standards, only IBM Java 7 seems to provide the correct
interfaces, so try upgrading your JDK.
Sun/Oracle Java 6 with outdated patchlevel: Some of the interfaces were only included/fixed in some of the patchlevels for Java 6. Try
running with the latest available patchlevel or even better use Java
7/8 where this functionality should be available in all cases.
So, if I read this correctly, in Android, I do need a "truncated" STAX api.
There are a number of problems when you try to use Apache POI and it's depending libraries in an Android Application. Among others there are duplicate classes in xmlbeans.jar, the "javax.*" packages are prohibited by the Android compiler and a few others.
There are currently two projects which try to fix those issues:
https://github.com/andruhon/android5xlsx
https://github.com/centic9/poi-on-android/ (which I maintain)
android5xlsx provides ready-made jar-files to include in your application, but currently uses a somewhat outdated version of POI. poi-on-android is based on POI 3.15-beta1 and can be recompiled for newer versions of POI fairly easily.
Both projects are for Android 5+ and come with sample code and should allow basic usage of Apache POI on Android.
Add implementation 'javax.xml.stream:stax-api:1.0' in you app build.gradle, as some core class missed

java.lang.NoSuchMethodError: jodd.Jodd.init(Ljava/lang/Class;)V

I am trying to use the Jodd-http version 3.6.6 library in a simple application. The application runs fine on a test machine which has java 1.8 installed but when I try to run the same application on another machine with java 1.7 it throws this excption.
java.lang.NoSuchMethodError: jodd.Jodd.init(Ljava/lang/Class;)V
is this version of jodd-http is not compatible with java 1.7?
Jodd modules are distributed in two flavors:
1 .as a single bundle jar, that contain all Jodd modules in one distribution archive.
separate jar for each module.
So Jodd may be used on any platform where there is a suitable Java 7+ runtime environment.
This shouldn't be related to java version, but to existance of jodd libraries - are you sure you have jodd-core jar in your classpath?
Because jodd-http can't work without jodd-core:) And from your exception it looks like only jodd-http jar is present in the classpath; but not jodd-core.
Can you check this please?
I don't know if you use maven repo (jCentar or Maven Central), but it would be good so all this dependencies can be loaded automatically.
EDIT:
Check httpclient example in the https://github.com/oblac/jodd-quickstart
EDIT:
Check the classloaders - if they see the Jodd class (or any class from jodd-core); maybe the classloader for some reason dont see it; or there are multiple different versions of jodd-http on the classpath.

Choosing what native library to load depending on system setup

In our OSGi code, we are using Bundle-NativeCode manifest headers to choose what native libraries to load for Windows or Linux.
The problem arises when one of the libraries we need to use depends on a specific version of an already installed library (GLIBC is currently at version 2.12 in Ubuntu and 2.11 in Debian). Is there a way to identify the installed Linux flavor, or at least the version of a specific library with the Bundle-NativeCode properties? Do you know any other way around this? (please note that osname and osversion only give us "Linux" and the linux kernel version respectively, which is not enough)
Thanks!
No, the OSGi native code filtering does not provide that level of dependency for externally sourced packages. Other than trying to include the specific version of your dependency in the bundle as well (which of course wouldn't work with glibc) you can't achieve this through the Native-Code alone.
One alternative is to not use the Native-Code and instead use your bundle to load the fragment code on demand, by using a different name. So you have Linux\Glibc\211 and Linux\Glibc\212, and then based on the runtime of your bundle's startup, can manually call the System.loadLibrary() yourself.

Categories