Question
· Aug 14, 2020

How could we attach external libraries to generated code with Java Gateway Wizard: %ProcessErrorStatic+4^%Net.Remote.Proxy java.lang.NoClassDefFoundError:

Hello,

We would need some help.

We have a Java project in Eclipse which uses two external libraries, which are referenced as a maven pom.xml dependency.

We created a JAR with all the dependencies included.

We have used the Java Gateway Wizard as follows:

In the image you could see that we have chosen the project's jar, written IP and PORT of Gateway and written all external dependencies' server path separated with semicolons.

It generates the following Ensemble class:

Class radarCovidcrearToken.CCAATokenGeneratorTest Extends java.lang.Object [ ProcedureBlock ]
{

Parameter IMPORTTIMESTAMP As STRING = "1970-01-01 00:00:00.0";

Method %OnNew(ByRef p0 As %ObjectHandle) As %Status
{
    Quit:'$D(p0) $$$OK
    Quit ..%Constructor(p0,"radarCovidcrearToken.CCAATokenGeneratorTest",0)
}

ClassMethod main(ByRef p0 As %ObjectHandle, ByRef p1 As %ObjectHandle)
{
    Do ..%PreInvokeStatic(p0,"radarCovidcrearToken.CCAATokenGeneratorTest")
    Set x=$zobjexport("main",18)
    Set x=$zobjexport(-1,18)
    Do ..%WriteArray(p0,"[Ljava.lang.String;",p1)
    Set x=$zobjexport("Y1",8)
    Set id=$zobjexport(9),fun=$zobjexport(15)
    Do:fun'="Y1" ..%ProcessErrorStatic(p0,fun,id)
    Set:$zobjexport(17) p1=..%ReadArrayArgument(p0)
    Do:fun'="Y5" ..%PostInvokeStatic(p0)
}

}

 

We have written an Operation to call the previous code:

Include (%systemInclude, Ensemble)

Class Operaciones.JAVA.AppSeguimiento Extends EnsLib.JavaGateway.AbstractOperation [ ProcedureBlock ]
{

Parameter INVOCATION = "Queue";

Method generarToken(pRequest As Mensajes.Request.Seguridad.AutenticacionLDAP, Output pResponse As %Library.String(MAXLEN="")) As %Status
{
    try{
        kill %objlasterror
        #dim tSC as %Status
        #dim tJavaGateway as EnsLib.JavaGateway.JavaGateway
         Set tSC = ..GetConnection(.tJavaGateway)
        If $$$ISOK(tSC)
        {
           set echo = ##class(radarCovidcrearToken.CCAATokenGeneratorTest).%New(.tJavaGateway)    
           $$$LOGINFO("echo: "_echo)
           zwrite %objlasterror
           do echo.main(.tJavaGateway,.pResponse)
           zwrite %objlasterror
           $$$LOGINFO("pResponse: "_pResponse)
        }
    }catch ex{
        $$$LOGINFO("%objlasterror: "_%objlasterror)
    }
    
    Quit $$$OK
}

XData MessageMap
{
<MapItems>
    <MapItem MessageType="Mensajes.Request.Seguridad.AutenticacionLDAP">
        <Method>generarToken</Method>
    </MapItem>
</MapItems>
}

}

 

The Operation's configuration in the Production is:

<Item Name="Operaciones.JAVA.AppSeguimiento" Category="AppSeguimiento" ClassName="Operaciones.JAVA.AppSeguimiento" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="true" Schedule="">
    <Setting Target="Host" Name="Port">19501</Setting>
    <Setting Target="Host" Name="AdditionalPaths">/opt/contenedor/Java/AppSeguimientoAnadidaReferenciaJARSexternos.jar,/opt/contenedor/Java/aether-api-1.7.jar,/opt/contenedor/Java/aether-impl-1.7.jar,/opt/contenedor/Java/aether-spi-1.7.jar,/opt/contenedor/Java/aether-util-1.7.jar,/opt/contenedor/Java/asm-6.2.jar,/opt/contenedor/Java/bcpkix-jdk15on-1.58.jar,/opt/contenedor/Java/bcprov-jdk15on-1.58.jar,/opt/contenedor/Java/classworlds-1.1.jar,/opt/contenedor/Java/commons-cli-1.0.jar,/opt/contenedor/Java/commons-codec-1.14.jar,/opt/contenedor/Java/commons-io-2.5.jar,/opt/contenedor/Java/jackson-annotations-2.10.3.jar,/opt/contenedor/Java/jackson-core-2.10.3.jar,/opt/contenedor/Java/jackson-databind-2.10.3.jar,/opt/contenedor/Java/java-jwt-3.10.3.jar,/opt/contenedor/Java/junit-3.8.1.jar,/opt/contenedor/Java/plexus-build-api-0.0.4.jar,/opt/contenedor/Java/plexus-cipher-1.4.jar,/opt/contenedor/Java/plexus-classworlds-2.2.3.jar,/opt/contenedor/Java/plexus-compiler-api-2.8.4.jar,/opt/contenedor/Java/plexus-compiler-javac-2.8.4.jar,/opt/contenedor/Java/plexus-compiler-manager-2.8.4.jar,/opt/contenedor/Java/plexus-component-annotations-1.7.1.jar,/opt/contenedor/Java/plexus-container-default-1.0-alpha-9-stable-1.jar,/opt/contenedor/Java/plexus-interactivity-api-1.0-alpha-4.jar,/opt/contenedor/Java/plexus-interpolation-1.13.jar,/opt/contenedor/Java/plexus-interpolation-1.14.jar,/opt/contenedor/Java/plexus-java-0.9.10.jar,/opt/contenedor/Java/plexus-sec-dispatcher-1.3.jar,/opt/contenedor/Java/plexus-utils-2.0.4.jar,/opt/contenedor/Java/plexus-utils-2.0.5.jar,/opt/contenedor/Java/qdox-2.0-M9.jar,/opt/contenedor/Java/sisu-guice-2.1.7-noaop.jar,/opt/contenedor/Java/sisu-inject-bean-1.4.2.jar,/opt/contenedor/Java/sisu-inject-plexus-1.4.2.jar</Setting>
  </Item>

 

When we execute the Operation from the Production, we observe the following exception:

%objlasterror: 0 ꟈjava.lang.NoClassDefFoundError: org/bouncycastle/util/io/pem/PemReader
at radarCovidcrearToken.CCAATokenGeneratorTest.loadPrivateKeyFromPem(CCAATokenGeneratorTest.java:76)
at radarCovidcrearToken.CCAATokenGeneratorTest.run(CCAATokenGeneratorTest.java:36)
at radarCovidcrearToken.CCAATokenGeneratorTest.main(CCAATokenGeneratorTest.java:31)
at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intersys.gateway.JavaGateway.executeInstanceMethod(JavaGateway.java:996)
at com.intersys.gateway.JavaGateway.executeMethod(JavaGateway.java:942)
at com.intersys.gateway.JavaGateway.processMessage(JavaGateway.java:559)
at com.intersys.gateway.JavaGateway.run(JavaGateway.java:548)
at com.intersys.gateway.JavaGateway.run(JavaGateway.java:519)
P ESBSSCCB/e^%ProcessErrorStatic+4^%Net.Remote.Proxy.1^1;d^zmain+7^radarCovidcrearToken.CCAATokenGeneratorTest.1^1(d^^Operaciones.JAVA.AppSeguimiento.1^0(e^^Operaciones.JAVA.AppSeguimiento.1^0(e^^Operaciones.JAVA.AppSeguimiento.1^0e^zOnTask+42^En

 

We have also read this topic where Robert Cemper and Eduard Lebedyuk, explain how to show native code's exception:

https://community.intersystems.com/post/processerror6-netremoteproxy1-er...

 

How could we attach external libraries to generated code with Java Gateway Wizard?

 

EDIT: We have add in the Production's Operation's configuration: "/opt/contenedor/Java/AppSeguimientoAnadidaReferenciaJARSexternos.jar
"

Discussion (5)1
Log in or sign up to continue

Hello Kevin,

We are using the following Java version:

java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)

If we execute the command with our jar (which includes the Java program and its dependencies):

jar -tf "AppSeguimientoAnadidaReferenciaJARSexternos.jar"

We see:

META-INF/MANIFEST.MF
org/
org/eclipse/
org/eclipse/jdt/
org/eclipse/jdt/internal/
org/eclipse/jdt/internal/jarinjarloader/
org/eclipse/jdt/internal/jarinjarloader/JIJConstants.class
org/eclipse/jdt/internal/jarinjarloader/JarRsrcLoader$ManifestInfo.class
org/eclipse/jdt/internal/jarinjarloader/JarRsrcLoader.class
org/eclipse/jdt/internal/jarinjarloader/RsrcURLConnection.class
org/eclipse/jdt/internal/jarinjarloader/RsrcURLStreamHandler.class
org/eclipse/jdt/internal/jarinjarloader/RsrcURLStreamHandlerFactory.class
radarCovidcrearToken/
radarCovidcrearToken/CCAATokenGeneratorTest.class
generated_private_base64.pem
aether-api-1.7.jar
aether-impl-1.7.jar
aether-spi-1.7.jar
aether-util-1.7.jar
asm-6.2.jar
bcpkix-jdk15on-1.58.jar
bcprov-jdk15on-1.58.jar
classworlds-1.1.jar
commons-cli-1.0.jar
commons-codec-1.14.jar
commons-io-2.5.jar
jackson-annotations-2.10.3.jar
jackson-core-2.10.3.jar
jackson-databind-2.10.3.jar
java-jwt-3.10.3.jar
junit-3.8.1.jar
plexus-build-api-0.0.4.jar
plexus-cipher-1.4.jar
plexus-classworlds-2.2.3.jar
plexus-compiler-api-2.8.4.jar
plexus-compiler-javac-2.8.4.jar
plexus-compiler-manager-2.8.4.jar
plexus-component-annotations-1.7.1.jar
plexus-container-default-1.0-alpha-9-stable-1.jar
plexus-interactivity-api-1.0-alpha-4.jar
plexus-interpolation-1.13.jar
plexus-interpolation-1.14.jar
plexus-java-0.9.10.jar
plexus-sec-dispatcher-1.3.jar
plexus-utils-2.0.4.jar
plexus-utils-2.0.5.jar
qdox-2.0-M9.jar
sisu-guice-2.1.7-noaop.jar
sisu-inject-bean-1.4.2.jar
sisu-inject-plexus-1.4.2.jar
java-jwt-3.10.3_2.jar
jackson-databind-2.10.3_2.jar
jackson-annotations-2.10.3_2.jar
jackson-core-2.10.3_2.jar
commons-codec-1.14_2.jar
bcpkix-jdk15on-1.58_2.jar
bcprov-jdk15on-1.58_2.jar

If we execute the command to locate the jar where is the class which generates the NoClassDefFoundError :

jar -tf "bcprov-jdk15on-1.58.jar"

We get:

...

org/bouncycastle/util/io/pem/
org/bouncycastle/util/io/pem/PemGenerationException.class
org/bouncycastle/util/io/pem/PemHeader.class
org/bouncycastle/util/io/pem/PemObject.class
org/bouncycastle/util/io/pem/PemObjectGenerator.class
org/bouncycastle/util/io/pem/PemObjectParser.class
org/bouncycastle/util/io/pem/PemReader.class
org/bouncycastle/util/io/pem/PemWriter.class
org/bouncycastle/util/test/

...

As you would notice it outputs the name of the missing class:

org/bouncycastle/util/io/pem/PemReader.class

What could we do?

I just did some research; Jars nested within Jars is actually a use-case that is not supported by Java.

https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4735639

https://stackoverflow.com/questions/12357136/reference-jars-inside-a-jar/12357544

Supposedly there are Maven plugins you can use to help resolve your problem; but this is a well-known Java issue.