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
Responder
lamanita
Rank: Programador Pleno
Rank: Programador Pleno
Mensagens: 42
Registrado em: Seg, 17 Mai 2004 2:41 pm
Localização: Porto Alegre - RS
Samuel, o lamanit@

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.
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5023
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

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

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:


Selecionar tudo

--=======================
--== 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.

Selecionar tudo

-- ======================================================================
-- ================ 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.

Selecionar tudo

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 :

Selecionar tudo

-- 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);

Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5023
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

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

mais um link bom:

Clique aqui

Selecionar tudo

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


nilodp
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 3
Registrado em: Ter, 24 Jun 2008 3:21 pm
Localização: Parana - Parana

oque seria YOUR PATH? o caminho do banco?

exec dbms_java.grant_permission('ERP', 'SYS:java.io.FilePermission', 'YOUR PATH', 'read,write,execute', :n);
Shakall
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 29
Registrado em: Qua, 13 Ago 2008 6:57 pm
Localização: Blumenau - SC

Uma duvida e se eu precisar utilizar uma biblioteca externa como deve ser o procedimento para se utiliza-la? Obrigado!
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5023
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

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

Não é com o LOADJAVA citado acima ?
Shakall
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 29
Registrado em: Qua, 13 Ago 2008 6:57 pm
Localização: Blumenau - SC

é 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
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 29
Registrado em: Qua, 13 Ago 2008 6:57 pm
Localização: Blumenau - SC

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);
luiz_daniel
Rank: Estagiário Júnior
Rank: Estagiário Júnior
Mensagens: 1
Registrado em: Ter, 09 Jun 2009 10:10 pm
Localização: sp

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á
Avatar do usuário
Porva
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 342
Registrado em: Seg, 29 Jan 2007 7:36 am
Localização: São Paulo/SP
Rafael S. Nunes
São Paulo/SP

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:


Selecionar tudo

--=======================
--== 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.

Selecionar tudo

-- ======================================================================
-- ================ 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.

Selecionar tudo

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 :

Selecionar tudo

-- 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)???
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante