Java Stored Procedures

Dúvidas, dicas e truques de PL/SQL. Aqui também vão assuntos relacionados a pacotes, triggers, funções, Java-Stored Procedures, etc
  

Mensagemem Seg, 13 Dez 2004 9:44 am

E ai pessoal, não sei se essa é a área certa pra esse assunto, mas gostaria de saber como funciona o processo de criar e executar procedimentos em Java no banco, passo a passo.
Se alguém souber e puder me ajudar, obrigado.
lamanita
Localização: Porto Alegre - RS

Samuel, o lamanit@

Mensagemem Seg, 13 Dez 2004 10:34 am

Bem, existe duas formas de se fazer isso.
Uma delas, é quando você tem o FONTE do programa (o arquivo .java). Outra, é quando você só tem o bytecode (ou seja, o .class)

Vamos lá:

SEM O FONTE - LOADJAVA

Se você só tem a classe, deve carregar ela para dentro do Oracle. Aí vai um exemplo:



Código: Selecionar todos
--=======================
--== CRIACAO DA CLASSE ==
--=======================
-- Em um arquivo txt crie seu código

public class StoreProcedureJava {
public static String Procedimento (){
return "Estah String veio de cohdigo java";
};
}

-- Salve o Arquivo com o mesmo nome da classe mais a extensao .java
-- compile o arquivo: javac StoreProcedureJava.java
-- note que será gerado o bitecode (.class)

--==========================
--== ARMAZENANDO NO BANCO ==
--==========================
-- loadjava é um utilitario que vem com o banco, deverá estar em
$ORACLE_HOME/bin

loadjava.bat -user esd/esd StoreProcedureJava.class

--==========================
--== Verificando a Criacao
--==========================
select OBJECT_NAME, OBJECT_TYPE, CREATED from USER_OBJECTS
where upper(OBJECT_NAME) = upper('StoreProcedureJava')
/

--====================================================
--== Criando uma Funcao PL/SQL para Chamar a Classe
--====================================================
-- Atencao na sintaxe, Classe.funcao/procedimento.

create or replace function JavaOracle return varchar2 AS
LANGUAGE JAVA NAME 'StoreProcedureJava.Procedimento() return
java.lang.String';
/

--=======================
--== Executando a Classe
--=======================
select JavaOracle() from dual;




Agora, vai um exemplo com passagem de parametro.
Código: Selecionar todos
-- ======================================================================
-- ================ EXEMPLO DE PASSAGEM DE PARAMETROS ===================
-- ======================================================================

--=======================
--== CRIACAO DA CLASSE ==
--=======================

public class StoreProcedureJava {

public static String Procedimento (java.lang.String Texto){
return "Estah String veio de cohdigo java: " + Texto;
};


public static void main (String args[]){
file://System.out.println(Procedimento("TESTE"));
};

}

--==========================
--== ARMAZENANDO NO BANCO ==
--==========================
loadjava.bat -user esd/esd StoreProcedureJava.class

--==========================
--== Verificando a Criacao
--==========================
select OBJECT_NAME, OBJECT_TYPE, CREATED from USER_OBJECTS
where upper(OBJECT_NAME) = upper('StoreProcedureJava')
/

--====================================================
--== Criando uma Funcao PL/SQL para Chamar a Classe
--====================================================
CREATE OR REPLACE function JavaOracle(p1 IN VARCHAR2) return VARCHAR2 AS
LANGUAGE JAVA NAME 'StoreProcedureJava.Procedimento(java.lang.String) return
java.lang.String';
/

--=======================
--== Executando a Classe
--=======================
select JavaOracle('funciona !!!') from dual;
/

-- Resultado: Estah String veio de cohdigo java: funciona !!!





COM O FONTE

O exemplo abaixo Mostra como criar uma função em Java, que depois será chamada na função PL/SQL chamada RUN . Note-se que a função RUN deve ser alimentada com o nome/path completo do executável a ser rodado. Se for desejado comando do SO, criar uma batch e passar a batch como argumento.

Código: Selecionar todos
create or replace and compile java source named "RunCommand" as
import java.util.*;
import java.io.*;

public class RunCommand extends Object
{
  static String result;
  public static String getOutput(){
     return result;
  }

  public static int RunThis(String args)
  {
  Runtime rt = Runtime.getRuntime();
  int        rc = -1;

  try
  {
     Process p = rt.exec(args);

     int bufSize = 4096;
     BufferedInputStream bis =
      new BufferedInputStream(p.getInputStream(), bufSize);
     int len;
     byte buffer[] = new byte[bufSize];

     // Echo back what the program spit out
     while ((len = bis.read(buffer, 0, bufSize)) != -1)
         result = result + new String(buffer);

     rc = p.waitFor();
  }
  catch (Exception e)
  {
     e.printStackTrace();
     rc = -1;
  }
  finally
  {
     return rc;
  }
  }
}
/

create or replace function run(Args varchar2 ) return number
as language java
name 'RunCommand.RunThis(java.lang.String) return int';
/


** IMPORTANTE : ** TEM que serem dadas as permissões para usuário,
diretório e arquivos , cfrme abaixo :

Código: Selecionar todos
-- Specific permissions should be given to run this code
var n number;
exec dbms_java.grant_permission('YOURUSER', 'SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '', :n);
exec dbms_java.grant_permission('YOURUSER', 'SYS:java.lang.RuntimePermission', 'readFileDescriptor', '', :n);
exec dbms_java.grant_permission('YOURUSER', 'SYS:java.io.FilePermission', 'YOUR PATH', 'read,write,execute', :n);

dr_gori
Localização: Portland, OR USA

Thomas F. G

Você já respondeu a dúvida de alguém hoje?
http://glufke.net/oracle/search.php?search_id=unanswered

Mensagemem Qui, 16 Jun 2005 11:27 am

mais um link bom:

Clique aqui


Código: Selecionar todos
Steve,

I'm looking for a Java-procedure executing host calls on a Unix environment from
the Oracle-server. I know the standard way of doing it by means of ProC (for
Oracle versions before 8.1) but I do not have the ProC compiler available.

I do not know Java or ProC (nor do I currently have the time to learn them).
I'vê found several examples of these scripts but the "Runtime Power" script on
this site does not seem to do anything at all and the other script I'vê found in
an Oracle newsgroup seems to miss some "#import" statements in order to compile
correctly.

I would greatly appreciate your help on this one.
Henk-Jan


and we said...


Here is how to do this in java in 8.1.6.  8.1.6 added lots of new security
features so this would be a little different in 8.1.5 but mostly the same. 

We need to start by granting some privs.  I'm going to grant as little as I have
to get allow us to execute the program /usr/bin/ps.  As SYS or some
appropriately priveleged user, we will execute:

sys@DEV816> begin
  2      dbms_java.grant_permission
  3      ('RT_TEST',
  4       'java.io.FilePermission',
  5       '/usr/bin/ps',
  6       'execute');
  7 
  8      dbms_java.grant_permission
  9      ('RT_TEST',
10       'java.lang.RuntimePermission',
11       '*',
12       'writeFileDescriptor' );
13  end;
14  /

PL/SQL procedure successfully completed.


That allows our user RT_TEST to successfully execute that program.  We could
have allowed it to execute /usr/bin/* or * or whatever -- I'm just letting it
execute that one program.

Now, RT_TEST would create in its schema:


rt_test@DEV816> create or replace and compile
  2  java source named "Util"
  3  as
  4  import java.io.*;
  5  import java.lang.*;
  6 
  7  public class Util extends Object
  8  {
  9 
10    public static int RunThis(String[] args)
11    {
12    Runtime rt = Runtime.getRuntime();
13    int        rc = -1;
14 
15    try
16    {
17       Process p = rt.exec(args[0]);
18 
19       int bufSize = 4096;
20       BufferedInputStream bis =
21        new BufferedInputStream(p.getInputStream(), bufSize);
22       int len;
23       byte buffer[] = new byte[bufSize];
24 
25       // Echo back what the program spit out
26       while ((len = bis.read(buffer, 0, bufSize)) != -1)
27          System.out.write(buffer, 0, len);
28 
29       rc = p.waitFor();
30    }
31    catch (Exception e)
32    {
33       e.printStackTrace();
34       rc = -1;
35    }
36    finally
37    {
38       return rc;
39    }
40    }
41  }
42  /

Java created.

rt_test@DEV816> create or replace
  2  function RUN_CMD( p_cmd  in varchar2) return number
  3  as
  4  language java
  5  name 'Util.RunThis(java.lang.String[]) return integer';
  6  /

Function created.


To make this callable as a procedure (ignoring the return code), we'll create a
procedure:

rt_test@DEV816>
rt_test@DEV816> create or replace procedure RC(p_cmd in varchar2)
  2  as
  3    x number;
  4  begin
  5    x := run_cmd(p_cmd);
  6  end;
  7  /

Procedure created.

And now to run it:

rt_test@DEV816> set serveroutput on size 1000000
rt_test@DEV816> exec dbms_java.set_output(1000000)
PL/SQL procedure successfully completed.
rt_test@DEV816> exec rc('/usr/bin/ps -ef');
UID   PID  PPID  C    STIME TTY      TIME CMD
root     0     0  0   Aug 17 ?        0:06 sched
root     1     0  0   Aug 17 ?        1:19 /etc/init -
root     2     0  0   Aug 17 ?        0:23 pageout
.....

PL/SQL procedure successfully completed.

rt_test@DEV816>


See


http://java.sun.com/j2se/1.3/docs/api/java/lang/RuntimePermission.html

http://java.sun.com/j2se/1.3/docs/api/java/security/SecurityPermission.html

http://java.sun.com/j2se/1.3/docs/api/java/io/FilePermission.html

and



http://download-east.oracle.com/docs/cd/A81042_01/DOC/java.816/a81353/perf.htm#1001971
From the “Java Developer’s Guide”, Part No. A81353-01, Chapter 5:

Table 5–1 Permission Types
n java.util.PropertyPermission
n java.io.SerializablePermission
n java.io.FilePermission
n java.net.NetPermission
n java.net.SocketPermission
n java.lang.RuntimePermission
n java.lang.reflect.ReflectPermission
n java.security.SecurityPermission
n oracle.aurora.rdbms.security.PolicyTablePermission
n oracle.aurora.security.JServerPermission


dr_gori
Localização: Portland, OR USA

Thomas F. G

Você já respondeu a dúvida de alguém hoje?
http://glufke.net/oracle/search.php?search_id=unanswered

Mensagemem Qua, 17 Set 2008 11:03 am

oque seria YOUR PATH? o caminho do banco?

exec dbms_java.grant_permission('ERP', 'SYS:java.io.FilePermission', 'YOUR PATH', 'read,write,execute', :n);
nilodp
Localização: Parana - Parana

Mensagemem Qui, 26 Fev 2009 12:50 pm

Uma duvida e se eu precisar utilizar uma biblioteca externa como deve ser o procedimento para se utiliza-la? Obrigado!
Shakall
Localização: Blumenau - SC

Mensagemem Sex, 27 Fev 2009 11:54 pm

Não é com o LOADJAVA citado acima ?
dr_gori
Localização: Portland, OR USA

Thomas F. G

Você já respondeu a dúvida de alguém hoje?
http://glufke.net/oracle/search.php?search_id=unanswered

Mensagemem Sex, 27 Fev 2009 11:56 pm

é que nos exemplos que eu vi o pessoal só usava ele com o .class, mas agora testei usando o jar e foi beleza, estou com outro problema agora, minha classe está rodando beleza, só que ela usa o comm.jar que é uma biblioteca para que eu possa ter acesso a porta com, o problema que esta biblioteca faz uso de uma dll, e se eu rodo minha classe no oracle ele da este erro pois esta faltando esta dll, tem como eu fazer o oracle encherga uma dll? se sim como?
Shakall
Localização: Blumenau - SC

Mensagemem Ter, 03 Mar 2009 1:49 pm

alguém poderia me ajudar estou tentando dar permissões java para um usuario mas não estou conseguindo, está dando erro de sintaxe.

Estou tentando usaer uma classe e o erro a seguir é apresentando.

"error: the Permission (java.lang.RuntimePermission getClassLoader) has not been granted to user. The PL/SQL to grant this is dbms_java.grant_permission( 'user', 'SYS:java.lang.RuntimePermission', 'getClassLoader', '' )"

tentei executar o comando de grant permission para o usuario utilizando a conta do sys, mas não deu certo.

usei o seguinte comando.

exec dbms_java.grant_permission('USER', 'SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '', :n);
exec dbms_java.grant_permission('USER', 'SYS:java.lang.RuntimePermission', 'readFileDescriptor', '', :n);
Shakall
Localização: Blumenau - SC

Mensagemem Ter, 09 Jun 2009 10:25 pm

pessoal,
estou fazendo uma pkg que faz uma integraçao com outro banco
e uma procedure faz um chamado a uma classe java para inserir
em um outro banco de dados os dados passados.....

a classe compila normal...mas na hora de conectar com o outro banco
via java, ele usa o jar de conexao, mas ele não encontra

tentei chamar o jar pelo loadjava mas deu erro, noDefFoundError no jar,

precisa ter que permissao pra executar isso, ou pra carregar um jar
de driver existe outra forma???

agradeço desde já
luiz_daniel
Localização: sp

Mensagemem Qua, 04 Set 2013 3:09 pm

dr_gori escreveu:Bem, existe duas formas de se fazer isso.
Uma delas, é quando você tem o FONTE do programa (o arquivo .java). Outra, é quando você só tem o bytecode (ou seja, o .class)

Vamos lá:

SEM O FONTE - LOADJAVA

Se você só tem a classe, deve carregar ela para dentro do Oracle. Aí vai um exemplo:



Código: Selecionar todos
--=======================
--== CRIACAO DA CLASSE ==
--=======================
-- Em um arquivo txt crie seu código

public class StoreProcedureJava {
public static String Procedimento (){
return "Estah String veio de cohdigo java";
};
}

-- Salve o Arquivo com o mesmo nome da classe mais a extensao .java
-- compile o arquivo: javac StoreProcedureJava.java
-- note que será gerado o bitecode (.class)

--==========================
--== ARMAZENANDO NO BANCO ==
--==========================
-- loadjava é um utilitario que vem com o banco, deverá estar em
$ORACLE_HOME/bin

loadjava.bat -user esd/esd StoreProcedureJava.class

--==========================
--== Verificando a Criacao
--==========================
select OBJECT_NAME, OBJECT_TYPE, CREATED from USER_OBJECTS
where upper(OBJECT_NAME) = upper('StoreProcedureJava')
/

--====================================================
--== Criando uma Funcao PL/SQL para Chamar a Classe
--====================================================
-- Atencao na sintaxe, Classe.funcao/procedimento.

create or replace function JavaOracle return varchar2 AS
LANGUAGE JAVA NAME 'StoreProcedureJava.Procedimento() return
java.lang.String';
/

--=======================
--== Executando a Classe
--=======================
select JavaOracle() from dual;




Agora, vai um exemplo com passagem de parametro.
Código: Selecionar todos
-- ======================================================================
-- ================ EXEMPLO DE PASSAGEM DE PARAMETROS ===================
-- ======================================================================

--=======================
--== CRIACAO DA CLASSE ==
--=======================

public class StoreProcedureJava {

public static String Procedimento (java.lang.String Texto){
return "Estah String veio de cohdigo java: " + Texto;
};


public static void main (String args[]){
file://System.out.println(Procedimento("TESTE"));
};

}

--==========================
--== ARMAZENANDO NO BANCO ==
--==========================
loadjava.bat -user esd/esd StoreProcedureJava.class

--==========================
--== Verificando a Criacao
--==========================
select OBJECT_NAME, OBJECT_TYPE, CREATED from USER_OBJECTS
where upper(OBJECT_NAME) = upper('StoreProcedureJava')
/

--====================================================
--== Criando uma Funcao PL/SQL para Chamar a Classe
--====================================================
CREATE OR REPLACE function JavaOracle(p1 IN VARCHAR2) return VARCHAR2 AS
LANGUAGE JAVA NAME 'StoreProcedureJava.Procedimento(java.lang.String) return
java.lang.String';
/

--=======================
--== Executando a Classe
--=======================
select JavaOracle('funciona !!!') from dual;
/

-- Resultado: Estah String veio de cohdigo java: funciona !!!





COM O FONTE

O exemplo abaixo Mostra como criar uma função em Java, que depois será chamada na função PL/SQL chamada RUN . Note-se que a função RUN deve ser alimentada com o nome/path completo do executável a ser rodado. Se for desejado comando do SO, criar uma batch e passar a batch como argumento.

Código: Selecionar todos
create or replace and compile java source named "RunCommand" as
import java.util.*;
import java.io.*;

public class RunCommand extends Object
{
  static String result;
  public static String getOutput(){
     return result;
  }

  public static int RunThis(String args)
  {
  Runtime rt = Runtime.getRuntime();
  int        rc = -1;

  try
  {
     Process p = rt.exec(args);

     int bufSize = 4096;
     BufferedInputStream bis =
      new BufferedInputStream(p.getInputStream(), bufSize);
     int len;
     byte buffer[] = new byte[bufSize];

     // Echo back what the program spit out
     while ((len = bis.read(buffer, 0, bufSize)) != -1)
         result = result + new String(buffer);

     rc = p.waitFor();
  }
  catch (Exception e)
  {
     e.printStackTrace();
     rc = -1;
  }
  finally
  {
     return rc;
  }
  }
}
/

create or replace function run(Args varchar2 ) return number
as language java
name 'RunCommand.RunThis(java.lang.String) return int';
/


** IMPORTANTE : ** TEM que serem dadas as permissões para usuário,
diretório e arquivos , cfrme abaixo :

Código: Selecionar todos
-- Specific permissions should be given to run this code
var n number;
exec dbms_java.grant_permission('YOURUSER', 'SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '', :n);
exec dbms_java.grant_permission('YOURUSER', 'SYS:java.lang.RuntimePermission', 'readFileDescriptor', '', :n);
exec dbms_java.grant_permission('YOURUSER', 'SYS:java.io.FilePermission', 'YOUR PATH', 'read,write,execute', :n);





gori, beleza?

deixa ver se entendi bem, esses "Javas" que você postou servem pra executar comandos no Unix através do Oracle, certo?

daria pra chamar um arquivo executável numa máquina local com Windows, através de um forms rodando dentro do ERP Applications (que roda no Unix)???
Porva
Localização: São Paulo/SP

Rafael S. Nunes
São Paulo/SP


  • Veja também
    Respostas
    ExibiÇões
    Última mensagem