Java Stored Procedure в субд Oracle на примере формирования PDF-файла

от автора

Всем доброго времени суток!
Недавно имел опыт создания функций (хранимых процедур) на языке Java в СУБД Oracle (Java Stored Procedures). Постараюсь описать шаги по созданию таких функций, расмотрев пример работы с pdf-файлом.

Вот, что для этого потребуется:

  • СУБД Oracle (в моем случае версии 10)
  • библиотеки iText (версия 1.4.8)
  • Java-код, реализующий требуемые функции


Важно знать, что, в зависимости от версии СУБД Oracle, с ней (с системой) может быть уставлена различная версия JVM (Java Virtual Machine). В 10-ой версии СУБД установлена JVM 1.4. А это значит, что при написании кода Java версию языка нужно использовать такую же.

Загрузка библиотек в СУБД

Код на языке Java оперирует существующими методами классов библиотеки iText. В связи с этим, мы должны сначала загрузить библиотекe в субд. В этом нам поможет команда loadjava. Сами библиотеки должны быть скомпилированы с использованием java версии 1.4. Поэтому я и выбрал itext 1.4.8. Кроме это требовалось загрузить сопутствующие библиотеки. Вот последовательность загрузки библиотек iText:

  • loadjava -resolve -verbose -thin -user user/password@ip-addres:port:TNS_NAME bcprov-jdk14-149.jar
  • loadjava -resolve -verbose -thin -user user/password@ip-addres:port:TNS_NAME bcpkix-jdk14-149.jar
  • loadjava -resolve -verbose -thin -user user/password@ip-addres:port:TNS_NAME bcmail-jdk14-149.jar
  • loadjava -resolve -verbose -thin -user user/password@ip-addres:port:TNS_NAME itext-1.4.8.jar

Сделать это можно удаленно. Для этого указываются пользовательские данные и параметры соединения с сервером.

Загрузка нашего Java-кода

До того, чтобы создать функции в базе данных мы должны загрузить наш собственный код в СУБД. В примере я открываю существующий файл, добавляю изображения и сохраняю в новый файл. Вот код:

create or replace and compile java source named "MyJavaPdf" as import java.io.FileOutputStream; import java.io.IOException; import com.lowagie.text.Annotation; import com.lowagie.text.DocumentException; import com.lowagie.text.Image; import com.lowagie.text.pdf.PdfContentByte; import com.lowagie.text.pdf.PdfReader; import com.lowagie.text.pdf.PdfStamper;  public class PdfGenerator{       public static final float LLX1 = 50;      public static final float LLY1 = 50;      public static final float W1 = 100;      public static final float H1 = 100;       public static final float LLX2 = 200;      public static final float LLY2 = 50;      public static final float W2 = 100;      public static final float H2 = 100;       public static final float LLX3 = 350;      public static final float LLY3 = 50;      public static final float W3 = 100;      public static final float H3 = 100;        public static String addSignsToPdf(String path, String input,               String output, String imm1, String imm2, String imm3) {           String result = null;                      try {                System.out.println("PDF Editing: START...");                System.out.println("Files path: " + path);                               System.out.println("Input file: " + input);                PdfReader reader = new PdfReader(path + input);                               System.out.println("Output file: " + output);                               PdfStamper stamper = new PdfStamper(reader,                         new FileOutputStream(path + output));                PdfContentByte canvas = stamper.getOverContent(1);                canvas.saveState();                canvas.setRGBColorFill(0xFF, 0xFF, 0xFF);                canvas.rectangle(LLX1, LLY1, W1, H1);                canvas.rectangle(LLX2, LLY2, W2, H2);                canvas.rectangle(LLX3, LLY3, W3, H3);                canvas.fill();                canvas.restoreState();                System.out.println("Image 1: " + imm1);                System.out.println("Image 2: " + imm2);                System.out.println("Image 3: " + imm3);                putImage(canvas, Image.getInstance(path + imm1),                         "IMMAGINE 1", LLX1, LLY1, W1, H1);                putImage(canvas, Image.getInstance(path + imm2),                         "IMMAGINE 2", LLX2, LLY2, W2, H2);                putImage(canvas, Image.getInstance(path + imm3),                         "IMMAGINE 3", LLX3, LLY3, W3, H3);                stamper.close();                result="OK";                System.out.println("PDF Editing: TERMINATED.");                sendStaffMailWithAttachment(path + output);           } catch (IOException e) {                result="ERROR";                for(int i=0; i<e.getStackTrace().length;i++){                            result += "\n\t\t\t" + e.getStackTrace()[i];                }                return result;           } catch (DocumentException e) {                result="ERROR";                for(int i=0; i<e.getStackTrace().length;i++){                            result += "\n\t\t\t" + e.getStackTrace()[i];                }                return result;           } catch (IllegalArgumentException e) {                result="ERROR";                for(int i=0; i<e.getStackTrace().length;i++){                            result += "\n\t\t\t" + e.getStackTrace()[i];                }                return result;           }           return result;      }       private static void putImage(PdfContentByte canvas, Image img,               String url, float llx, float lly, float w, float h)               throws DocumentException {           img.scaleToFit(w, h);           float offsetX = w / 2f;           float offsetY = h / 2f;           img.setAbsolutePosition(llx + offsetX, lly + offsetY);           img.setAnnotation(new Annotation(0, 0, 0, 0, url));           canvas.addImage(img);      } }; 

«compile» дает указание скомпилировать данный код в класс. Кроме такого варианта можно использовать имеющийся файл *.class

Создание функции, использующей java-класс

Теперь мы можем создать функцию на основе нашего java-класса. Это достаточно просто:

create or replace function createPdf(   files_path in VARCHAR2,                                             input_file in VARCHAR2,                                             output_file in VARCHAR2,                                             picture1 in VARCHAR2,                                             picture2 in VARCHAR2,                                             picture3 in VARCHAR2)        return VARCHAR2                                                                         as language java     name 'PdfGenerator.addSignsToPdf(java.lang.String, java.lang.String,          java.lang.String, java.lang.String, java.lang.String, java.lang.String)          return java.lang.String'; / 

Указываем здесь входные параметры и тип возвращаемого значения.

Настройка доступа к директориям

Исходный и сформированный файлы хранятся на сервере СУБД, поэтому мы должны создать директорию в Oracle и раздать права на нее:

create directory PDFDIR as '/home/oracle/PDF' ; commit; grant ALL on directory PDFDIR to PUBLIC;  exec dbms_java.grant_permission('SchemaUser','java.util.PropertyPermission','*','read,write'); exec dbms_java.grant_permission('SchemaUser','java.net.SocketPermission','*','connect, resolve'); exec dbms_java.grant_permission('SchemaUser', 'SYS:java.io.FilePermission', '/home/oracle/PDF/*', 'read,write'); commit; /

Пример использования функции

Теперь мы можем использовать данную функцию:

select createPdf('/home/oracle/PDF/', 'INPUT.PDF', 'OUTPUT.PDF', 'picture1.jpg', 'picture2.jpg', 'picture3.jpg') from dual;

Надеюсь, что кому-то данный пример пригодится. Не судите строго, это мой первый пост на хабре.

Желаю всем успехов! Спасибо за внимание!

ссылка на оригинал статьи http://habrahabr.ru/post/197940/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *