2011-08-09 16 views
5

Estoy intentando enviar un mensaje JMS punto a punto desde un procedimiento almacenado de la base de datos de Oracle a una aplicación java. Los dos "puntos" se encuentran en diferentes máquinas, que he confirmado que pueden comunicarse entre sí a través de ping.Oracle: procedimiento almacenado Java que envía mensaje JMS

He creado una aplicación Java capaz de sacar mensajes de una cola dentro del servidor de aplicaciones. La aplicación se ejecuta dentro de un servidor JBoss v4.2.3. Pude enviar con éxito un mensaje JMS desde una aplicación Java remota, por lo que estoy seguro de que el código que se ejecuta dentro del servidor es correcto.

He tomado el código de la aplicación Java remota en funcionamiento y lo he cargado correctamente en un procedimiento almacenado de Oracle. También he logrado (¡creo!) Cargar en Oracle los archivos jar requeridos usando la utilidad loadjava. Los tres archivos jar que he cargado en son:

* jms-1.1 
    * jbossmq-3.2.3 
    * jboss-client-4.0.2 

los tres frascos se utilizan dentro de la aplicación Java remota de trabajo y parecen ser todo lo que se requiere. El código contenido cargado en el procedimiento almacenado es el siguiente:

package com.base.jms.client; 

    import java.util.Hashtable; 

    import javax.jms.JMSException; 
    import javax.jms.Queue; 
    import javax.jms.QueueConnection; 
    import javax.jms.QueueConnectionFactory; 
    import javax.jms.QueueSender; 
    import javax.jms.QueueSession; 
    import javax.jms.TextMessage; 
    import javax.naming.Context; 
    import javax.naming.InitialContext; 

    public class StandAloneClient { 

     public static String send() throws Exception { 

      String result = "Starting -> "; 

      try { 

       Hashtable env = new Hashtable(); 
       env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); 
       env.put(Context.PROVIDER_URL, "192.168.111.242:1099"); 
       env.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); 

       result = result + "Environment -> "; 

       // set up stuff 
       Context ic = new InitialContext(env); 
       result = result + "Context -> "; 

       QueueConnectionFactory connectionFactory = (QueueConnectionFactory) ic.lookup("ConnectionFactory"); 
       result = result + "Factory -> "; 

       Queue queue = (Queue) ic.lookup("queue/A"); 
       result = result + "Queue -> "; 

       QueueConnection connection = connectionFactory.createQueueConnection(); 
       result = result + "Connection -> "; 

       QueueSession session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE); 
       result = result + "Session -> "; 

       QueueSender sender = session.createSender(queue); 
       connection.start(); 

       result = result + "Sender -> "; 

       TextMessage myMessage = session.createTextMessage(); 
       myMessage.setText(result); 
       sender.send(myMessage); 

       result = result + "Sending Message -> "; 

       sender.close(); 
       session.close(); 
       connection.close(); 

       result = result + "Close"; 

      } catch (JMSException e) { 
       result = result + "JMS Exception"; 

       /* 
       if(e.getMessage() != null) { 
        result = result + ":" + e.getMessage(); 
       }*/ 

      } catch (Exception e) { 
       result = result + "Exception"; 

       /* 
       if(e.getMessage() != null) { 
        result = result + ":" + e.getMessage(); 
       }*/ 

      } 

      return result; 
     } 

    } 

He añadido la cadena de resultado en lo que puedo tratar de determinar en qué parte del código se caiga. Para crear y probar este procedimiento, estoy ejecutando los siguientes comandos en sqlplus:

create or replace function send_jms return VARCHAR2 as language java name 'com.base.jms.client.StandAloneClient.send() return java.lang.String'; 

variable myString varchar2(20); 
call send_jms() into :myString; 
Call completed. 
print myString; 

Todo parece estar cargado y compilar correctamente, sin embargo, no se envía el mensaje. La cadena de resultado devuelta implica que se está cayendo al intentar recuperar la clase QueueConnectionFactory del InitialContext. La cadena de resultado devuelto es:

Starting -> Environment -> Context -> Exception 

Estoy en una pérdida de por qué esto no está funcionando, y han sido incapaces de recoger más de la excepción lanzada. ¿Alguien puede confirmar que estoy haciendo esto correctamente, y si lo estoy, ver lo que estoy haciendo mal?

Disculpas por el largo post pero gracias de antemano por mirarlo!

+0

Así como una nota al margen: Oracle viene con una implementación de JMS construido encima de cola avanzada. ¿Alguna vez alguien ha tenido éxito en la interoperación con JBoss u otro servidor de aplicaciones utilizando el JMS incorporado, posiblemente ni siquiera usando Java sino solo los paquetes PL/SQL? – Codo

+0

He echado un vistazo utilizando las colas avanzadas ofrecidas por JBoss. Las transmisiones de Oracle también se pueden usar para JMS. Pensé que sería más fácil ir por el enfoque que he hecho. Estoy empezando a pensar lo contrario :) – ScreamingMage

Respuesta

3

No soy exactamente un experto en ejecutar Java y JMS dentro de la base de datos Oracle (aunque conozco cada uno de los tres componentes por separado). Pero según su descripción, parece que no ha tenido en cuenta el modelo de seguridad de Oracle para Java.

Oracle no permitirá que ningún componente acceda a la red (o al sistema de archivos, etc.) sin que se le haya otorgado explícitamente el derecho a. Así que comience a leer acerca de Oracle JVM security para saber cómo puede necesitar configurar Oracle para que pueda conectarse a una máquina remota.

La concesión de los permisos podría incluir la siguiente declaración:

EXEC DBMS_JAVA.GRANT_PERMISSION('YOUR_SCHEMA', 'SYS:java.net.SocketPermission', '192.168.111.242', 'connect,accept,resolve'); 
+0

Hola Cody, gracias por la respuesta. He ejecutado ese permiso de concesión que proporcionó junto con un par de permisos de concesión para JAVASYSPRIV, para el esquema con el que estoy trabajando. Parece que ha movido el problema a lo largo. Anteriormente, obtenía una AccessControlException que es consistente con lo que dijiste. Sin embargo, ahora recibo una javax.naming.CommunicationException cuando intento recuperar el QueueConnectionFactory. Investigaré el motivo de esta nueva excepción. ¡Cualquier otra idea que pueda ofrecer sería apreciada! – ScreamingMage

3

fin tengo todo este trabajo, en gran parte gracias a la ayuda ofrecida por Cody. Solo estoy respondiendo por si alguien más se encuentra con los mismos problemas y quiere saber exactamente cómo lo resolví.

Las declaraciones me encontré a conceder los permisos necesarios para Oracle fueron:

GRANT JAVASYSPRIV to NTIS 
EXEC dbms_java.grant_permission ('JAVASYSPRIV', 'SYS:java.net.SocketPermission', '*', 'accept,connect,listen,resolve'); 
EXEC DBMS_JAVA.GRANT_PERMISSION('YOUR SCHEMA', 'SYS:java.net.SocketPermission', '*', 'connect,accept,resolve'); 

Tienes que ha iniciado la sesión como usuario 'sistema' al ejecutar estos comandos.

Tuve algunos problemas adicionales con el procedimiento almacenado que se debieron a problemas con las bibliotecas que cargué en Oracle. Los frascos que usé fueron:

jms 
jbossmq-client 
jboss-client 

El JBossMQ-cliente y frascos jboss- cliente deben ser las mismas versiones como los utilizados en el propio servidor de aplicaciones. Estaba usando JBoss 4.2.3, así que copié estos archivos jar de la carpeta 'cliente' dentro del directorio de JBoss.

También tuve que poner el ipaddress al que se hace referencia en la clase java/procedimiento almacenado en el archivo de hosts ya que al parecer oráculo hace una búsqueda inversa en el ipaddress. Si no lo haces, obtienes una excepción de host desconocido. En el archivo hosts, solo ingrese el nombre de su computadora y la dirección IP.

Después de hacer todo esto, ¡ahora está funcionando correctamente para mí! Espero que esto ayude a alguien si encuentran el mismo problema.

0

Descubrí que, aunque estaba tratando de otorgar el permiso como SYS, y la política pertenecía a SYS, entonces SYS no tenía permiso para otorgar esa política. Así Esto funcionó para mí:

exec dbms_java.grant_policy_permission('SYS','SYS','java.net.SocketPermission','*'); 
exec dbms_java.grant_permission('MY_SCHEMA', 'SYS:java.net.SocketPermission', '*', 'connect,resolve'); 
Cuestiones relacionadas