Oracle:发送JMS消息的Java存储过程

我试图从oracle数据库存储过程发送点对点JMS消息到java应用程序。 这两个“点”位于不同的机器上,我已经确认可以通过ping相互通信。

我创建了一个java应用程序,能够成功地将消息从应用程序服务器中的队列中取出。 该应用程序在JBoss v4.2.3服务器中运行。 我已经能够从远程Java应用程序成功发送JMS消息,所以我确信在服务器中运行的代码是可以的。

我从工作的远程java应用程序中获取代码并将其成功加载到oracle存储过程中。 我还设法(我相信!)使用loadjava实用程序将所需的jar文件加载到oracle中。 我加载的三个jar文件是:

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

这三个jar在工作的远程java应用程序中使用,看起来就是所有需要的。 包含在存储过程中的代码如下:

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

我已经添加了结果字符串,所以我可以尝试确定它在代码中的位置。 要创建并测试此过程,我在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; 

似乎所有东西都被正确加载和编译,但是没有发送消息。 返回的结果字符串表示它在尝试从InitialContext中检索QueueConnectionFactory类时会崩溃。 返回的结果字符串是:

 Starting -> Environment -> Context -> Exception 

我不知道为什么这不起作用,并且无法从抛出的exception中收集到更多信息。 任何人都可以确认我这样做是正确的,如果我这样做,看看我做错了什么?

为长篇文章道歉,但提前感谢您的关注!

我不是在Oracle数据库中运行Java和JMS的专家(尽管我分别知道这三个组件中的每一个)。 但是根据您的描述,您似乎没有考虑Java的Oracle安全模型。

如果没有明确授予权利,Oracle将不允许任何组件访问网络(或文件系统等)。 因此,请开始阅读有关Oracle JVM安全性的内容,以了解如何配置Oracle以使您连接到远程计算机。

授予权限可能涉及以下语句:

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

我终于把这一切都搞定了,这在很大程度上要归功于Cody提供的帮助。 我只是提出这个答案,以防其他人遇到同样的问题,并想知道我是如何解决它的。

我运行以向oracle授予必要权限的语句是:

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

执行这些命令时,您必须以“SYSTEM”用户身份登录。

我对存储过程有一些进一步的问题,这些问题归结为我加载到oracle中的库的问题。 我用过的jar子是:

  jms jbossmq-client jboss-client 

jbossmq-client和jboss-client jar必须与应用程序服务器本身使用的版本相同。 我使用的是JBoss 4.2.3,所以我从JBoss目录中的’client’文件夹中复制了这些jar。

我还必须将java类/存储过程中引用的ipaddress放在hosts文件中,因为oracle会在ipaddress上执行反向查找。 如果不这样做,则会出现未知的主机exception。 在hosts文件中,只需输入您的计算机名称和ipaddress。

完成所有这些之后,它现在正在为我工​​作! 希望这可以帮助他们遇到同样的问题。

我发现即使我尝试授予SYS权限,并且该策略属于SYS,那么SYS也没有权限授予该策略。 所以这对我有用:

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