Access `sun.security.x509` in JDK 11 without modules? - java

(tl,dr at the end)
We have a small method that generates self-signed SSL certificate and it obviously depends on sun.security.x509. Currently we are still building it using JDK8 because of that, even though the rest of the codebase (it's only small, single library) is build using JDK11 and run with JVM11.
Unfortunately there aren't replacement in the main JDK, as per (and CertificateFactory has little to nothing with generating certificates, contrary to what it's javadoc states…):
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8165481
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8058778
One option would be to use BouncyCastle, but that's additional 4MB that we really don't need, especially for such small task so I was pondering ways to access it while
From what I saw, the package and required classes are still package and relevant classes are still there (see sun.security.x509 on github but when building it (using maven) I get error:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project: Compilation failure: Compilation failure:
[ERROR] OldSelfSignedCertificateGenerator.java:[20,25] package sun.security.x509 does not exist
[ERROR] OldSelfSignedCertificateGenerator.java:[71,45] cannot find symbol
[ERROR] symbol: class X509CertInfo
[ERROR] location: class OldSelfSignedCertificateGenerator
I was searching a bit and adding:
<arg>--add-exports</arg><arg>java.base/sun.security.x509=ALL-UNNAMED</arg>
to maven-compiler-plugin and it somewhat worked - I only get WARNING not regarding sun.security.x509 package:
[WARNING] OldSelfSignedCertificateGenerator.java:[20,25] sun.security.x509.AlgorithmId is internal proprietary API and may be removed in a future release
BUT! Now it seems I entered (unwillingly!) module system and it complains about access to other, basic Java classes (and one more our dependency):
[ERROR] CertificateUtil.java:[35,17] package java.util.logging is not visible
(package java.util.logging is declared in module java.logging, but module java.base does not read it)
I tried adding java.logging module in the same manner to exports but without much success. It also seems that I would have to convert both this library and it's dependency to module system, which is not really desired.
The question is somewhat related to How to generate a self-signed certificate using only JDK supported classes?
tl,dr;
is there a way to compile library using sun.security.x509 package under JDK 11 without module system? Some simple switch?

It turns out that presumably it has to do with the fact that builds produced by newer JDK (9+) Versions won't be executable under JDK8:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>9</source>
<target>9</target>
<release combine.self="override"></release>
<compilerArgs>
<arg>--add-exports</arg><arg>java.base/sun.security.x509=ALL-UNNAMED</arg>
</compilerArgs>
</configuration>
</plugin>

To include sun.security.[somePackage] classes in gradle you may add:
tasks.withType(AbstractCompile) {
options.compilerArgs += ["--add-exports", "java.base/sun.security.util=ALL-UNNAMED"]
options.compilerArgs += ["--add-exports", "java.base/sun.security.pkcs=ALL-UNNAMED"]
}

Related

Not finding automatic modules when compiling Java Application

I have a large multi module (100s) Java project and have been experimenting with adopting java module support. This is using Java 17 (temurin), gradle 7.6, and IntelliJ 2022.3.
I have hit a couple of stubborn errors with java modules where the module cannot be found.
I have one project which has some java code that uses plexus ie:
import org.codehaus.plexus.util.Base64;
...
byte[] encodedAuthorizationString = Base64.encodeBase64(authorizationString.getBytes(StandardCharsets.US_ASCII));
It has a gradle dependency
implementation 'org.codehaus.plexus:plexus-utils'
This has a version constraint in our main build.gradle (just salient lines included):
plexusVersion = '3.5.0'
implementation("org.codehaus.plexus:plexus-utils:${plexusVersion}")
Prior to adding module support this is working fine.
Now, with a module-info.java:
module egeria.open.metadata.implementation.adapters.open.connectors.rest.client.connectors.spring.rest.client.connector.main {
requires egeria.open.metadata.implementation.adapters.authentication.plugins.http.helper.main;
requires egeria.open.metadata.implementation.adapters.open.connectors.rest.client.connectors.rest.client.connectors.api.main;
//requires egeria.open.metadata.implementation.adapters.open.connectors.rest.client.connectors.rest.client.factory.main;
requires egeria.open.metadata.implementation.frameworks.open.connector.framework.main;
requires plexus.utils;
requires org.slf4j;
requires spring.core;
requires spring.web;
exports org.odpi.openmetadata.adapters.connectors.restclients.spring;
}
I am getting a compile error
Task ':open-metadata-implementation:adapters:open-connectors:rest-client-connectors:spring-rest-client-connector:compileJava' is not up-to-date because:
Task has failed previously.
The input changes require a full rebuild for incremental task ':open-metadata-implementation:adapters:open-connectors:rest-client-connectors:spring-rest-client-connector:compileJava'.
Full recompilation is required because no incremental change information is available. This is usually caused by clean builds or changing compiler arguments.
Compiling with toolchain '/Library/Java/JavaVirtualMachines/temurin-19.jdk/Contents/Home'.
Compiling with JDK Java compiler API.
/Users/jonesn/IdeaProjects/egeria/v4/open-metadata-implementation/adapters/open-connectors/rest-client-connectors/spring-rest-client-connector/src/main/java/module-info.java:6: error: module not found: plexus.utils
requires plexus.utils;
^
1 error
This is despite the fact, that having downloaded the jar file, the automatic module name looks to be what I am using ie:
jar --file=/Users/jonesn/Downloads/plexus-utils-3.5.0.jar --describe-module
No module descriptor found. Derived automatic module.
plexus.utils#3.5.0 automatic
requires java.base mandated
contains org.codehaus.plexus.util
contains org.codehaus.plexus.util.cli
contains org.codehaus.plexus.util.cli.shell
contains org.codehaus.plexus.util.dag
contains org.codehaus.plexus.util.introspection
contains org.codehaus.plexus.util.io
contains org.codehaus.plexus.util.reflection
contains org.codehaus.plexus.util.xml
contains org.codehaus.plexus.util.xml.pull
I am seeing the same error with kafka-clients
For most other code, including those libraries without full module support, all is good....
tried various compilers, such as openjdk 17 & temurin 19
built at cli & within IntelliJ
I was expecting this module to resolve ok
I have also reviewed Java 9 automatic modules not found but note that other automatic modules (including org.slf4j) are working just fine
I should add that I could refactor this code to use java.util.Base64 (probably makes sense)... but I'm still confused as to why the module error, which I also see in another project with 'kafka.clients'

How to use jlink with automated libraries

I am having a problem where I can not use jlink for compiling and I now kind of know what is wrong: jlink can not compile automated modules because they have unstable names. Is there a workaround or a fix for this? Here are the relevant parts of my code:
module-info.java
module org.example {
requires MathParser.org.mXparser;
exports org.example;
}
pom.xml
...
<dependency>
<groupId>org.mariuszgromada.math</groupId>
<artifactId>MathParser.org-mXparser</artifactId>
<version>4.4.2</version>
</dependency>
...
Main.java
...
import org.mariuszgromada.math.mxparser.*;
...
When compiling with jlink, it gives this error message:
Required filename-based automodules detected. Please don't publish this project to a public artifact repository!
This question is no duplicate because it was not answered yet. The suggested question did not receive a fix or a workaround. Still it answers the technical things: What does "Required filename-based automodules detected." warning mean?
No, there is no workaround for your case. jlink doesn't support automatic modules (even stable names will not help). You need to convert your automatic module to an explicit module first. The good news is that you don't have to recompile your library. You can generate a module declaration with jdeps --generate-module-info and then inject it into the JAR. This was described in this question.

Maven jar dependency issue package not found on OpenShift server

I'm getting a dependency issue with a jar I'm attempting to use.
I receive the following error
remote: [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2:compile (default-compile) on project sparq: Compilation failure: Compilation failure:
remote: [ERROR] /var/lib/openshift/55846322500446673d000007/app-root/runtime/repo/src/main/java/ServerQuery.java:[3,0] error: package com.github.koraktor.steamcondenser does not exist
remote: [ERROR] /var/lib/openshift/55846322500446673d000007/app-root/runtime/repo/src/main/java/ServerQuery.java:[8,8] error: cannot find symbol
remote: [ERROR] class ServerQuery
remote: [ERROR] /var/lib/openshift/55846322500446673d000007/app-root/runtime/repo/src/main/java/ServerQuery.java:[8,34] error: cannot find symbol
Here is the offending java file.
package helpers;
import com.github.koraktor.steamcondenser.*;
public class ServerQuery {
public static String getPlayers() {
SourceServer server = new SourceServer("66.150.155.152",27015);
server.initialize();
return server.toString();
}
}
I've added the following dependency to my pom.xml
<dependency>
<groupId>com.github.koraktor</groupId>
<artifactId>steam-condenser</artifactId>
<version>1.3.9</version>
</dependency>
I've also added the following action_hook pre_build script
mvn install:install-file -Dfile=./app-root/repo/steam-condenser.jar -DgroupId=com.github.koraktor -DartifactId=steam-condenser -Dversion=1.3.9 -Dpackaging=jar
Here's the GitHub for the project
https://github.com/koraktor/steam-condenser-java
And the website for it
http://koraktor.de/steam-condenser/usage/
Any ideas? Completely lost. Help much appreciated.
Since you are including the jar file in your project already, trying to manage the dependency with Maven seems like overkill. You should be able to put the jar file in your project's lib directory like this article describes. Then you won't need to configure that dependency in Maven at all.
I would use Maven for any dependencies that you want to download at the time your application is being built. Any jar files that you are checking into your project shouldn't need to be configured in Maven.
Just by looking at the question and the excerpts provided, I believe you are struggling with the basics of Maven. If I understand the situation correctly you have a library (which is not written by you):
once added to your project as a Maven dependency. This seems reasonable if you want to use it.
once the source code of the library incorrectly added to your own Java project.
remote: [ERROR] /var/lib/openshift/55846322500446673d000007/app-root/runtime/repo/src/main/java/ServerQuery.java:[3,0] error: package com.github.koraktor.steamcondenser does not exist
Based on the errormessage above it seems you have copied one of the sourcefiles from the library into your project. This is now causing problems. The main one is that without your source-folder (src/main/java) correctly representing the package structure declared in the source file (com.github...) it cannot be compiled. Hence the errormessage:
package com.github.koraktor.steamcondenser does not exist.
First of all you need to remove this copy-pasted file entirely an just use the dependency-management feature of Maven to get the library on classpath. After that just follow the examples given by the author of the library using the link you have already found (http://koraktor.de/steam-condenser/usage/).

maven-javadoc-plugin: How can I exclude resource folders which violate Java package naming conventions?

I am trying to generate an aggregated set of javadocs from a collection of related projects, like so.
In a nutshell, this POM project declares a bunch of dependencies and then uses the maven-javadoc-plugin's <includeDependencySources>true</includeDependencySources> option.
Some of the dependencies have a script-templates folder in their resources, which gets lumped into the "-sources" JAR by the maven-source-plugin.
Unfortunately, it seems the javadoc tool dislikes folders with violate java package naming conventions. So my build ultimately fails with:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-javadoc-plugin:2.9.1:jar (attach-javadocs) on project imagej-javadoc: MavenReportException: Error while creating archive:
[ERROR] Exit code: 1 - javadoc: error - Illegal package name: "script-templates.Java"
I tried adding <excludePackageNames>script-templates</excludePackageNames> to the maven-javadoc-plugin configuration, but it seemed to have no effect.
Does anyone have ideas how to work around this problem?
Have you tried the fakeClass source modification?
<sourceModifications>
<sourceModification>
<className>fakeClass</className>
<includes>
<include name="script-templates.java"/>
</includes>
</sourceModification>
</sourceModifications>

com.sun.xml.internal.ws.client does not exist

I'm trying to catch ClientTransportException and my program fails on compilation stage with the following exception
[ERROR]\workspace\rates\java\service\bundle1\src\main\java\com\connector\ws\TestClass1.java:[72,70] package com.sun.xml.internal.ws.client does not exist
As I know this package is from rt.jar and exist in jre
If I add #SuppressWarnings("restriction") it compiles from Eclipse Maven Plugin, but not from IntelliJ Idea(via maven) or command line neither.
When I remove #SuppressWarnings Eclipse show the following warning
Access restriction: The type ClientTransportException is not accessible due to restriction on required library C:\Program Files\Java\jre6\lib\rt.jar
I've found similar question but it's answer isn't clear enough for me cause I can this class in rt.jar and my IntelliJ Idea can see it either.
Can someone explain such behavior and possible solution for it?
According to this FAQ it's a bad practice to directly call 'sun' packages. When I ran into the same problem it was fixed by catching javax.xml.ws.WebServiceException instead (as sugested by artbristol).
You can get rid of this error using :
javac -XDignore.symbol.file=true
That's the argument to pass to javac to use rt.jar instead of ct.sym (ct.sym is used by default and required for compiling to a target older version)
ct.symdoes not contains all classes from rt.jar. Because using sun.* classes should not be used the class stub for them might not be present in in ct.sym making the compilation fails.
Removing calls to sun.* should remove this issue. (It's a bad practice to use sun packages)
References :
https://blogs.oracle.com/geertjan/ctsym-steals-the-asm-class
The truth of the matter is that there's something called "ct.sym" in the JDK. When javac is compiling code, it doesn't link against rt.jar. Instead, it uses a special symbol file lib/ct.sym with class stubs. Internal JDK classes are not put in that symbol file, since those are internal classes. You shouldn't want to use them, at all.
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6778491
This is not a compiler issue. javac is behaving correctly, according to the information provided in ct.sym.
The issue belongs with those who decide what should be available with (and what should be hidden by) ct.sym
I cannot as yet determine the correct category for this bug.
This is intentional. Perhaps the package name "com.sun.xml.internal...." might be seen as a hint.
Users should not write code that depends on internal JDK implementation classes. Such classes are internal implementation details of the JDK and subject to change without notice.
http://openjdk.java.net/jeps/247
For JDK N and --release M, M < N, signature data of the documented APIs of release M of the platform is needed. This data is stored in the $JDK_ROOT/lib/ct.sym file, which is similar, but not the same, as the file of the same name in JDK 8. The ct.sym file is a ZIP file containing stripped-down class files corresponding to class files from the target platform versions.
For JDK N and --release N,the JDK's own image is used as the source of the class files to compile against. The list of observable modules is limited, however, to the documented modules and the jdk.unsupported module.
NOTE
In this case, it would be better to not use the ClientTransportException class and replaced it by javax.xml.ws.WebServiceException, as suggested by artbristol.
Jre System library restricts some packages access to compiler, while they are accessible to JDK. In that case there will be no error in code but when compiling it will show errors like class not found or package not found.
In that case there are two practices.
1) Add rt.jar of jre system library to your build path for compiling and building.
2) Add jaxws-rt.jar in your build path.
Second option is a good option as it will avoid adding duplicate libraries to your build path.
import this dependency in pom.xml
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>2.1.4</version>
</dependency>
Even in 2015, I've found many projects that use this bad practice of importing com.sun.* packages.
If you (like me) can't change the classes importing those packages, adding rt.jar to your classpath should do the trick.
Note that the said rt.jar is usually found under <jdk_home>/jre/lib folder.
The solution is quite simple: when you copy the ready-made code or write the code first and then load the dependencies, there is a dependency conflicts. com.sun.xml.* package is already part of JDK8, but Maven does not see it when compiling. So make sure that you use the package from mvn:repo:/...rt.jar not jdk* / .../rt.jar.
Even I was facing same issue in my maven project. I had imported
import com.sun.xml.internal.ws.client.ResponseContext; in one of class file but this was not in use.
I just commented the line in my class file and the error stopped and i could successful run my maven project.
For maven build adding the following plugin will resolve the issue.
Basically adding the compiler arguments to refer correct path of tools.jar
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArguments>
<bootclasspath>${java.home}/lib/rt.jar${path.separator}${java.home}/lib/jce.jar${path.separator}${java.home}/../lib/tools.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
You should not use com.sun.* packages.
We could solve the problem by using our own class instead:
/**
* Copy of com.sun.xml.internal.ws.client.BindingProviderProperties since we're
* not allowed to use com.sun.* packages..
*/
public final class BindingProviderProperties {
public static final java.lang.String CONNECT_TIMEOUT = "com.sun.xml.internal.ws.connect.timeout";
public static final java.lang.String REQUEST_TIMEOUT = "com.sun.xml.internal.ws.request.timeout";
}

Categories

Resources