How best to provide JAXB components in an RCP application - java

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.

Related

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

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.

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

Build web service with jax-ws reference implemetation bundled in JDK 6

I used to saw a tutorial about this topic. But when I try to make my example application by following the example. I can't find com.sun.xml.ws.transport.http.servlet.WSServletContextListener on my classpath.
but I found com.sun.xml.internal.ws.transport.http.servlet.WSServletContextListener
It confused me, why Oracle move those classes in com.sun.xml.xxx to com.sun.xml.internal? I am using JDK1.6.0_45. I saw some people said, form JDK6U4, jax-ws reference implementation is bundled in JDK, so we should be able to publish a web service by running a light weight http server just with JDK and no other dependencies needed, is that ture? You should notice that in the tutorial I mentioned above, additional dependencies is still needed, see step 5 "JAX-WS Dependencies".
And I also found that in IBM JDK, even com.sun.xml.internal.ws.transport.http.servlet.WSServletContextListener can't be found.
Yes, JAX-WS RI (same as JAX-B RI) is shipped with JDK since Jdk6. All the packages except for javax.xml.* are changed to .internal. in order to avoid conflicts between JDK's and standalone JAX-WS versions.
Using JDK's version, you can deploy web service using just JDK; if you want deploy WS in tomcat or in some AS, you still need JAX-WS standalone version.
If you check grepcode for (non-internal) WSServletContextListener, it shows you, the class is shipped with jaxws-rt/webservice-rt jar.
By looking for the internal WSServletContextListener, you can't find a jar shipping it. (but grepcode also contains the sources of openJDK)
Also, I tried to find WSServletContextListener in my local jdk7, but can't find it. But maybe some third-party jdk ship with the class.
Anyway, if you look into the tutorial again, you will find that jaxws-rt.jar is necessery for the application. Probably you should add it?

JAXB backward compatibility

Years ago I wrote an application that used JAXB to generate Java bindings for an XML schema. The application code and the schema have been updated quite a lot over the years, but the JAXB jars remained the same since 2008, which was when I started using JAXB for this application. I've been using Ant to build the application, including generating and compiling bindings, and everything worked fine on at least two XP Pro development machines. I made some changes to the schema and never had to think about JAXB.
Recently I tried to rebuild the application from scratch on a new laptop, and the build keeps failing. The new 64-bit laptop is running windows 7 Pro, it had a newer JDK (1.7.0_45) and a new version of Ant (1.9.3). I was able to get around some weird problems by switching to a yet newer version of ant (1.9.4) and switching to latest JAXB jars. At this point, I don't even remember what those issues were (but I can recreate them by reverting to older JAXB jars in SVN).
After upgrading JAXB, I ran into new problems. First of all, the xjc task in ant seems to be interpreting the target attribute differently; it threw some error and apparently the destdir has the semantic meaning that target used to have.
Second, this task no longer generates the impl package with the implementation classes whose names were supposed to end with Type, so the rest of my code fails with a bunch of compilation problems.
Is there a way to make the new JAXB version backward-compatible? My other options are try updating the code to work with the new bindings, which seems like a lot of unnecessary work, or reverting to old JDK and Ant.
This is a late reply to the original post. But should be good as a reference for other folks. I met the same problem. Here is what worked for me after going through much of the same struggles trying to rebuild JAXB 1.0 scheme/binding using later JDKs (8 and 7).
My goal is to build with latest JDKs without the hassle of upgrading JAXB, if possible.
JDK 7&8 failed building with JAXB 1.0 due to ClassCastException thrown from <xjc> possibly due to incompatible language features. JDK 5&6 work, however.
I went through several attempts trying to upgrade to the latest JAXB 2.11.12,
Update ant build file <xjc> task to replace target attribute with deskdir
Change binding files syntax - bindingStyle attribute was removed in <jxb:globalBindings> in the latest JAXB - we use modelGroupBinding
Adjust binding class files suffix to avoid name conflicts. Update sources for the new type names generated.
There were still remaining name conflicts and source upgrades required.
I decided to stop going further down the rabbit hole making all these changes and focus on finding just one version of JAXB that generates JDK 7&8 compatible sources but still support JAXB 1.0 schema and binding.
Newer <xjc> task supports version specification by source attribute. However, as the original poster found out, support of "1.0" was removed in later JAXB distributions
The "Illgal version 1.0" error message when using <xjc> is due to support for version 1.0 was removed in since JAXB 2.2.7 (https://jaxb.java.net/nonav/2.2.11/docs/ch02.html#a-2-2-7)
However, JAXB 2.2.6 doesn't work either. There seems to be a bug in that "jaxb-xjc.jar" version not generating sources correctly based on the attribute, resulting in the certain ClassNotFoundException during build.
I read reports on JAXB 2.1.18 failing to respect "1.0" source as well
Eventually I found JAXB 2.0.5 is to be one version that can generate JDK 7&8 compatible sources using JAXB 1.0 source schema and binding.
Drop in the JAXB-RI 2.0.5 libs and remove old jaxb-libs.jar
Add source="1.0" attribute the <xjc> task
No need to convert <xjc> "target" attribute to "deskdir" in this version
I have not tested more versions beyond 2.0.5 but it's possible there are higher versions that does the same
Your old project seems to use JAXB 1 whereas all the tools now have JAXB 2.x by default.
Try the following in the XJC task:
source="1.0"
target="1.0"
See these documents:
https://jaxb.java.net/2.2.4/docs/xjcTask.html
https://jaxb.java.net/2.2.4/docs/jaxb-1_0.html

Categories