2011-08-09 39 views
5

Tôi đang cố gắng gửi một thông báo JMS điểm tới điểm từ thủ tục lưu trữ cơ sở dữ liệu oracle đến một ứng dụng java. Hai 'điểm' ngồi trên các máy khác nhau, mà tôi đã xác nhận có thể nói chuyện với nhau thông qua ping.Oracle: Thủ tục lưu sẵn Java gửi thông báo JMS

Tôi đã tạo một ứng dụng java có thể nhận tin nhắn thành công ngoài hàng đợi trong máy chủ ứng dụng. Ứng dụng đang chạy trong một máy chủ JBoss v4.2.3. Tôi đã có thể gửi thành công một tin nhắn JMS từ một ứng dụng java từ xa, vì vậy tôi chắc chắn rằng mã chạy trong máy chủ là ok.

Tôi đã lấy mã từ ứng dụng java từ xa đang hoạt động và tải thành công này vào một thủ tục lưu trữ oracle. Tôi cũng đã quản lý (tôi tin!) Tải vào oracle các tệp jar yêu cầu bằng cách sử dụng tiện ích loadjava. Ba tệp jar tôi đã tải là:

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

Ba lọ được sử dụng trong ứng dụng java từ xa đang hoạt động và dường như là tất cả những gì bắt buộc. Mã được chứa trong quy trình được lưu trữ như sau:

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

    } 

Tôi đã thêm chuỗi kết quả để tôi có thể thử và xác định vị trí mã nằm trên đó. Để tạo và kiểm tra quy trình này, tôi đang thực hiện các lệnh sau trong 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; 

Tất cả mọi thứ dường như được nạp và biên dịch một cách chính xác, tuy nhiên thông báo sẽ không được gửi đi. Chuỗi kết quả trả về có nghĩa là nó rơi xuống khi cố gắng truy xuất lớp QueueConnectionFactory từ InitialContext. Chuỗi kết quả được trả lại là:

Starting -> Environment -> Context -> Exception 

Tôi không biết tại sao điều này không hoạt động và không thể thu thập thêm từ ngoại lệ được ném. Bất cứ ai có thể xác nhận rằng tôi đang làm điều này một cách chính xác, và nếu tôi, hãy xem những gì tôi đang làm sai?

Xin lỗi vì bài đăng dài nhưng cảm ơn bạn đã xem trước!

+0

Cũng giống như một lưu ý: Oracle đi kèm với một triển khai JMS được xây dựng trên đầu tiên của xếp hàng nâng cao. Có ai từng thành công trong việc tương tác với JBoss hoặc một máy chủ ứng dụng khác bằng cách sử dụng JMS tích hợp, có thể thậm chí không sử dụng Java mà chỉ là các gói PL/SQL? – Codo

+0

Tôi đã có một cái nhìn bằng cách sử dụng hàng đợi trước được cung cấp bởi JBoss. Các luồng Oracle cũng có thể được sử dụng cho JMS. Tôi nghĩ sẽ dễ dàng hơn cho cách tiếp cận mà tôi đã làm. Tôi bắt đầu nghĩ khác đi :) – ScreamingMage

Trả lời

3

Tôi không chính xác là một chuyên gia về chạy Java và JMS trong cơ sở dữ liệu Oracle (mặc dù tôi biết từng thành phần riêng lẻ). Nhưng từ mô tả của bạn có vẻ như bạn đã không đưa mô hình bảo mật Oracle cho Java vào xem xét.

Oracle sẽ không cho phép bất kỳ thành phần nào truy cập vào mạng (hoặc hệ thống tệp, v.v.) mà không được cấp quyền rõ ràng. Vì vậy, hãy bắt đầu đọc về Oracle JVM security để tìm hiểu cách bạn có thể cần phải định cấu hình Oracle để cho phép bạn kết nối với máy từ xa.

Cấp quyền có thể liên quan đến các tuyên bố sau:

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

Xin chào Cody, cảm ơn bạn đã trả lời. Tôi đã chạy quyền cấp phép mà bạn đã cung cấp cùng với một vài quyền cấp phép cho JAVASYSPRIV, cho lược đồ mà tôi đang làm việc chống lại. Dường như đã di chuyển vấn đề. Trước đây, tôi đã nhận được một AccessControlException đó là phù hợp với những gì bạn nói. Tuy nhiên, bây giờ tôi nhận được một javax.naming.CommunicationException khi cố gắng truy xuất QueueConnectionFactory. Tôi sẽ điều tra lý do cho ngoại lệ mới này. Bất kỳ ý tưởng thêm bạn có thể cung cấp sẽ được đánh giá cao! – ScreamingMage

3

cuối cùng tôi đã nhận được điều này tất cả làm việc, nhờ một phần lớn vào sự giúp đỡ cung cấp bởi Cody. Tôi chỉ đưa câu trả lời này lên trong trường hợp người khác gặp phải vấn đề tương tự và muốn biết chính xác cách tôi giải quyết nó.

Báo cáo Tôi chạy đến cấp quyền cần thiết để oracle là:

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

Bạn phải được đăng nhập như người dùng HỆ THỐNG 'khi thực hiện các lệnh này.

Tôi đã gặp phải một số vấn đề khác với thủ tục được lưu trữ đã giảm xuống các vấn đề với thư viện mà tôi đã tải vào oracle. Các lọ tôi đã sử dụng là:

jms 
jbossmq-client 
jboss-client 

Bình jbossmq-client và jboss-client phải giống với các phiên bản được sử dụng trong chính máy chủ ứng dụng. Tôi đã sử dụng JBoss 4.2.3, vì vậy tôi đã sao chép các lọ này từ thư mục 'client' trong thư mục JBoss.

Tôi cũng phải đặt ipaddress được tham chiếu trong lớp java/thủ tục lưu trữ trong tệp máy chủ khi nó xuất hiện oracle không tra cứu ngược trên ipaddress. Nếu bạn không làm điều này, bạn sẽ nhận được một ngoại lệ máy chủ không xác định. Trong tệp host, chỉ cần đặt tên máy tính của bạn và ipaddress.

Sau khi thực hiện tất cả điều này, nó hiện đang hoạt động chính xác cho tôi! Hy vọng điều này sẽ giúp ai đó nếu họ gặp vấn đề tương tự.

0

Tôi thấy rằng mặc dù tôi đã cố cấp quyền cho SYS và chính sách thuộc về SYS, thì SYS không có quyền cấp chính sách đó. Vì vậy, điều này làm việc cho tôi:

exec dbms_java.grant_policy_permission('SYS','SYS','java.net.SocketPermission','*'); 
exec dbms_java.grant_permission('MY_SCHEMA', 'SYS:java.net.SocketPermission', '*', 'connect,resolve'); 
Các vấn đề liên quan