Oracle: хранимая процедура Java, отправляющая сообщение JMS - PullRequest
5 голосов
/ 09 августа 2011

Я пытаюсь отправить двухточечное сообщение JMS из хранимой процедуры базы данных оракула в приложение Java. Две «точки» расположены на разных машинах, и я убедился, что они могут общаться друг с другом через ping.

Я создал приложение Java, способное успешно удалять сообщения из очереди на сервере приложений. Приложение работает на сервере JBoss v4.2.3. Мне удалось успешно отправить сообщение JMS из удаленного Java-приложения, поэтому я уверен, что код, запущенный на сервере, в порядке.

Я взял код из работающего удаленного Java-приложения и успешно загрузил его в хранимую процедуру Oracle. Мне также удалось (я верю!) Загрузить в oracle необходимые файлы jar с помощью утилиты loadjava. Я загрузил три 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;

Кажется, что все загружается и компилируется правильно, однако сообщение не отправляется. Возвращаемая строка результата подразумевает, что она падает при попытке извлечь класс QueueConnectionFactory из InitialContext. Возвращенная строка результата:

Starting -> Environment -> Context -> Exception

Я в недоумении, почему это не работает, и не смог найти больше из брошенного исключения. Может ли кто-нибудь подтвердить, что я делаю это правильно, и если да, посмотрите, что я делаю неправильно?

Извиняюсь за длинный пост, но заранее благодарю за просмотр!

Ответы [ 3 ]

3 голосов
/ 10 августа 2011

Наконец-то все заработало, во многом благодаря помощи, которую предлагает Коди.Я просто выкладываю этот ответ на тот случай, если кто-то еще сталкивается с такими же проблемами и хочет точно знать, как я их решил.

Заявления, которые я использовал для предоставления необходимых разрешений оракулу, были:

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 

jar-файлы jbossmq-client и jboss-client должны иметь те же версии, что и используемые на самом сервере приложений.Я использовал JBoss 4.2.3, поэтому я скопировал эти jar-файлы из папки «client» в каталоге JBoss.

Мне также пришлось поместить ipaddress, указанный в процедуре класса / java, в файле hosts как:кажется оракул делает обратный поиск на IPaddress.Если вы этого не сделаете, вы получите неизвестное исключение хоста.В файле hosts просто укажите имя своего компьютера и IP-адрес.

После всего этого он теперь работает корректно для меня!Надеюсь, это поможет кому-то, если он столкнется с той же проблемой.

3 голосов
/ 09 августа 2011

Я не совсем специалист по запуску Java и JMS в базе данных Oracle (хотя я знаю каждый из трех компонентов отдельно).Но из вашего описания кажется, что вы не приняли во внимание модель безопасности Oracle для Java.

Oracle не позволит любому компоненту получить доступ к сети (или файловой системе и т. Д.) Без явного предоставления правак.Так что начните читать о Oracle JVM security , чтобы узнать, как вам может понадобиться настроить Oracle для подключения к удаленной машине.

Предоставление разрешений может включать в себя следующее утверждение:

EXEC DBMS_JAVA.GRANT_PERMISSION('YOUR_SCHEMA', 'SYS:java.net.SocketPermission', '192.168.111.242', 'connect,accept,resolve');
0 голосов
/ 19 ноября 2015

Я обнаружил, что хотя я пытался предоставить разрешение от имени 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' );
...