Postgres PL/JAVA: ошибка java.lang.ClassNotFoundException после загрузки файла JAR в базу данных
Я получаю исключение java.lang.ClassNotFoundException: ошибка внутри Postgres при запуске функции, которая вызывает загруженный файл JAR. Я установил и сконфигурировал PL/JAVA (включая предоставленные примеры) в своей базе данных и могу запустить примеры к успеху. Я не пытаюсь загрузить / установить свой первый JAR, но я делаю что-то не так.
Мой хост контролирует версию ОС: CentOS 6.8. Postgres - это версия 8.4.
Я пытаюсь установить свой собственный очень простой Java-класс, который является производным от предоставленного примера класса Parameters.addOne. Весь мой код находится в /tmp. Вот шаги, которые я выполнил:
Doug.java:
package com.msmetric;
import java.math.BigDecimal;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import java.util.logging.Logger;
public class Doug {
public static int addOne(int value) {
return value + 1;
}
}
Скомпилируйте Doug.java, используя 'javac Doug.java'.
Создайте файл JAR с файлом Doug.class, используя 'jar -cvf Doug.jar Doug.class. Это отлично работает.
Теперь я загружаю файл JAR в Postgres (общедоступную схему), изменяю classpath, создаю функцию, которая вызывает JAR, а затем пытаюсь запустить в приглашении psql.
Запустите sqlj.install_jar из psql:
select sqlj.install_jar('file:/tmp/Doug.jar','Doug',false);
Задайте путь к классам внутри Postgres (из приглашения psql postgres=#):
select sqlj.set_classpath('public','Doug');
Создайте функцию, которая вызывает JAR. Этот код функции создания взят непосредственно из файла examples.ddr, поставляемого с PL/JAVA. Я просто изменил org.postgres на com.msmetric.
create or replace function addone(int) returns int as 'com.msmetric.Doug.addOne(java.lang.Integer)' language java;
Теперь с загруженным JAR и созданной функцией я пытаюсь запустить его. Эта функция должна просто добавить 1 к предоставленному номеру.
select addone(3);
Результаты: ОШИБКА: java.lang.ClassNotFoundException: com.msmetric.Doug
Мысли?
1 ответ
Мне очень жаль, что я не увидела ваш вопрос раньше. Под всеми экзотическими деталями (PostgreSQL, PL/Java, схемы, пути к классам...), здесь происходит лишь немного базовой Java: если файл jar содержит класс Doug.class
в упаковке com.msmetric
его путь внутри банки должен отражать это: он должен быть com/msmetric/Doug.class
, В противном случае он не будет найден.
Вы можете настроить всю эту структуру шаг за шагом:
javac Doug.java
mkdir com
mkdir com/msmetric
mv Doug.class com/msmetric/
jar -cvf Doug.jar com/msmetric/Doug.class
Или вы можете позволить javac
сделать больше работы для вас:
mkdir classes
javac -d classes Doug.java
jar -cvf Doug.jar -C classes .
Когда вы даете javac
-d
опция каталога, а не просто запись файлов классов рядом с их .java
Источники, он поместит их все на свои места в каталоге, который вы назвали, а затем вы можете просто сказать jar
переместиться в этот каталог и вылить их все на стол (не забывайте .
в конце этого jar
команда).
Как только вы исправите это, если вы попытаетесь повторить свои первоначальные шаги, вы увидите, что теперь вы получите другую ошибку:
ERROR: Unable to find static method com.msmetric.Doug.addOne with signature (Ljava/lang/Integer;)I
Это происходит потому, что вы объявили функцию в Doug.java
с int addOne(int value)
(то есть, принимая примитив int
аргумент), но вы объявили это в SQL с returns int as 'com.msmetric.Doug.addOne(java.lang.Integer)'
принимая Integer
объект.
Как только вы исправите это:
create or replace function addone(int) returns int as 'com.msmetric.Doug.addOne(int)' language java;
вы сможете увидеть:
# select addone(3);
addone
--------
4
(1 row)
Если вам посчастливилось увидеть этот запоздалый ответ, могу я спросить, какую версию PL / Java вы используете? Это одна деталь, которую вы не упомянули. Если он старше 1.5.0, есть новые функции, которые могут вам помочь. Например, вы можете просто аннотировать эту функцию:
@Function
public static int addOne(int value) {
return value + 1;
}
и имеют javac
выплюнуть не только Doug.class
файл, но и pljava.ddr
файл с вашей декларацией функции SQL, уже написанной правильно (не путая типы аргументов!). Есть способ включить это .ddr
файл в банку, которую вы создаете, так что вы можете просто позвонить sqlj.install_jar
с последним параметром true
поэтому он запускает команды в .ddr
и ваши функции готовы к использованию. В документации есть пример Hello, world, который показывает больше того, как это делается.
Ура,
-Глава