Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Language IDEs » Java Development Tools (JDT) » trying to port project to Java 9 using Oxygen.1a, can't figure out errors(apologies for the long post)
trying to port project to Java 9 using Oxygen.1a, can't figure out errors [message #1775706] Fri, 03 November 2017 17:04 Go to next message
J. Zufallig is currently offline J. ZufalligFriend
Messages: 15
Registered: May 2013
Junior Member
We have a project that builds and runs under Java 8. But it uses some of the JAXB stuff, so it no longer builds nor runs under Java 9, now that those APIs are "deprecated" (meaning, broken unless you move to Java 9 and adopt modules). It's an executable JAR file and most of the users are on Windows, so the runtime workaround of passing --add-modules to the java launcher is not applicable: the users double-click a .jar file and expect it to work.

According to JEP 261, we can't build in "legacy mode" (because then we can't see the JAXB stuff) nor in "single-module mode" (because we have to use a module-info.java file at build time instead of --add-modules at runtime). So we're stuck having to go to full-on "multi-module mode". Okay, fine, whatever, it's not the first time Oracle has shoved a new technology into our faces that we don't need.

Installed JDK 9.0.1 and Oxygen.1a. Updated the execution environments and the project compiler compliance. For now, source and target are both 9. (I'm seeing a lot of references on the intartubez that the way to go for this kind of situation is building module-info.java targeting 9, and the rest of the project targeting Java [1.]8. That's easy to do in our Ant's build.xml, but for Eclipse it would be a pain since it can't do file-specific settings.) I kludge together a module-info.java file requiring a bunch of java.* modules -- none of the JAXB stuff yet, I'll get to that later.

The JEP says that multi-module mode is triggered by the use of --module-source-path. Eclipse has no way of showing "here's what the equivalent javac command-line options would have been", but my guess is that --module-source-path corresponds to having one or more entries under Modulepath in Project -> Build Path.

Initially, in the project's Build Path -> Libraries, I kept all of the third-party JARs on the classpath. None of them export modules and were written against Java 6 or 7, after all, so keeping them on the classpath seems like the right thing to do. However, those JARs are completely ignored by the Eclipse compiler, leading to thousands of can't-find-this-type errors on the 'import' statements. The JARs are still showing up properly under "Referenced Libraries" in the package explorer, and expanding them properly shows their packages and classes. But the classpath seems to be completely ignored altogether. I can't find a setting controlling this.

After hunting through google, I tried toggling the "Is Modular" setting under each third-party JAR. This seems like a complete kludge since none of them export a module, but JEP 261 claims that they will magically be treated like special modules based on the JAR's filename. Okay, I mark them all as modules. I add appropriate "requires" lines to the module-info.java file. For example, slf4j-api-1.7.25.jar is now under Modulepath, with "requires slf4j.api;" in the module-info. No errors on that line, so presumably it's finding the definitions.

(I know an SLF4J 1.8 beta is out with actual module exports. We don't want to ship beta code. And this is just an example anyhow; there are several more such JARs.)

But now I'm getting bizarre errors in the source anytime I use the fully-qualified class name of one of those third-party "modules". Continuing the example, anytime the source code refers to org.slf4j.Logger there's now an error from Eclipse, "The package org.slf4j is accessible from more than one module: " but then it doesn't say which modules or where from or anything else.

Note that the "import org.slf4j.Logger;" lines elsewhere in the project are fine. It's just any explicit reference to the full class name, anywhere, which generates these errors. I don't know how to begin to solve that, or even how to work around it -- and yes, the full class names need to be there.

I think, ideally, I'd prefer to move all these JARs back to the classpath, but then I don't know how to solve the problem of the classpath being ignored at compile time.

(As you can tell, there's also more than a little frustration at Java 9 imposing an unwanted technology on us that, to date, has caused only problems and not helped us solve anything.)

[Updated on: Fri, 03 November 2017 17:05]

Report message to a moderator

Re: trying to port project to Java 9 using Oxygen.1a, can't figure out errors [message #1775708 is a reply to message #1775706] Fri, 03 November 2017 17:58 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1526
Registered: July 2009
Senior Member
Also we had our "surprises" when implementing support for Java 9, and I won't claim that Oxygen.1a is without quirks nor bugs in this area.

But let's be pragmatic and address one issue at a time:

The distinction between Single-module mode and Multi-module mode should, AFAICS, not make any difference within an IDE. In my understanding this distinction is only relevant for telling javac which folders represent modules vs. packages, and which files are associated with which module. In JLS all these issues are explicitly unspecified, and left to the discretion of the "host system", where javac is one host system, and build tools, IDEs are different host systems - so each may define its own rules in this regard.

Two things that are semantically relevant, though: (1) Are you compiling sources in an unnamed module or a named module (in Eclipse: a project without / with module-info.java in the root of a source folder)? (2) Are dependencies considered as legacy on the classpath, or as modules on the module path? This is what toggling "Is modular" toggles in the first place (note that you can add dependencies directly to the Module Path which should directly set "Is modular").

Usage of -classpath in otherwise modular builds is probably not a solution:
from JEP 261:
It is possible to put arbitrary classes and JAR files on the class path in this mode, but that is not recommended since it amounts to treating those classes and JAR files as part of the module being compiled.


And frankly I'm not even sure why compilers ignore the classpath as soon as module-info.java is part of the compilation, but Eclipse and javac seem consistent in this regard ...

Quote:
"The package org.slf4j is accessible from more than one module: "


This finally looks like a straight bug in JDT. It would be cool if you could isolate an example and file a bug against JDT/Core.
Re: trying to port project to Java 9 using Oxygen.1a, can't figure out errors [message #1775710 is a reply to message #1775708] Fri, 03 November 2017 19:29 Go to previous messageGo to next message
J. Zufallig is currently offline J. ZufalligFriend
Messages: 15
Registered: May 2013
Junior Member
Stephan Herrmann wrote on Fri, 03 November 2017 13:58
In JLS all these issues are explicitly unspecified, and left to the discretion of the "host system", where javac is one host system, and build tools, IDEs are different host systems - so each may define its own rules in this regard.


Ahhhh, that's good to know. I had wondered about the apparent underspecification in the JLS; I hadn't realized it was deliberate.

Quote:
Two things that are semantically relevant, though: (1) Are you compiling sources in an unnamed module or a named module (in Eclipse: a project without / with module-info.java in the root of a source folder)?


A named module, but only because module-info.java seems to be the only way to get java.xml.bind pulled in at runtime without the (unavailable to us) options to the java launcher.

We don't want to use modules, or module-info.java, or any of the rest of this stuff "ourselves", so to speak. All of this is just trying to make an executable JAR that's equally usable under Java 8 or Java 9; all the rest of these jumping through hoops is all with that goal in mind. If we could have achieved that goal using only some clever command-line options to javac/jar, that would have been great.

Quote:
(2) Are dependencies considered as legacy on the classpath, or as modules on the module path?


It makes no difference to us. Java 9 modules are trying to solve a problem that we don't have. We'll cheerfully designate third-party libraries that were released yesterday as "legacy" if it means the damn thing will continue to work under Oracle's new definition of "deprecated".

from JEP 261:
It is possible to put arbitrary classes and JAR files on the class path in this mode, but that is not recommended since it amounts to treating those classes and JAR files as part of the module being compiled.


See, that sounds like it would solve our "problem" perfectly. I see nothing wrong with that scenario. I don't care if all the third-party library stuff becomes part of our "module" because we don't have a module.

If I knew how to get the tools to actually do that, I would consider that to be the most appropriate solution for now.

The requires java.xml.bind; statement in module-info.java actually caused errors for us, until we found this answer of yours describing how to get that to work in Oxygen.1a. I wish I understood what effect the answer is having, precisely, but maybe I don't need to. :-)

Possibly the way to go would be for us to get rid of module-info.java, and instead find one of the standalone JAXB implementations. We'd end up shipping a duplicate of the code that's already installed on every user's computer, but meh, Oracle's going to remove it someday anyhow. (By that point, hopefully, we'll have moved the project away from using XML at all, and won't even need JAXB.) If shipping a replacement is something we'd need to do eventually, starting now might be best...

Quote:
"The package org.slf4j is accessible from more than one module: "


This finally looks like a straight bug in JDT. It would be cool if you could isolate an example and file a bug against JDT/Core.[/quote]

I will try. Combining an import

import org.slf4j.Logger;


with a fully qualified mention of the name

private static final org.slf4j.Logger example()
{
    org.slf4j.Logger foo;
    return null;
}


was what did it for us; the above has no problem with the import, but causes two errors on each mention in the function.
Re: trying to port project to Java 9 using Oxygen.1a, can't figure out errors [message #1775719 is a reply to message #1775710] Fri, 03 November 2017 22:37 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1526
Registered: July 2009
Senior Member
Quote:
[ ... regarding -classpath ...] See, that sounds like it would solve our "problem" perfectly. I see nothing wrong with that scenario. I don't care if all the third-party library stuff becomes part of our "module" because we don't have a module.

If I knew how to get the tools to actually do that, I would consider that to be the most appropriate solution for now.


We might have a bug here, we may have to ensure that jars on the classpath are considered part of the currently compiled module.
Since javac seems to have the same bug, we should first consult JLS authors about the intention.
I filed https://bugs.eclipse.org/526831 to follow-up.

Regarding making java.xml.bind accessible: don't worry, once you have a module and once we fixed https://bugs.eclipse.org/526054 (tests are running as we speak) this will no longer be necessary.

I could not reproduce your problem regarding slf4j. Please create a minimal example, zip and attach it in a new bug in bugzilla. Make sure that .project and .classpath are contained in the zip. TIA.
Re: trying to port project to Java 9 using Oxygen.1a, can't figure out errors [message #1775822 is a reply to message #1775719] Mon, 06 November 2017 19:40 Go to previous messageGo to next message
J. Zufallig is currently offline J. ZufalligFriend
Messages: 15
Registered: May 2013
Junior Member
Actually, all of this may have just become moot for reasons below. If I get time I'll try to make a new project to duplicate the "accessible from more than one module" error, whether it's using SLF4J or not as the third party module. For now, I've just changed the project build path back to Java 8 and told it to exclude module-info.java.

Here's why none of it matters for us. When an executable JAR (which is what we're building) is launched using java -jar foo.jar (which is what the command line will be under Windows) then according to the spec, module-info.class is deliberately ignored, which means none of the "requires" lines take effect... which means that the JAXB stuff is still unavailable... which means that Java 9 completely torpedoes the project. Having finally gotten Ant+javac to build an executable JAR using a Java 9 module-info.class, I've been launching it in a development environment with java -verbose:module --show-module-resolution and can verify that none of the "requires" lines are taking effect from the default startup. And sure enough, NoClassDefFoundError referring to javax.xml.bind.JAXBException follows shortly thereafter, meaning all of the module-info.java work was so much wasted effort.

I hadn't noticed that module-info is ignored for executable JARs without special command-line launcher options, and of course those options aren't going to happen under Windows. In all the desperate searching for something that would compile, I missed that part of the JLS/JEP changes. My mistake.

The rest is just me thinking aloud. Feel free to ignore:

So... using the standard JAXB stuff isn't an option, since there's no mechanism for us to require the EE XML modules. In the immediate term, we'll have to get the standalone JAXB implementation and build it into our own JAR to ship. Regarding Java 9, the standalone JAXB release says "Implementation and tool jars jaxb-core, jaxb-impl, jaxb-xjc and jaxb-jxc contain split packages and cannot be used as JPMS automatic modules." so possibly we have to ship it all under some other merged package name to prevent the JRE from hosing us with name clashes. After that, in the short term we need to migrate away from using JAXB at all, since apparently JAXB is such a bad thing that we didn't even get a single major release of Java where it only caused warnings before they broke it. In the medium/long term... we need to reconsider whether Java is still a useful platform for our project, given how hostile this release has been to developers and how much our customer base hates installing the JRE. I'm sure the Oracle/OpenJDK cathedral have no problem handwaving away problems with "just launch with these options" but in the real world that's not always under our control.

Possibly we can get a JNLP file to launch the software instead, and use java-vm-args to pass along all the magic handwavy add-module options. Then we reduce the problem to fighting with JWS when there's no codebase= parameter, which still is retardedly limited despite the JNLP fixes in Java 1.6. Still, it's a start. [edit: nope, Oracle's Standard Edition Deployment Guide for Java 9 says "Modular applications can be packaged as self-contained applications. They cannot be packaged as Java Web Start applications." Boy, they really don't give a rat's ass about current developers.] Relying on launching-JAR-via-double-click was a dumb thing to do, but that's another thing developers don't always get to control. It would at least buy us time until Java 10 (or "Java 18.5" or whatever other shitty number that pretends to be semantic versioning but is actually just marketing) removes JAXB and the other workarounds. That might be enough time to move to C++.

End of rant.

[Updated on: Tue, 07 November 2017 17:22]

Report message to a moderator

Re: trying to port project to Java 9 using Oxygen.1a, can't figure out errors [message #1775871 is a reply to message #1775822] Tue, 07 November 2017 12:01 Go to previous message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1526
Registered: July 2009
Senior Member
J. Zufallig wrote on Mon, 06 November 2017 20:40
If I get time I'll try to make a new project to duplicate the "accessible from more than one module" error, whether it's using SLF4J or not as the third party module.


that'd be great, thanks
Previous Topic:Inverted SWT design?
Next Topic:Error while running Eclipse for Java Developers for the first time
Goto Forum:
  


Current Time: Mon Dec 11 04:00:52 GMT 2017

Powered by FUDForum. Page generated in 0.01773 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software