I have an Oracle 12 database and I'm trying to load a Java function so that it can be called from PL/SQL.
I've written a NetBeans project to test my function and it works fine.
However, inside Oracle, it cannot compile.
One factor is that it references a library of about 75 jar files.
I loaded these jars into the database earlier using
loadjava -u ......... *.jar -jarasresource
(These are the same jars that are part of the NetBeans library.)
The source was loaded into the database using loadjava:
loadjava -u ......... -r -v -genmissing PictureGenerator.java
The error messages mention the classes in the import statements.
StandardCharsets is part of the JDK, isn't it?
The other imported classes are included in the jar files I loaded.
Please tell me what to do to get my class to resolve within Oracle.
Here's the source:
package gov.nlm.structuredepictor;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import chemaxon.formats.MolExporter;
import chemaxon.formats.MolImporter;
import chemaxon.struc.Molecule;
public class PictureGenerator
{
public static byte[] getPngForMol(String molString, String sbFormat)
{
MolImporter mi = null;
try
{
ByteArrayInputStream inStream = new ByteArrayInputStream(molString.getBytes(StandardCharsets.UTF_8));
if (inStream == null)
{
System.err.print("Error creating ByteArrayInputStream");
return null;
}
mi = new MolImporter(inStream);
Molecule mol = mi.read();
mi.close();
byte[] b = MolExporter.exportToBinFormat(mol, sbFormat);
return b;
} catch (Exception ex1)
{
System.err.println("Error creeating MolImporter: " + ex1.getMessage());
//Logger.getLogger(PictureGenerator.class.getName()).log(Level.SEVERE, null, ex1);
}
return null;
}
}
Thanks for the suggestion about the JDK version! I changed the DB to use JDK 7 and was able to compile without errors. The next step was to declare the PL/SQL function
create or replace function getPngForMol(molString varchar2, sbFormat varchar2) return raw
as LANGUAGE JAVA
Name 'gov.nlm.structuredepictor.PictureGenerator.getPngForMol(java.lang.String, java.lang.String)
return byte[]';
This compiled without error. However, at runtime, I get this error:
Error report -
ORA-29532: Java call terminated by uncaught Java exception: java.lang.NoClassDefFoundError
ORA-06512: at "CHEM.GETPNGFORMOL", line 1
ORA-06512: at line 11
29532. 00000 - "Java call terminated by uncaught Java exception: %s"
*Cause: A Java exception or error was signaled and could not be
resolved by the Java code.
*Action: Modify Java code, if this behavior is not intended.
Does this suggest anything?
Related
I downloaded and installed the free Spire.Doc.jar file to work with .docx files. When I run it within Netbeans the functionality works fine however when I attempt to build the program I am getting the following error:
warning: Supported source version 'RELEASE_6' from annotation processor 'org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor' less than -source '1.8'
Note: Creating static metadata factory ...
error: com.sun.tools.javac.code.Symbol$CompletionFailure: class file for com.spire.doc.packages.spryOb$1
not found
An annotation processor threw an uncaught exception.
Consult the following stack trace for details.
java.lang.RuntimeException: com.sun.tools.javac.code.Symbol$CompletionFailure: class file for com.spire.doc.packages.spryOb$1 not found
I have added the .jar file to my class path however there appears to be a class file missing from the com.spire.packages location.
Does anyone know if this is a Netbeans issue or does it look like there is an issue with the .jar file? I find it strange that it works when I run it within Netbeans but the above error occurs when I attempt to build the project.
I managed to get my application to build. What I had to do was remove the following code from my class and then it worked:
document.getMailMerge().MergeImageField = new MergeImageFieldEventHandler()
{
#Override
public void invoke(Object sender, MergeImageFieldEventArgs args)
{
mailMerge_MergeImageField(sender, args);
}
};
private static void mailMerge_MergeImageField(Object sender, MergeImageFieldEventArgs field)
{
String filePath = field.getImageFileName();
if (filePath != null && !"".equals(filePath))
{
try
{
field.setImage(filePath);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
I'm not sure why it didn't work with this included however I got this code from the following website:
https://www.c-sharpcorner.com/article/how-to-perform-mail-merge-in-word-document-in-java/
therefore I will inform them in case this happens to someone else in the future.
I'm using Google OR-tools library (v6.4) for a project (though my question is not specific to this library). This consists of one jar, which has a few native dependencies (a bunch of ".so"/".dylib" object files, depending on the OS). This build for my project is being made on Ubuntu 14.04
The problem I'm facing: On trying to load a specific object file at runtime (using System.load()), I'm getting an UnsatisfiedLinkError with the message as "undefined symbol" (I've added the stacktrace below). However, I am loading the object file defining this symbol just before this, so I'm not sure why this error is being thrown.
I'm loading the dependencies in the following way: The object files are being packed into the jar created by Maven during build, and are being extracted and loaded (using System.load()) at runtime. The method for that is as follows:
public class EnvironmentUtils {
public static void loadResourceFromJar(String prefix, String suffix) {
String tempFilesDirectory = System.getProperty("java.io.tmpdir");
File tempFile = null;
try {
tempFile = new File(tempFilesDirectory + "/" + prefix + suffix);
tempFile.deleteOnExit();
try (final InputStream inputStream = EnvironmentUtils.class.getClassLoader().
getResourceAsStream(prefix+suffix)) {
if (inputStream == null) {
throw new RuntimeException(prefix + suffix + " was not found inside JAR.");
} else {
Files.copy(inputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
}
System.load(tempFile.getAbsolutePath());
} catch (Exception e) {
//Log top 10 lines of stack trace
}
}
}
This method is being called inside a static block for all dependencies:
public class DummyClass {
static {
String sharedLibraryExtension = EnvironmentUtils.getSharedLibraryExtension(); //.so for linux, .dylib for Mac
String jniLibraryExtension = EnvironmentUtils.getJniLibraryExtension(); //.so for linux, .jnilib for Mac
EnvironmentUtils.loadResourceFromJar("libfap", sharedLibraryExtension);
EnvironmentUtils.loadResourceFromJar("libcvrptw_lib", sharedLibraryExtension);
EnvironmentUtils.loadResourceFromJar("libortools", sharedLibraryExtension);
EnvironmentUtils.loadResourceFromJar("libdimacs", sharedLibraryExtension);
EnvironmentUtils.loadResourceFromJar("libjniortools", jniLibraryExtension);
}
}
On running System.load() for libdimacs.so, an UnsatisfiedLinkError is thrown. Stacktrace:
java.lang.UnsatisfiedLinkError: /tmp/libdimacs.so: /tmp/libdimacs.so: undefined symbol: _ZN6google14FlagRegistererC1IbEEPKcS3_S3_PT_S5_
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1086)
at com.(PROJECT_NAME).utils.EnvironmentUtils.loadResourceFromJar(EnvironmentUtils.java:78)
at com.(PROJECT_NAME).DummyClass.<clinit>(DummyClass.java:28)
However, this symbol "_ZN6google14FlagRegistererC1IbEEPKcS3_S3_PT_S5_" is present in libortools.so, which is being loaded before libdimacs. I verified this by running the following command:
objdump -t (LIBRARY_PATH)/libortools.so | grep _ZN6google14FlagRegistererC1IbEEPKcS3_S3_PT_S5_
This gave me the following output:
0000000000ce12cc gw F .text 00000091 _ZN6google14FlagRegistererC1IbEEPKcS3_S3_PT_S5_
So it would seem that the symbol should have been defined at the time of the System.load() call, unless there was some issue in loading the containing object file. To check if the object file had been loaded correctly, I used the approach detailed in this solution. Apart from the class detailed in that answer, I added the following lines after System.load() call in EnvironmentUtils.loadResourceFromJar() to print the most recently loaded library name:
public class EnvironmentUtils {
public static void loadResourceFromJar(String prefix, String suffix) {
...
System.load(tempFile.getAbsolutePath());
final String[] libraries = ClassScope.getLoadedLibraries(ClassLoader.getSystemClassLoader());
System.out.println(libraries[libraries.length - 1]);
}
}
The output (till just before the UnsatisfiedLinkError) is as follows:
/tmp/libfap.so
/tmp/libcvrptw_lib.so
/tmp/libortools.so
So libortools.so seems to be loading correctly, which means the symbol should be loaded in memory. The exact same code is working perfectly with the corresponding Mac (".dylib") dependencies (Built on MacOS Sierra 10.12.5). Would appreciate any advice on resolving this. Thank you.
I'm apologize that the java artifact may be broken currently...
you can use c++filt to demangle the symbol ;)
c++filt _ZN6google14FlagRegistererC1IbEEPKcS3_S3_PT_S5_
google::FlagRegisterer::FlagRegisterer<bool>(char const*, char const*, char const*, bool*, bool*)
In fact gflag has recently change its namespace from google:: to gflags:: and glog or protobobuf? try to find the correct one and I guess it failed...
note: Still not completely sure whose is the bad guy who use the google:: namespace since libortools merge all its static dependencies but I guess now you understand the bug...
note2: I have a patch in mizux/shared branch https://github.com/google/or-tools/commit/805bc0600f4b5645114da704a0eb04a0b1058e28#diff-e8590fe6fb5044985c8bf8c9e73c0d88R114
warning: this branch is currently broken and not ready yet. I'm trying ,for unix, to move from static to dynamic dependencies, so I need to fix all rpath, transitives deps etc... and in the process I also had to fix this issue (that I didn't reproduced while using static dependencies)
If too long to finish (we should create a release 6.7.2 or 6.8 (i.e. new artifact) by the end of May 2018) which maybe only contains this fix and not my branch...
I am using java methods in PL/SQL and recently I have stumbled upon this error :
An error was encounterd performing the request operation:
ORA-29548: Release of Java system classes in database (12.1.0.2.171017
1.6) does not match that of the oracle executable (12.1.0.2.180116 1.6)
29548. 00000 = "Java system class reported" %s"
What should I do to make it work?
Make sure the java version you use to compile and the version installed in ORACLE both are same.
select dbms_java.get_ojvm_property ('java.version')
from dual
Although, you can let Oracle do compile the source code directly.
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "Azam/Azam_Test" as package Azam;
import java.lang.*;
public class Azam_Test {
public static String Azam_Test_Print(String testString) {
System.out.println(testString);
return testString;
}
}
I want to use matlab function in java application. I create java package from my function by deploytool in matlab. Now, how can i use this package? Can only import the jar file created by deploytool in my java project and use its function?
After a lot of googling, I used this toturial but in the final step, i get error "could not load file".
Also i read about MatlabControl, but in this solution, we should have matlab environment in our system to java code running. But i will run my final app in systems that may not have matlab at all.
So i need a solution to run matlab function in java class even in absence of matlab environment.
Finally I solve my problem. the solution step by step is as follows:
write matlab function:
function y = makesqr(x)
y = magic(x);
Use deploytool in matlab and create java package.
3.create new java application in Eclipse and add main class. import javabuilde.jar and makesqr.jar:
import com.mathworks.toolbox.javabuilder.MWArray;
import com.mathworks.toolbox.javabuilder.MWClassID;
import com.mathworks.toolbox.javabuilder.MWNumericArray;
import makesqr.Class1;
and main.java:
public class main {
public static void main(String[] args) {
MWNumericArray n = null;
Object[] result = null;
Class1 theMagic = null;
try
{
n = new MWNumericArray(Double.valueOf(5),MWClassID.DOUBLE);
theMagic = new Class1();
result = theMagic.makesqr(1, n);
System.out.println(result[0]);
}
catch (Exception e)
{
System.out.println("Exception: " + e.toString());
}
finally
{
MWArray.disposeArray(n);
MWArray.disposeArray(result);
theMagic.dispose();
}
}
}
add javabuilder.jar and makesqr.jar to java build path of your project.
run it.
the Double.valueOf(3), define the input for our function and the output is as follows:
8 1 6
3 5 7
4 9 2
I didn't get properly your problem. Did you already compile the jar file from Matlab code and you are trying to use that, or you are at the last step of the tutorial?
If your answer is the latest case, most probably you forgot the "." before the class path.
From tutorial you linked:
You must be sure to place a dot (.) in the first position of the class path. If it not, you get a message stating that Java cannot load the class.
Also check if the matlab compiler path ("c:\Program Files\MATLAB\MATLAB Compiler Runtime\v82\toolbox\javabuilder\jar\javabuilder.jar" - in the tutorial) is correct for your system.
I get back an error indicating java.sql.SQLException: No suitable driver found for
jdbc:postgresql://localhost:
5432/testDBMS
import java.sql.*;
import java.util.*;
public class JdbcPostgresqlConnection {
public static void main(String[] args) {
Connection conn3 = null;
try {
String dbURL3 = "jdbc:postgresql://localhost:5432/testDBMS";
Properties parameters = new Properties();
parameters.put("user", "pgmrHere");
parameters.put("password", "111111");
conn3 = DriverManager.getConnection(dbURL3, parameters);
}
catch (SQLException ex) { ex.printStackTrace(); }
}
}
java -cp . JdbcPostgresqlConnection
So, clearly, the only thing that is in the classpath is the current directory (.). The postgresql driver jar is not. You need to add it to the classpath:
java -cp .:/path/to/driver.jar JdbcPostgresqlConnection
on Linux/MacOS, or
java -cp .;c:\path\to\driver.jar JdbcPostgresqlConnection
on Windows.
The syntax to compile was - java -cp .;"C:\Program Files\PostgreSQL\9.3\lib\postgresql-9.3-1102.jdbc4.jar" JdbcPostgresqlConnection. Note 2 things; the quotes around the jar specification and the jar files cannot be in a folder with a space in the name. This is normally not the case on *nix system, but is often encountered in Windows systems. Note too, that when I put the jar file in the same folder with the java program I could eliminate the double quotes - java -cp .;C:\AZ_Fantasy5\postgresql-9.3-1102.jdbc4.jar JdbcPostgresqlConnection. Special thanks to JB Nizet for pointing out this situation.
As the error says java -cp . JdbcPostgresqlConnection java.sql.SQLException:
No suitable driver found for jdbc:postgresql://localhost: 5432/testDBMS
Which means you didnot include the postgresql.jar in your classpath
Try executing like this and I'm assuming it is Windows OS by seeing your error
java -cp .;pathOfYourDriverjar/postgresql.jar JdbcPostgresqlConnection
Did you not load the driver in your code? Either define the jdbc.drivers property setting it to org.postgresql.Driver or add Class.forName("org.postgresql.Driver") to your code.