rednight

          0x2B|~0x2B,That's not a question,Just do it.
          posts - 32, comments - 14, trackbacks - 0, articles - 0

          2006年8月28日

          當(dāng)前,CORBA、DCOM、RMI等RPC中間件技術(shù)已廣泛應(yīng)用于各個(gè)領(lǐng)域。但是面對(duì)規(guī)模和復(fù)雜度都越來(lái)越高的分布式系統(tǒng),這些技術(shù)也顯示出其局限性:(1)同步通信:客戶發(fā)出調(diào)用后,必須等待服務(wù)對(duì)象完成處理并返回結(jié)果后才能繼續(xù)執(zhí)行;(2)客戶和服務(wù)對(duì)象的生命周期緊密耦合:客戶進(jìn)程和服務(wù)對(duì)象進(jìn)程都必須正常運(yùn)行;如果由于服務(wù)對(duì)象崩潰或者網(wǎng)絡(luò)故障導(dǎo)致客戶的請(qǐng)求不可達(dá),客戶會(huì)接收到異常;(3)點(diǎn)對(duì)點(diǎn)通信:客戶的一次調(diào)用只發(fā)送給某個(gè)單獨(dú)的目標(biāo)對(duì)象。
             面向消息的中間件(Message Oriented Middleware,MOM)較好的解決了以上問(wèn)題。發(fā)送者將消息發(fā)送給消息服務(wù)器,消息服務(wù)器將消息存放在若干隊(duì)列中,在合適的時(shí)候再將消息轉(zhuǎn)發(fā)給接收者。這種模式下,發(fā)送和接收是異步的,發(fā)送者無(wú)需等待;二者的生命周期未必相同:發(fā)送消息的時(shí)候接收者不一定運(yùn)行,接收消息的時(shí)候發(fā)送者也不一定運(yùn)行;一對(duì)多通信:對(duì)于一個(gè)消息可以有多個(gè)接收者。
             已有的MOM系統(tǒng)包括IBM的MQSeries、Microsoft的MSMQ和BEA的MessageQ等。由于沒(méi)有一個(gè)通用的標(biāo)準(zhǔn),這些系統(tǒng)很難實(shí)現(xiàn)互操作和無(wú)縫連接。Java Message Service(JMS)是SUN提出的旨在統(tǒng)一各種MOM系統(tǒng)接口的規(guī)范,它包含點(diǎn)對(duì)點(diǎn)(Point to Point,PTP)和發(fā)布/訂閱(Publish/Subscribe,pub/sub)兩種消息模型,提供可靠消息傳輸、事務(wù)和消息過(guò)濾等機(jī)制。

          1.JMS
             JAVA 消息服務(wù)(JMS)定義了Java 中訪問(wèn)消息中間件的接口。JMS 只是接口,并沒(méi)有給予實(shí)現(xiàn),實(shí)現(xiàn)JMS 接口的消息中間件稱為JMS Provider,iLink實(shí)現(xiàn)了JMS接口,用戶可以通過(guò)使用JMS接口,在iLink中進(jìn)行JMS編程。 iLink支持JMS1.0.2版本。

          2.JMS接口描述
             JMS 支持兩種消息類型PTP 和Pub/Sub,分別稱作:PTP Domain 和Pub/Sub Domain,這兩種接口都繼承統(tǒng)一的JMS父接口,JMS 主要接口如下所示:

          MS父接口

          PTP

          Pub/Sub

          ConnectionFactory

          QueueConnectionFactory

          TopicConnectionFactory

          Connection

          QueueConnection

          TopicConnection

          Destination

          Queue

          Topic

          Session

          QueueSession

          TopicSession

          MessageProducer

          QueueSender

          TopicPublisher

          MessageConsumer

          QueueReceiver,QueueBrowse r

          TopicSubscriber

           

           

           

                            
             ConnectionFactory :連接工廠,JMS 用它創(chuàng)建連接
             Connection :JMS 客戶端到JMS Provider 的連接
             Destination :消息的目的地
             Session: 一個(gè)發(fā)送或接收消息的線程
             MessageProducer: 由Session 對(duì)象創(chuàng)建的用來(lái)發(fā)送消息的對(duì)象
             MessageConsumer: 由Session 對(duì)象創(chuàng)建的用來(lái)接收消息的對(duì)象

          3.JMS消息模型
          JMS 消息由以下幾部分組成:消息頭,屬性,消息體。
            
          3.1 消息頭(Header) - 消息頭包含消息的識(shí)別信息和路由信息,消息頭包含一些標(biāo)準(zhǔn)的屬性如:JMSDestination,JMSMessageID 等。

           消息頭

           由誰(shuí)設(shè)置

          JMSDestination

          send 或 publish 方法

          JMSDeliveryMode

          send 或 publish 方法

          JMSExpiration

          send 或 publish 方法

          JMSPriority

          send 或 publish 方法

          JMSMessageID

          send 或 publish 方法

          JMSTimestamp

          send 或 publish 方法

          JMSCorrelationID

          客戶

          JMSReplyTo

          客戶

          JMSType

          客戶

          JMSRedelivered

          JMS Provider

           

           

                  
           

           

           

                


          3.2 屬性(Properties)
          - 除了消息頭中定義好的標(biāo)準(zhǔn)屬性外,JMS 提供一種機(jī)制增加新屬性到消息頭 中,這種新屬性包含以下幾種:
             1. 應(yīng)用需要用到的屬性;
             2. 消息頭中原有的一些可選屬性;
             3. JMS Provider 需要用到的屬性。
             標(biāo)準(zhǔn)的JMS 消息頭包含以下屬性:

          JMSDestination

          消息發(fā)送的目的地

          JMSDeliveryMode

          傳遞模式, 有兩種模式: PERSISTENT 和NON_PERSISTENT,PERSISTENT 表示該消息一定要被送到目的地,否則會(huì)導(dǎo)致應(yīng)用錯(cuò)誤。NON_PERSISTENT 表示偶然丟失該消息是被允許的,這兩種模式使開(kāi)發(fā)者可以在消息傳遞的可靠性和吞吐量之間找到平衡點(diǎn)。

          JMSMessageID

          唯一識(shí)別每個(gè)消息的標(biāo)識(shí),由JMS Provider 產(chǎn)生。

          JMSTimestamp

          一個(gè)消息被提交給JMS Provider 到消息被發(fā)出的時(shí)間。

          JMSCorrelationID

          用來(lái)連接到另外一個(gè)消息,典型的應(yīng)用是在回復(fù)消息中連接到原消息。

          JMSReplyTo

          提供本消息回復(fù)消息的目的地址

          JMSRedelivered

          如果一個(gè)客戶端收到一個(gè)設(shè)置了JMSRedelivered 屬性的消息,則表示可能該客戶端曾經(jīng)在早些時(shí)候收到過(guò)該消息,但并沒(méi)有簽收(acknowledged)。

          JMSType

          消息類型的識(shí)別符。

          JMSExpiration

          消息過(guò)期時(shí)間,等于QueueSender 的send 方法中的timeToLive 值或TopicPublisher 的publish 方法中的timeToLive 值加上發(fā)送時(shí)刻的GMT 時(shí)間值。如果timeToLive值等于零,則JMSExpiration 被設(shè)為零,表示該消息永不過(guò)期。如果發(fā)送后,在消息過(guò)期時(shí)間之后消息還沒(méi)有被發(fā)送到目的地,則該消息被清除。

          JMSPriority

          消息優(yōu)先級(jí),從0-9 十個(gè)級(jí)別,0-4 是普通消息,5-9 是加急消息。JMS 不要求JMS Provider 嚴(yán)格按照這十個(gè)優(yōu)先級(jí)發(fā)送消息,但必須保證加急消息要先于普通消息到達(dá)。

           

           

           

           

           

           

           

           

           

           



          3.3 消息體(Body) - JMS API 定義了5種消息體格式,也叫消息類型,你可以使用不同形式發(fā)送接收 數(shù)據(jù)并可以兼容現(xiàn)有的消息格式,下面描述這5種類型:

          消息類型

          消息體

          TextMessage

          java.lang.String對(duì)象,如xml文件內(nèi)容

          MapMessage

          名/值對(duì)的集合,名是String對(duì)象,值類型可以是Java任何基本類型

          BytesMessage

          字節(jié)流

          StreamMessage

          Java中的輸入輸出流

          ObjectMessage

          Java中的可序列化對(duì)象

          Message

          沒(méi)有消息體,只有消息頭和屬性













          下例演示創(chuàng)建并發(fā)送一個(gè)TextMessage到一個(gè)隊(duì)列:
          TextMessage message = queueSession.createTextMessage();
          message.setText(msg_text); // msg_text is a String
          queueSender.send(message);

          下例演示接收消息并轉(zhuǎn)換為合適的消息類型:
          Message m = queueReceiver.receive();
          if (m instanceof TextMessage) {
           TextMessage message = (TextMessage) m;
           System.out.println("Reading message: " + message.getText());
          } else {
           // Handle error
          }

          4. 消息的同步異步接收
             消息的同步接收是指客戶端主動(dòng)去接收消息,JMS 客戶端可以采用MessageConsumer 的receive方法去接收下一個(gè)消息。
             消息的異步接收是指當(dāng)消息到達(dá)時(shí),主動(dòng)通知客戶端。JMS 客戶端可以通過(guò)注冊(cè)一個(gè)實(shí) 現(xiàn)MessageListener 接口的對(duì)象到MessageConsumer,這樣,每當(dāng)消息到達(dá)時(shí),JMS Provider 會(huì)調(diào)用MessageListener中的onMessage 方法。

          5. PTP模型
          PTP(Point-to-Point)模型是基于隊(duì)列的,發(fā)送方發(fā)消息到隊(duì)列,接收方從隊(duì)列接收消息,隊(duì)列的存在使得消息的異步傳輸成為可能。和郵件系統(tǒng)中的郵箱一樣,隊(duì)列可以包含各種消息,JMS Provider 提 供工具管理隊(duì)列的創(chuàng)建、刪除。JMS PTP 模型定義了客戶端如何向隊(duì)列發(fā)送消息,從隊(duì)列接收消息,瀏覽隊(duì)列中的消息。
             下面描述JMS PTP 模型中的主要概念和對(duì)象:

          名稱

          描述

          Queue

          由JMS Provider 管理,隊(duì)列由隊(duì)列名識(shí)別,客戶端可以通過(guò)JNDI 接口用隊(duì)列名得到一個(gè)隊(duì)列對(duì)象。

          TemporaryQueue

          由QueueConnection 創(chuàng)建,而且只能由創(chuàng)建它的QueueConnection 使用。

          QueueConnectionFactory

          客戶端用QueueConnectionFactory 創(chuàng)建QueueConnection 對(duì)象。

          QueueConnection

          一個(gè)到JMS PTP provider 的連接,客戶端可以用QueueConnection 創(chuàng)建QueueSession 來(lái)發(fā)送和接收消息。

          QueueSession

          提供一些方法創(chuàng)建QueueReceiver 、QueueSender、QueueBrowser 和TemporaryQueue。如果在QueueSession 關(guān)閉時(shí),有一些消息已經(jīng)被收到,但還沒(méi)有被簽收(acknowledged),那么,當(dāng)接收者下次連接到相同的隊(duì)列時(shí),這些消息還會(huì)被再次接收。

          QueueReceiver

          客戶端用QueueReceiver 接收隊(duì)列中的消息,如果用戶在QueueReceiver 中設(shè)定了消息選擇條件,那么不符合條件的消息會(huì)留在隊(duì)列中,不會(huì)被接收到。

          QueueSender

          客戶端用QueueSender 發(fā)送消息到隊(duì)列。

          QueueBrowser

          客戶端可以QueueBrowser 瀏覽隊(duì)列中的消息,但不會(huì)收走消息。

          QueueRequestor

          JMS 提供QueueRequestor 類簡(jiǎn)化消息的收發(fā)過(guò)程。QueueRequestor 的構(gòu)造函數(shù)有兩個(gè)參數(shù):QueueSession 和queue,QueueRequestor 通過(guò)創(chuàng)建一個(gè)臨時(shí)隊(duì)列來(lái)完成最終的收發(fā)消息請(qǐng)求。

          可靠性(Reliability)

          隊(duì)列可以長(zhǎng)久地保存消息直到接收者收到消息。接收者不需要因?yàn)閾?dān)心消息會(huì)丟失而時(shí)刻和隊(duì)列保持激活的連接狀態(tài),充分體現(xiàn)了異步傳輸模式的優(yōu)勢(shì)。



                        
                    
            
           

           

           

           

           

           

           

           

           


          6. PUB/SUB模型
          JMS Pub/Sub 模型定義了如何向一個(gè)內(nèi)容節(jié)點(diǎn)發(fā)布和訂閱消息,這些節(jié)點(diǎn)被稱作主題(topic)。
             主題可以被認(rèn)為是消息的傳輸中介,發(fā)布者(publisher)發(fā)布消息到主題,訂閱者(subscribe)從主題訂閱消息。主題使得消息訂閱者和消息發(fā)布者保持互相獨(dú)立,不需要接觸即可保證消息的傳送。
             下面描述JMS Pub/Sub 模型中的主要概念和對(duì)象:

          名稱

          描述

          訂閱(subscription)

          消息訂閱分為非持久訂閱(non-durable subscription)和持久訂閱(durable subscrip-tion),非持久訂閱只有當(dāng)客戶端處于激活狀態(tài),也就是和JMS Provider 保持連接狀態(tài)才能收到發(fā)送到某個(gè)主題的消息,而當(dāng)客戶端處于離線狀態(tài),這個(gè)時(shí)間段發(fā)到主題的消息將會(huì)丟失,永遠(yuǎn)不會(huì)收到。持久訂閱時(shí),客戶端向JMS 注冊(cè)一個(gè)識(shí)別自己身份的ID,當(dāng)這個(gè)客戶端處于離線時(shí),JMS Provider 會(huì)為這個(gè)ID 保存所有發(fā)送到主題的消息,當(dāng)客戶再次連接到JMS Provider時(shí),會(huì)根據(jù)自己的ID 得到所有當(dāng)自己處于離線時(shí)發(fā)送到主題的消息。

          Topic

          主題由JMS Provider 管理,主題由主題名識(shí)別,客戶端可以通過(guò)JNDI 接口用主題名得到一個(gè)主題對(duì)象。JMS 沒(méi)有給出主題的組織和層次結(jié)構(gòu)的定義,由JMS Provider 自己定義。

          TemporaryTopic

          臨時(shí)主題由TopicConnection 創(chuàng)建,而且只能由創(chuàng)建它的TopicConnection 使用。臨時(shí)主題不能提供持久訂閱功能。

          TopicConnectionFactory

          客戶端用TopicConnectionFactory 創(chuàng)建TopicConnection 對(duì)象。

          TopicConnection

          TopicConnection 是一個(gè)到JMS Pub/Sub provider 的連接,客戶端可以用TopicConnection創(chuàng)建TopicSession 來(lái)發(fā)布和訂閱消息。

          TopicSession

          TopicSession 提供一些方法創(chuàng)建TopicPublisher、TopicSubscriber、TemporaryTopic 。它還提供unsubscribe 方法取消消息的持久訂閱。

          TopicPublisher

          客戶端用TopicPublisher 發(fā)布消息到主題。

          TopicSubscriber

          客戶端用TopicSubscriber 接收發(fā)布到主題上的消息。可以在TopicSubscriber 中設(shè)置消息過(guò)濾功能,這樣,不符合要求的消息不會(huì)被接收。

          Durable TopicSubscriber

          如果一個(gè)客戶端需要持久訂閱消息,可以使用Durable TopicSubscriber,TopSession 提供一個(gè)方法createDurableSubscriber創(chuàng)建Durable TopicSubscriber 對(duì)象。

          恢復(fù)和重新派送(Recovery and Redelivery)

          非持久訂閱狀態(tài)下,不能恢復(fù)或重新派送一個(gè)未簽收的消息。只有持久訂閱才能恢復(fù)或重新派送一個(gè)未簽收的消息。

          TopicRequestor

          JMS 提供TopicRequestor 類簡(jiǎn)化消息的收發(fā)過(guò)程。TopicRequestor 的構(gòu)造函數(shù)有兩個(gè)參數(shù):TopicSession 和topic。TopicRequestor 通過(guò)創(chuàng)建一個(gè)臨時(shí)主題來(lái)完成最終的發(fā)布和接收消息請(qǐng)求。

          可靠性(Reliability)

          當(dāng)所有的消息必須被接收,則用持久訂閱模式。當(dāng)丟失消息能夠被容忍,則用非持久訂閱模式。

           

           

           

           

           

           

           


           

           


           
           
           
           
           
           
           
           
           




          7. 開(kāi)發(fā)JMS的步驟
             廣義上說(shuō),一個(gè)JMS 應(yīng)用是幾個(gè)JMS 客戶端交換消息,開(kāi)發(fā)JMS 客戶端應(yīng)用由以下幾步構(gòu)成:
          用JNDI 得到ConnectionFactory 對(duì)象;
          用JNDI 得到目標(biāo)隊(duì)列或主題對(duì)象,即Destination 對(duì)象;
          用ConnectionFactory 創(chuàng)建Connection 對(duì)象;
          用Connection 對(duì)象創(chuàng)建一個(gè)或多個(gè)JMS Session;
          用Session 和Destination 創(chuàng)建MessageProducer 和MessageConsumer;
          通知Connection 開(kāi)始傳遞消息。

          posted @ 2007-04-11 16:41 rednight 閱讀(350) | 評(píng)論 (0)編輯 收藏

          Some XA JDBC drivers do not support local transaction operations, which can cause an error similar to the following when optimistic concurrency is used with such a driver:

          SQL operations are not allowed with no global transaction by default for XA drivers.

          In other words, the error will occur when SupportsLocalTransactions="true" is specified for the JDBCConnectionPool.

          This problem occurs because optimistic concurrency suspends a global transaction and does reads in a local transaction when the database is not Oracle. (When using Oracle, you can avoid this problem by explicitly setting <database-type>Oracle</database-type> in your CMP deployment descriptor.)

          Workaround : Use the "RollbackLocalTxUponConnClose" on the JDBCConnection.

          posted @ 2007-03-06 12:49 rednight 閱讀(233) | 評(píng)論 (0)編輯 收藏

          在談到 XA 規(guī)范之前,必須首先了解分布式事務(wù)處理( Distributed Transaction Processing DTP )的概念。 Transaction ,即事務(wù),又稱之為交易,指一個(gè)程序或程序段,在一個(gè)或多個(gè)資源如 數(shù)據(jù)庫(kù) 或文件上為完成某些功能的執(zhí)行過(guò)程的集合。 LU 人的博客 )vqfhOBA
            分布式事務(wù)處理是指一個(gè)事務(wù)可能涉及多個(gè)數(shù)據(jù)庫(kù)操作,分布式事務(wù)處理的關(guān)鍵是必須有一種方法可以知道事務(wù)在任何地方所做的所有動(dòng)作,提交或回滾事務(wù)的決定必須產(chǎn)生統(tǒng)一的結(jié)果(全部提交或全部回滾)。
            X/Open 組織(即現(xiàn)在的 Open Group )定義了分布式事務(wù)處理模型。 X/Open DTP 模型( 1994 )包括應(yīng)用程序( AP )、事務(wù)管理器( TM )、資源管理器( RM )、通信資源管理器( CRM )四部分。一般,常見(jiàn)的事務(wù)管理器( TM )是交易中間件,常見(jiàn)的資源管理器( RM )是數(shù)據(jù)庫(kù),常見(jiàn)的通信資源管理器( CRM )是消息中間件。
            通常把一個(gè)數(shù)據(jù)庫(kù)內(nèi)部的事務(wù)處理,如對(duì)多個(gè)表的操作,作為本地事務(wù)看待。數(shù)據(jù)庫(kù)的事務(wù)處理對(duì)象是本地事務(wù),而分布式事務(wù)處理的對(duì)象是全局事務(wù)。

          所謂全局事務(wù),是指分布式事務(wù)處理環(huán)境中,多個(gè)數(shù)據(jù)庫(kù)可能需要共同完成一個(gè)工作,這個(gè)工作即是一個(gè)全局事務(wù),例如,一個(gè)事務(wù)中可能更新幾個(gè)不同的數(shù)據(jù)庫(kù)。對(duì)數(shù)據(jù)庫(kù)的操作發(fā)生在系統(tǒng)的各處但必須全部被提交或回滾。此時(shí)一個(gè)數(shù)據(jù)庫(kù)對(duì)自己內(nèi)部所做操作的提交不僅依賴本身操作是否成功,還要依賴與全局事務(wù)相關(guān)的其它數(shù)據(jù)庫(kù)的操作是否成功,如果任一數(shù)據(jù)庫(kù)的任一操作失敗,則參與此事務(wù)的所有數(shù)據(jù)庫(kù)所做的所有操作都必須回滾。 LU 人的博客 8v:d?(~;~$A-Q9V D
            一般情況下,某一數(shù)據(jù)庫(kù)無(wú)法知道其它數(shù)據(jù)庫(kù)在做什么,因此,在一個(gè) DTP 環(huán)境中,交易中間件是必需的,由它通知和協(xié)調(diào)相關(guān)數(shù)據(jù)庫(kù)的提交或回滾。而一個(gè)數(shù)據(jù)庫(kù)只將其自己所做的操作(可恢復(fù))影射到全局事務(wù)中。

             XA 就是 X/Open DTP 定義的交易中間件與數(shù)據(jù)庫(kù)之間的接口規(guī)范(即接口函數(shù)),交易中間件用它來(lái)通知數(shù)據(jù)庫(kù)事務(wù)的開(kāi)始、結(jié)束以及提交、回滾等。 XA 接口函數(shù)由數(shù)據(jù)庫(kù)廠商提供。

          XA
          與兩階段提交協(xié)議

            通常情況下,交易中間件與數(shù)據(jù)庫(kù)通過(guò) XA 接口規(guī)范,使用兩階段提交來(lái)完成一個(gè)全局事務(wù), XA 規(guī)范的基礎(chǔ)是兩階段提交協(xié)議。
            在第一階段,交易中間件請(qǐng)求所有相關(guān)數(shù)據(jù)庫(kù)準(zhǔn)備提交(預(yù)提交)各自的事務(wù)分支,以確認(rèn)是否所有相關(guān)數(shù)據(jù)庫(kù)都可以提交各自的事務(wù)分支。當(dāng)某一數(shù)據(jù)庫(kù)收到預(yù)提交后,如果可以提交屬于自己的事務(wù)分支,則將自己在該事務(wù)分支中所做的操作固定記錄下來(lái),并給交易中間件一個(gè)同意提交的應(yīng)答,此時(shí)數(shù)據(jù)庫(kù)將不能再在該事務(wù)分支中加入任何操作,但此時(shí)數(shù)據(jù)庫(kù)并沒(méi)有真正提交該事務(wù),數(shù)據(jù)庫(kù)對(duì)共享資源的操作還未釋放(處于上鎖狀態(tài))。如果由于某種原因數(shù)據(jù)庫(kù)無(wú)法提交屬于自己的事務(wù)分支,它將回滾自己的所有操作,釋放對(duì)共享資源上的鎖,并返回給交易中間件失敗應(yīng)答。 在第二階段,交易中間件審查所有數(shù)據(jù)庫(kù)返回的預(yù)提交結(jié)果,如所有數(shù)據(jù)庫(kù)都可以提交,交易中間件將要求所有數(shù)據(jù)庫(kù)做正式提交,這樣該全局事務(wù)被提交。而如果有任一數(shù)據(jù)庫(kù)預(yù)提交返回失敗,交易中間件將要求所有其它數(shù)據(jù)庫(kù)回滾其操作,這樣該全局事務(wù)被回滾。
            以一個(gè)全局事務(wù)為例, AP 首先通知交易中間件開(kāi)始一個(gè)全局事務(wù),交易中間件通過(guò) XA 接口函數(shù)通知數(shù)據(jù)庫(kù)開(kāi)始事務(wù),然后 AP 可以對(duì)數(shù)據(jù)庫(kù)管理的資源進(jìn)行操作,數(shù)據(jù)庫(kù)系統(tǒng)記錄事務(wù)對(duì)本地資源的所有操作。操作完成后交易中間件通過(guò) XA 接口函數(shù)通知數(shù)據(jù)庫(kù)操作完成。交易中間件負(fù)責(zé)記錄 AP 操作過(guò)哪些數(shù)據(jù)庫(kù)(事務(wù)分支)。 AP 根據(jù)情況通知交易中間件提交該全局事務(wù),交易中間件會(huì)通過(guò) XA 接口函數(shù)要求各個(gè)數(shù)據(jù)庫(kù)做預(yù)提交,所有數(shù)據(jù)庫(kù)返回成功后要求各個(gè)數(shù)據(jù)庫(kù)做正式提交,此時(shí)一筆全局事務(wù)結(jié)束。

             XA 規(guī)范對(duì)應(yīng)用來(lái)說(shuō),最大好處在于事務(wù)的完整性由交易中間件和數(shù)據(jù)庫(kù)通過(guò) XA 接口控制, AP 只需要關(guān)注與數(shù)據(jù)庫(kù)的應(yīng)用邏輯的處理,而無(wú)需過(guò)多關(guān)心事務(wù)的完整性,應(yīng)用設(shè)計(jì)開(kāi)發(fā)會(huì)簡(jiǎn)化很多。
            具體來(lái)說(shuō),如果沒(méi)有交易中間件,應(yīng)用系統(tǒng)需要在程序內(nèi)部直接通知數(shù)據(jù)庫(kù)開(kāi)始、結(jié)束和提交事務(wù),當(dāng)出現(xiàn)異常情況時(shí)必須由專門的程序?qū)?shù)據(jù)庫(kù)進(jìn)行反向操作才能完成回滾。如果是有很多事務(wù)分支的全局事務(wù),回滾時(shí)情況將變得異常復(fù)雜。而使用 XA 接口,則全局事務(wù)的提交是由交易中間件控制,應(yīng)用程序只需通知交易中間件提交或回滾事務(wù),就可以控制整個(gè)事務(wù)(可能涉及多個(gè)異地的數(shù)據(jù)庫(kù))的全部提交或回滾,應(yīng)用程序完全不用考慮沖正邏輯。
            在一個(gè)涉及多個(gè)數(shù)據(jù)庫(kù)的全局事務(wù)中,為保證全局事務(wù)的完整性,由交易中間件控制數(shù)據(jù)庫(kù)做兩階段提交是必要的。但典型的兩階段提交,對(duì)數(shù)據(jù)庫(kù)來(lái)說(shuō)事務(wù)從開(kāi)始到結(jié)束(提交或回滾)時(shí)間相對(duì)較長(zhǎng),在事務(wù)處理期間數(shù)據(jù)庫(kù)使用的資源(如邏輯日志、各種鎖),直到事務(wù)結(jié)束時(shí)才會(huì)釋放。因此,使用典型的兩階段提交相對(duì)來(lái)說(shuō)會(huì)占用更多的資源,在網(wǎng)絡(luò)條件不是很好,如低速網(wǎng)、網(wǎng)絡(luò)顛簸頻繁,情況會(huì)更為嚴(yán)重。
            當(dāng)一個(gè)全局事務(wù)只涉及一個(gè)數(shù)據(jù)庫(kù)時(shí),有一種優(yōu)化方式,即一階段提交。當(dāng) AP 通知交易中間件提交事務(wù)時(shí),交易中間件直接要求數(shù)據(jù)庫(kù)提交事務(wù),省去兩階段提交中的第一階段,可以縮短處理一個(gè)事務(wù)的時(shí)間,以提高事務(wù)處理的效率。作為兩階段提交的一種特例,與兩階段一樣,一階段提交也是標(biāo)準(zhǔn)的。

          posted @ 2007-03-06 10:11 rednight 閱讀(11415) | 評(píng)論 (6)編輯 收藏

          If you encountered “ Cannot call Connection.commit in distributed transaction ” error, should check the weblogic connection pool and the datasource

          ?

          If the connection pool is XA,

          you should make sure that when you create the datasource to make it XA by select the check from "Honor Global Transaction" from the weblogic console.(default is selected)

          If the connection pool is non-XA

          you should make sure that when you create the datasource to make it non-XA by remove the check from "Honor Global Transaction" from the weblogic console.

          posted @ 2007-03-06 09:58 rednight 閱讀(2497) | 評(píng)論 (2)編輯 收藏

          問(wèn)題描述:
              <[ServletContext(id=18489944,name=EBLGWeb,context-path=/)]: Deployment descriptor "/WEB-INF/bhr-tags-pagination.tld" is malformed. Check against the DTD: Content is not allowed in prolog. (line 1, column 1).>
              <[ServletContext(id=18489944,name=EBLGWeb,context-path=/)]: Error while parsing the Tag Library Descriptor at "/WEB-INF/bhr-tags-pagination.tld".
          org.xml.sax.SAXException: [HTTP:101248][ServletContext(id=18489944,name=EBLGWeb,context-path=/)]: Deployment descriptor "/WEB-INF/bhr-tags-pagination.tld" is malformed. Check against the DTD: Content is not allowed in prolog. (line 1, column 1).
                  at weblogic.apache.xerces.parsers.DOMParser.parse(DOMParser.java:285)
                  at weblogic.apache.xerces.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:201)
                  at weblogic.servlet.jsp.dd.JSPEntityResolver.load(JSPEntityResolver.java:81)
                  at weblogic.servlet.jsp.dd.JSPEntityResolver.load(JSPEntityResolver.java:96)
                  at weblogic.servlet.internal.WebAppHelper.registerTagLibListeners(WebAppHelper.java:293)
                  at weblogic.servlet.internal.WebAppServletContext.activateFromDescriptors(WebAppServletContext.java:2530)
                  at weblogic.servlet.internal.WebAppServletContext.activate(WebAppServletContext.java:6163)
                  at weblogic.servlet.internal.WebAppServletContext.setActive(WebAppServletContext.java:6141)
                  at weblogic.servlet.internal.WebAppModule.activate(WebAppModule.java:836)
                  at weblogic.j2ee.J2EEApplicationContainer.activateModule(J2EEApplicationContainer.java:3322)
                  at weblogic.j2ee.J2EEApplicationContainer.activate(J2EEApplicationContainer.java:2201)
                  at weblogic.j2ee.J2EEApplicationContainer.activate(J2EEApplicationContainer.java:2174)
                  at weblogic.j2ee.J2EEApplicationContainer.activate(J2EEApplicationContainer.java:2122)
                  at weblogic.management.deploy.slave.SlaveDeployer$Application.setActivation(SlaveDeployer.java:3099)
                  at weblogic.management.deploy.slave.SlaveDeployer.setActivationStateForAllApplications(SlaveDeployer.java:1768)
                  at weblogic.management.deploy.slave.SlaveDeployer.resume(SlaveDeployer.java:351)
                  at weblogic.management.deploy.DeploymentManagerServerLifeCycleImpl.resume(DeploymentManagerServerLifeCycleImpl.java:229)
                  at weblogic.t3.srvr.SubsystemManager.resume(SubsystemManager.java:136)
                  at weblogic.t3.srvr.T3Srvr.resume(T3Srvr.java:965)
                  at weblogic.t3.srvr.T3Srvr.run(T3Srvr.java:360)
                  at weblogic.Server.main(Server.java:32)
          >
          
          原因分析和解決方法:
          是由于某些文本編輯器(UltraEdit)存文本的時(shí)候產(chǎn)生的問(wèn)題。可以使用text pad, word pad編輯XML格式的文件。
          

          posted @ 2007-01-16 09:09 rednight 閱讀(1355) | 評(píng)論 (0)編輯 收藏

          問(wèn)題描述:
          通過(guò)HTTP提交EDI請(qǐng)求,當(dāng)EDI處理時(shí)間超過(guò)了20分鐘后,就會(huì)看到在另一個(gè)weblogic server也接收到了這個(gè)EDI請(qǐng)求,重新處理這個(gè)報(bào)文.
          如果報(bào)文處理時(shí)間更長(zhǎng),比如超過(guò)了50分鐘,就會(huì)發(fā)現(xiàn)這個(gè)報(bào)文被處理了3遍或5遍.
          
          原因分析和解決方法:
          When the Apache HTTP Server Plug-In attempts to connect to WebLogic Server, the plug-in uses several configuration 
          parameters to determine how long to wait for connections to the WebLogic Server host and, after a connection is
          established, how long the plug-in waits for a response. If the plug-in cannot connect or does not receive a response, 
          the plug-in attempts to connect and send the request to other WebLogic Server instances in the cluster. If the 
          connection fails or there is no response from any WebLogic Server in the cluster, an error message is sent.
          
          
          響應(yīng)等待時(shí)間參數(shù)WLIOTimeoutSecs (http://e-docs.bea.com/wls/docs81/plugins/plugin_params.html#1149781.
          按照BEA 推薦的,這個(gè)值應(yīng)該設(shè)得大一些, 這個(gè)參數(shù)的缺省值為300s. 見(jiàn)下面:
          <Location /EDIHandler>
                   SetHandler weblogic-handler
                   WebLogicCluster apc_app1wls1:7011,apc_app1wls2:7011
                   KeepAliveEnabled ON
                   WLIOTimeoutSecs 7200
          </Location>
          

          posted @ 2007-01-16 09:09 rednight 閱讀(1429) | 評(píng)論 (0)編輯 收藏

          有時(shí)候使用的mq jar文件的版本不對(duì)給出現(xiàn)一些末名奇妙的問(wèn)題,本文則是能接收消息但不能發(fā)送消息的一個(gè)問(wèn)題.碰到這樣的問(wèn)題一定要記得double-check你使用的mq jar文件的版本


          問(wèn)題描述:
          MQJMS200713 Oct 2006 16:47:15,484 ERROR MessagingUtilServlet [ExecuteThread: '14' for queue: 'weblogic.kernel.Default'][]: **********EXCEPTION TRACE START*************
          13 Oct 2006 16:47:15,484 ERROR MessagingUtilServlet [ExecuteThread: '14' for queue: 'weblogic.kernel.Default'][]: produce error
          com.bhr.infra.messaging.exception.PMException: JMSException
                  at com.bhr.infra.messaging.PMHandler.send(PMHandler.java:419)
                  at com.bhr.epc.infra.messaging.util.MessagingUtilServlet.produce(MessagingUtilServlet.java:312)
                  at com.bhr.epc.infra.messaging.util.MessagingUtilServlet.service(MessagingUtilServlet.java:74)
                  at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
                  at weblogic.servlet.internal.ServletStubImpl$ServletInvocationAction.run(ServletStubImpl.java:1072)
                  at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:465)
                  at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:348)
                  at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:6981)
                  at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
                  at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
                  at weblogic.servlet.internal.WebAppServletContext.invokeServlet(WebAppServletContext.java:3892)
                  at weblogic.servlet.internal.ServletRequestImpl.execute(ServletRequestImpl.java:2766)
                  at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:224)
                  at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:183)
          Caused by: javax.jms.JMSException: MQJMS2007: failed to send message to MQ queue
                  at com.ibm.mq.jms.services.ConfigEnvironment.newException(ConfigEnvironment.java:553)
                  at com.ibm.mq.jms.MQMessageProducer.sendInternal(MQMessageProducer.java:1589)
                  at com.ibm.mq.jms.MQMessageProducer.send(MQMessageProducer.java:1012)
                  at com.ibm.mq.jms.MQMessageProducer.send(MQMessageProducer.java:1046)
                  at com.bhr.infra.messaging.PMQueueSender.send(PMQueueSender.java:57)
                  at com.bhr.infra.messaging.PMHandler.send(PMHandler.java:410)
                  ... 13 more
          13 Oct 2006 16:47:15,486 ERROR MessagingUtilServlet [ExecuteThread: '14' for queue: 'weblogic.kernel.Default'][]: **********EXCEPTION TRACE END**************
          
          
          原因分析和解決方法:
          It may be caused by use of old version MQ jar. It can receive message, but cannot send message.
          

          posted @ 2007-01-16 09:08 rednight 閱讀(1139) | 評(píng)論 (0)編輯 收藏

          如果你碰到"Cannot Forward a Response that is Already Committed"這樣的錯(cuò)誤信息,一定是應(yīng)用對(duì)一次http請(qǐng)求做了多次頁(yè)面跳轉(zhuǎn)或?qū)esponse對(duì)象做過(guò)close后,又去寫響應(yīng).

          這個(gè)問(wèn)題的根本原因由于響應(yīng)本次請(qǐng)求的Response對(duì)象的狀態(tài)是已提交狀態(tài)造成的, 它不允許響應(yīng)提交多次。
          
          什么時(shí)候Response對(duì)象的狀態(tài)變成已提交狀態(tài):當(dāng)你的應(yīng)用已經(jīng)實(shí)現(xiàn)了頁(yè)面跳轉(zhuǎn)邏輯。
          
          通常原因:
          
          1. 如果你使用了community的話, community的安全認(rèn)證和授權(quán)如果沒(méi)有通過(guò),community內(nèi)部會(huì)進(jìn)行頁(yè)面跳轉(zhuǎn)。但你的應(yīng)用(對(duì)于workshop應(yīng)用的話,指的是action)又試圖進(jìn)行頁(yè)面跳轉(zhuǎn),就會(huì)出現(xiàn)這樣的問(wèn)題。
          
          
              /**
          
               * @jpf:action
          
               * @jpf:forward name="page" path="page.jsp"
          
               */
          
              protected Forward actionMethod()
          
          {
          
              //如果已經(jīng)提交了響應(yīng),你仍然試圖再次進(jìn)行頁(yè)面跳轉(zhuǎn),即再次提交響應(yīng),可能出現(xiàn)問(wèn)題
          
              //通常可以加一個(gè)判斷
          
           
          
                 if (!getResponse().isCommitted()) {
          
                      return new Forward("success");
          
                  } else {
          
                      return null;
          
                  }
          
              }
          
           
          
              protected void beforeAction() {
          
                 SecurityManager.checkAuthorization(getRequest(), getResponse(), config.getString(
          
                          CDConstants.CREATE_TERM_ACTION_NAME, ""));
          
                //這個(gè)調(diào)用可能實(shí)現(xiàn)了頁(yè)面跳轉(zhuǎn),即提交響應(yīng)
          
          }
          
           
          
          注意JSP中實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)后,加return 語(yǔ)句防止繼續(xù)提交響應(yīng):
          
           
          
          <%
          
                 SecurityManager.checkAuthorization(getRequest(), getResponse(), config.getString(
          
                          CDConstants.CREATE_TERM_ACTION_NAME, ""));
          
          {
          
               //可能有實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)邏輯
          
              ……………forward();
          
                  return;//記得加retrun.
          
              }
          
          %>
          
           
          
          2. .如果沒(méi)有使用community的話,下面情景也會(huì)出現(xiàn)這個(gè)問(wèn)題
          
           
          
              /**
          
               * @jpf:action
          
               * @jpf:forward name="page" path="page.jsp"
          
               */
          
              protected Forward actionMethod()
          
           
          
          //直接操作Response對(duì)象寫響應(yīng)
          
               getResponse().getPrintWriter().println();
          
              …
          
          /
          
             // 又執(zhí)行的頁(yè)面跳轉(zhuǎn),也可能出現(xiàn)問(wèn)題
          
                  return new Forward("index");
          
              }
          

          posted @ 2007-01-16 09:07 rednight 閱讀(7058) | 評(píng)論 (5)編輯 收藏

          一個(gè)頁(yè)面流在第一次使用時(shí),內(nèi)部屬性currentpage并沒(méi)有指定頁(yè)面,所以避免在begin方法里使用return-to: current page用法.同時(shí)在用的時(shí)候注意頁(yè)面流的工作方式


          問(wèn)題描述:
          Error message like below in Web Page is displayed:
          
          Page Flow:
           /com/xxxx/xxx/xxx.jpf
          Action:
           update
           
          Page Flow Error - No Relevant Page
          You have tried to return to a recent page in the current page flow through return-to="currentPage", 
          but there is no appropriate page. 
          
          
          Exception's stack trace:
          
          Exception: No previous page for return-to="currentPage" on action create in page flow
           /com/gems/mt/web/CreateReleaseCntr/CreateReleaseCntrController.jpf.
          com.bea.wlw.netui.pageflow.NoPreviousPageException: No relevant page for return-to="currentPage" 
          on action create in page flow /com/gems/mt/web/CreateReleaseCntr/CreateReleaseCntrController.jpf.
          at com.bea.wlw.netui.pageflow.FlowController.doReturnToPage(FlowController.java:1328)
          at com.bea.wlw.netui.pageflow.FlowController.forwardTo(FlowController.java:1023)
          at com.bea.wlw.netui.pageflow.PageFlowController.forwardTo(PageFlowController.java:606)
          at com.bea.wlw.netui.pageflow.FlowController.internalExecute(FlowController.java:765)
          
          ...
          
          
          
          原因分析和解決方法:
          When a new page flow is created and its current page is null (it mean you visit at the fist time),
           so such an exception like NoPreviousPageException occur if you use return-to="currentPage".
          
          if a new page flow finish a successful forward, it will treat last page as current page
          
          so that we can use current page to display error message conveniently.
          
          Solution:
          
          ensure page flow finish a successful forward and use current page again.
          
          You can also use path="specificPage.jsp" instead of return-to="currentPage" 
          if your original return-to is just one specific page.
          
          

          posted @ 2007-01-16 09:06 rednight 閱讀(752) | 評(píng)論 (0)編輯 收藏

          We have known, the ListCellRenderer interface has only one method public Component getListCellRendererComponent(), and it returns a Component. When a JList needs to compute its dimension or paint its cell item, this method will be called. So it will be called frequently, and we have a best practice, try to reuse object, avoid time-consumed computation and unnecessary operation in this method.

          ?

          Recently found, there is a memory leak bug for list cell renderer in both JDK 1.4.x and JDK 5 (don’t know whether has the same bug in earlier JDK). The component returned from getListCellRendererComponent() method could not be GC, and all its referenced objects also could not be GC. Unfortunately, this bug is only fixed in JDK 6.

          ?

          So currently, if a JList use the ListCellRenderer, but only holds a little resource (eg: the JList only has little items, and the component is returned from ListCellRenderer is a simple JLable), you may not care about the memory leak.

          ?

          But if a JList use the ListCellRenderer, and holds a large resource, you should remember to use the following way to avoid memory leak.

          ?

          Work Around: Subclass JList and invoke removeAll after painting is done:

          ?????? public class xxxList extends JList {

          ??????????? private CellRendererPane renderer;

          ??????????? private CellRendererPane getRenderer() {

          ??????????????? if (renderer == null) {

          ??????????????????? for (int i=0; i<getComponents().length; i++) {

          ????????????????????????????????????????? Component c? = getComponents()[i];

          ??????????????????????? if (c instanceof CellRendererPane) {

          ??????????????????????????? renderer = (CellRendererPane)c;

          ??????????????????????????? break;

          ??????????????????????? }

          ??????????????????? }

          ??????????????? }

          ??????????????? return renderer;

          ??????????? }

          ??????????? protected void paintComponent(Graphics g) {

          ??????????????? super.paintComponent(g);

          ??????????????? CellRendererPane renderer = getRenderer();

          ??????????????? if (renderer != null) {

          ??????????????????? renderer.removeAll();

          ??????????????? }

          ??????????? }

          ??????? }


          Please refer to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5044798 for more details.

          posted @ 2007-01-16 09:04 rednight 閱讀(437) | 評(píng)論 (0)編輯 收藏

          The logic to change state is only inside one method (initVesselView(…)) inside GrVessel.java.?

          if (viewType == VIEW_STOWAGE) {
          ??????????? vslView_ = new VesselStowageView(leftPoint, bow2Left, leftCenter,
          ???????????????????????????????????????????? rightCenter, shipWidth_);
          ??????? }
          ??????? else if (viewType == VIEW_SIDE) {
          ??????????? vslView_ = new VesselSideView(leftPoint, bow2Left, leftCenter,
          ????????????????????????????????????????? rightCenter, shipWidth_);
          ??????? }
          ??????? else if (viewType == VIEW_PLAN) {
          ??????????? vslView_ = new VesselPlanView(leftPoint, bow2Left, leftCenter,
          ????????????????????????????????????????? rightCenter, shipWidth_);
          ??????? }
          ??????? else {
          ??????????? throw new IllegalArgumentException(
          ??????????????? "GrVessel::initVesselView-->Invalid view type!");
          ??????? }


          We do not need to repeat this logic of changing view in many other method.
          This is the benefit of State design pattern.
          The 3 state classes here are VesselPlanView.java, VesselSideView.java and VesselStowageView.java

          Please note that in the state classes, if a method is supported by stateA and not supported by stateB.?
          Then, in stateB, the method body will throw an exception (IllegalArgumentException) to indicate that coder call the wrong method in the wrong state.

          Example, in VesselPlanView.java, public boolean addStowage(...).? This method is only meaningful to stowageView.

          public boolean addStowage(IlvManager manager, List transformList, IlvGraphic stowage, String stadBayN,
          ????????????????????????????? boolean isSelect) {
          ??????? throw new IllegalArgumentException(
          ??????????????? "GrVessel::addStowage-->be sure the vessel at stowage view!");
          ??? }


          Hence, in PlanView, the method body will throw exception.

          Just to share with you a better way to code.

          posted @ 2006-12-26 14:46 rednight 閱讀(349) | 評(píng)論 (0)編輯 收藏

               摘要: 本文討論模型過(guò)濾技術(shù)。您可將這一技術(shù)用于 Swing 組件集,這樣即可在不改變底層數(shù)據(jù)的條件下提供模型數(shù)據(jù)的不同視圖。過(guò)濾器可以改變數(shù)據(jù)元素的外在內(nèi)容,將數(shù)據(jù)排除在視圖之外、將外部元素包含進(jìn)數(shù)據(jù)集中、或者以不同的順序呈現(xiàn)元素。過(guò)濾器既可應(yīng)用于數(shù)據(jù)模型,也可應(yīng)用于狀態(tài)模型。您還可以疊用過(guò)濾器,以將它們的效果組合起來(lái)。  閱讀全文

          posted @ 2006-11-11 16:16 rednight| 編輯 收藏

          有時(shí)運(yùn)行ANT 時(shí)會(huì)拋出 java.lang.InstantiationException: org.apache.tools.ant.Main 異常
          原因之一是在機(jī)器中存在2種不同版本的ANT,我碰到的情況是classpath 中即有weblogic.jar,又有1.6.5的ANT,
          刪除weblogic.jar后運(yùn)行就正常了

          posted @ 2006-11-09 18:23 rednight 閱讀(1756) | 評(píng)論 (1)編輯 收藏

          public class GroupableHeaderExample extends JFrame {

          ? GroupableHeaderExample() {
          ??? super( "Groupable Header Example" );

          ??? DefaultTableModel dm = new DefaultTableModel();
          ??? dm.setDataVector(new Object[][]{
          ????? {"119","foo","bar","ja","ko","zh"},
          ????? {"911","bar","foo","en","fr","pt"}},
          ??? new Object[]{"SNo.","1","2","Native","2","3"});

          ??? JTable table = new JTable( dm ) {
          ????? protected JTableHeader createDefaultTableHeader() {
          ? return new GroupableTableHeader(columnModel);
          ????? }
          ??? };
          ??? TableColumnModel cm = table.getColumnModel();
          ??? ColumnGroup g_name = new ColumnGroup("Name");
          ??? g_name.add(cm.getColumn(1));
          ??? g_name.add(cm.getColumn(2));
          ??? ColumnGroup g_lang = new ColumnGroup("Language");
          ??? g_lang.add(cm.getColumn(3));
          ??? ColumnGroup g_other = new ColumnGroup("Others");
          ??? g_other.add(cm.getColumn(4));
          ??? g_other.add(cm.getColumn(5));
          ??? g_lang.add(g_other);
          ??? GroupableTableHeader header = (GroupableTableHeader)table.getTableHeader();
          ??? header.addColumnGroup(g_name);
          ??? header.addColumnGroup(g_lang);

          ??? TableCellRenderer renderer =? new DefaultTableCellRenderer() {
          ??????? public Component getTableCellRendererComponent(JTable table, Object value,
          ???????????????????????? boolean isSelected, boolean hasFocus, int row, int column) {
          ????????? JTableHeader header = table.getTableHeader();
          ????????? if (header != null) {
          ??????????? setForeground(header.getForeground());
          ??????????? setBackground(header.getBackground());
          ??????????? setFont(header.getFont());
          ????????? }
          ????????? setHorizontalAlignment(JLabel.CENTER);
          ????????? setText((value == null) ? "" : value.toString());
          ????????? setBorder(UIManager.getBorder("TableHeader.cellBorder"));
          ????????? return this;
          ??????? }
          ????? };

          ??? TableColumnModel model = table.getColumnModel();
          ??? for (int i=0;i<model.getColumnCount();i++) {
          ????? model.getColumn(i).setHeaderRenderer(renderer);
          ??? }
          ??? JScrollPane scroll = new JScrollPane( table );
          ??? getContentPane().add( scroll );
          ??? setSize( 400, 120 );
          ? }

          ? public static void main(String[] args) {
          ??? GroupableHeaderExample frame = new GroupableHeaderExample();
          ??? frame.addWindowListener( new WindowAdapter() {
          ????? public void windowClosing( WindowEvent e ) {
          ? System.exit(0);
          ????? }
          ??? });
          ??? frame.setVisible(true);
          ? }
          }

          =============================================
          public void paint(Graphics g, JComponent c) {
          ??? Rectangle clipBounds = g.getClipBounds();
          ??? if (header.getColumnModel() == null) return;
          //??? ((GroupableTableHeader)header).setColumnMargin();
          ??? int column = 0;
          ??? Dimension size = header.getSize();
          ??? Rectangle cellRect? = new Rectangle(0, 0, size.width, size.height);
          ??? Hashtable h = new Hashtable();
          //??? int columnMargin = header.getColumnModel().getColumnMargin();

          ??? Enumeration enumeration = header.getColumnModel().getColumns();
          ??? while (enumeration.hasMoreElements()) {
          ????? cellRect.height = size.height;
          ????? cellRect.y????? = 0;
          ????? TableColumn aColumn = (TableColumn)enumeration.nextElement();
          ????? Enumeration cGroups = ((GroupableTableHeader)header).getColumnGroups(aColumn);
          ????? if (cGroups != null) {
          ??????? int groupHeight = 0;
          ??????? while (cGroups.hasMoreElements()) {
          ????????? ColumnGroup cGroup = (ColumnGroup)cGroups.nextElement();
          ????????? Rectangle groupRect = (Rectangle)h.get(cGroup);
          ????????? if (groupRect == null) {
          ??????????? groupRect = new Rectangle(cellRect);
          ??????????? Dimension d = cGroup.getSize(header.getTable());
          ??????????? groupRect.width? = d.width;
          ??????????? groupRect.height = d.height;
          ??????????? h.put(cGroup, groupRect);
          ????????? }
          ????????? paintCell(g, groupRect, cGroup);
          ????????? groupHeight += groupRect.height;
          ????????? cellRect.height = size.height - groupHeight;
          ????????? cellRect.y????? = groupHeight;
          ??????? }
          ????? }
          ????? cellRect.width = aColumn.getWidth() ;//+ columnMargin;
          ????? if (cellRect.intersects(clipBounds)) {
          ??????? paintCell(g, cellRect, column);
          ????? }
          ????? cellRect.x += cellRect.width;
          ????? column++;
          ??? }
          ? }



          posted @ 2006-11-08 21:05 rednight| 編輯 收藏

          使用 IlvToolTipManager 創(chuàng)建一個(gè)多行的 tooltip ?

          1) 首先需要注冊(cè) view (IlvManagerView)I
          lvToolTipManager.registerView(view); ?

          2) 創(chuàng)建需要顯示的信息的數(shù)組,即每行的信息為數(shù)組中的一個(gè)元素:
          new String[] tooltipArray ; ?

          3) 創(chuàng)建 tooltip, 第一個(gè)參數(shù)是上面創(chuàng)建的數(shù)組,第二個(gè)參數(shù)是顯示位置,必須是 SwingConstants.LEFT , RIGHT , or CENTER String tooltip = IlvToolTipManager.createMultiLineToolTipText(tooltipArray, SwingConstants.LEFT); ?

          4) 設(shè)置 tooltip
          IlvGraphic.setToolTipText(tooltip);



          public static String createMultiLineToolTipText(String as[], int i)
          ??? {
          ??????? String s;
          ??????? switch(i)
          ??????? {
          ??????? case 2: // '\002'
          ??????????? s = "left";
          ??????????? break;

          ??????? case 4: // '\004'
          ??????????? s = "right";
          ??????????? break;

          ??????? case 0: // '\0'
          ??????????? s = "center";
          ??????????? break;

          ??????? case 1: // '\001'
          ??????? case 3: // '\003'
          ??????? default:
          ??????????? throw new IllegalArgumentException("Alignment must be LEFT, RIGHT, or CENTER");
          ??????? }
          ??????? Font font = UIManager.getFont("ToolTip.font");
          ??????? StringBuffer stringbuffer = new StringBuffer("<p align=\"");
          ??????? stringbuffer.append(s);
          ??????? stringbuffer.append("\" style=\"font-family:");
          ??????? stringbuffer.append(font.getName());
          ??????? stringbuffer.append(";font-size:");
          ??????? stringbuffer.append(font.getSize());
          ??????? stringbuffer.append("pt\">");
          ??????? String s1 = stringbuffer.toString();
          ??????? StringBuffer stringbuffer1 = new StringBuffer("<html>");
          ??????? for(int j = 0; j < as.length; j++)
          ??????? {
          ??????????? stringbuffer1.append(s1);
          ??????????? stringbuffer1.append(as[j]);
          ??????????? stringbuffer1.append("</p>");
          ??????? }

          ??????? stringbuffer1.append("</html>");
          ??????? return stringbuffer1.toString();
          ??? }

          ?

          posted @ 2006-11-08 09:22 rednight 閱讀(273) | 評(píng)論 (0)編輯 收藏

          下面這個(gè)異常是因?yàn)闆](méi)有找到EJB, JNDI NAME 本來(lái)是 'ejb/ppp/sss/Resource' ,? 可找的卻是'ejb.ppp.sss/Resource' ,
          后來(lái)查到是因?yàn)?font color="#ff0033">EJB 的REMOTE 接口中的方法在BEAN中沒(méi)有定義
          . 不知道還有沒(méi)有其他什么原因可以導(dǎo)致這種情況.

          Caused by: javax.naming.NameNotFoundException: While trying to lookup 'ejb.ppp.sss/Resource' didn't find subcontext 'ppp' Resolved ejb
          ?at weblogic.jndi.internal.BasicNamingNode.newNameNotFoundException(BasicNamingNode.java:924)
          ?at weblogic.jndi.internal.BasicNamingNode.lookupHere(BasicNamingNode.java:225)
          ?at weblogic.jndi.internal.ServerNamingNode.lookupHere(ServerNamingNode.java:154)
          ?at weblogic.jndi.internal.BasicNamingNode.lookup(BasicNamingNode.java:188)
          ?at weblogic.jndi.internal.BasicNamingNode.lookup(BasicNamingNode.java:196)
          ?at weblogic.jndi.internal.RootNamingNode_WLSkel.invoke(Unknown Source)
          ?at weblogic.rmi.internal.BasicServerRef.invoke(BasicServerRef.java:492)
          ?at weblogic.rmi.cluster.ReplicaAwareServerRef.invoke(ReplicaAwareServerRef.java:108)
          ?at weblogic.rmi.internal.BasicServerRef$1.run(BasicServerRef.java:435)
          ?at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363)
          ?at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:147)
          ?at weblogic.rmi.internal.BasicServerRef.handleRequest(BasicServerRef.java:430)
          ?at weblogic.rmi.internal.BasicExecuteRequest.execute(BasicExecuteRequest.java:35)
          ?at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:224)
          ?at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:183)

          posted @ 2006-11-08 08:51 rednight 閱讀(482) | 評(píng)論 (0)編輯 收藏

               摘要: 我們期待自己成為一個(gè)優(yōu)秀的軟件模型設(shè)計(jì)者,但是,要怎樣做,又從哪里開(kāi)始呢?

            將下列原則應(yīng)用到你的軟件工程中,你會(huì)獲得立桿見(jiàn)影的成果  閱讀全文

          posted @ 2006-09-24 11:46 rednight 閱讀(112) | 評(píng)論 (0)編輯 收藏

          Eclipse插件下載列表
          MyEclipse:J2EE開(kāi)發(fā)插件,支持JSP、EJB、數(shù)據(jù)庫(kù)等操作。
          下載站點(diǎn):www.myeclipseide.com

          Lomboz:和MyEclipse的同類型插件且免費(fèi)。
          下載站點(diǎn):http://forge.objectweb.org/project/showfiles.php?group_id=97

          XMLBuddy:xml文件編輯器
          下載站點(diǎn):www.xmlbuddy.com

          Fat Jar:項(xiàng)目打包插件,可以將項(xiàng)目支持包和項(xiàng)目本身打成一個(gè)包。
          下載站點(diǎn):http://fjep.sourceforge.net/

          Jinto:國(guó)際化插件
          下載站點(diǎn):http://www.guh-software.de/

          Jasper Assistant:報(bào)表插件
          下載站點(diǎn):http://www.jasperassistant.com/

          Log4E Log4j插件,提供Log4j的快速操作。Log4j專用于為程序輸入調(diào)試信息。
          下載站點(diǎn):http://log4e.jayefem.de/index.php/Main_Page

          VSSplugin: VSS客戶端插件,VSS是一個(gè)和CVS齊名的版本管理系統(tǒng)。
          下載站點(diǎn):http://sourcefore.net/projects/vssplugin

          Implementors: 當(dāng)追蹤方法代碼時(shí),Eclipse默認(rèn)是轉(zhuǎn)到方法的接口類,而接口中是只有方法名稱沒(méi)有代碼的。此插件提供了追蹤到方法的實(shí)現(xiàn)代碼功能。
          下載頁(yè)面:http://eclipse-tools.sourceforge.net/implementors/

          Call Hierarchy: 顯示一個(gè)方法的調(diào)用層次,可以從中看到它被哪些方法調(diào)用了,以及它調(diào)用了哪些方法,是代碼追蹤比較實(shí)用的工具。
          下載站點(diǎn):http://eclipse-tools.sourceforge.net/ccall-hierarchy/

          Hebernate Synchronizer: Hibernate插件,提供Hibernate的自動(dòng)映射等操作。
          下載站點(diǎn):http://www.binamics.com/hibernatesync/

          Profiler: 性能跟蹤、測(cè)量工具,能跟蹤、測(cè)試B/S模式開(kāi)發(fā)的程序。
          下載站點(diǎn):http://sourceforge.net/projects/eclipsecolorer/

          myeclipse
          http://www.myeclipseide.com/ContentExpress-display-ceid-10.html


          WindowBuilder Pro - SWT/Swing Designer
          http://www.swt-designer.com/

          posted @ 2006-09-07 10:01 rednight| 編輯 收藏

          WLS 9.1與MQ v5.3 通過(guò)JMS Bridge通信配置

          時(shí)間:2006-06-27
          作者:孟和
          瀏覽次數(shù): 1229
          本文關(guān)鍵字:WebLogic,?MQ,?JMS,?MQSeries,?JMS Bridge
          文章工具
          推薦給朋友?推薦給朋友
          打印文章?打印文章

            最近參與一個(gè)系統(tǒng)的原型開(kāi)發(fā),原型要求演示W(wǎng)ebLogic Server9.1與其他第三方產(chǎn)品的通信支持,包括與IBM MQSeries的雙向交互、與Tuxedo的雙向交互、支持與.NET的通過(guò)Web Service交互等。我負(fù)責(zé)完成與IBM MQSeries的雙向交互這部分,在網(wǎng)上找了不少文章,發(fā)現(xiàn)其中基本都是基于WebLogic Server 8.1實(shí)現(xiàn)的。因?yàn)閃ebLogic Server 9.1在JMS上有很大的增強(qiáng),所以我參考以前的文章,自己實(shí)現(xiàn)了WebLogic Server 9.1與IBM MQSeries 5.3的雙向交互并且進(jìn)行了測(cè)試。想必很多同行會(huì)遇到跟我一樣的問(wèn)題,特此撰文一片跟大家分享。本文配置在window xp上測(cè)試成功。

          概述

            目標(biāo)是實(shí)現(xiàn)WebLogic Server 9.1和IBM MQSeries5.3之間的的雙向交互,包括:

          • WebLogic Server 9.1消息轉(zhuǎn)發(fā)給IBM MQSeries5.3
          • IBM MQSeries 5.3消息轉(zhuǎn)發(fā)給WebLogic Server 9.1

            具體地,將WebLogic Server9.1隊(duì)列WLSSendQueue的消息轉(zhuǎn)發(fā)到IBM MQSeries 5.3隊(duì)列MQReceiveQueue,同時(shí)將IBM MQSeries 5.3隊(duì)列MQSendQueue的消息轉(zhuǎn)發(fā)到WebLogic Server 9.1隊(duì)列WLSSendQueue。

            WebLogic Server包含一個(gè)完整的、有豐富特性的消息服務(wù)器。第三方的消息服務(wù)器(如IBM MQSeries),只要其提供了JMS API的實(shí)現(xiàn),也可以在其中運(yùn)行。Messaging Bridge是一種由WebLogic Server提供的J2EE設(shè)備,用于轉(zhuǎn)發(fā)兩個(gè)消息提供者的消息。你可以使用Messaging Bridge將消息從一個(gè)消息提供者的目的地(隊(duì)列或者主題)移至另外一個(gè)消息提供者的目的地。因此,當(dāng)WebLogic應(yīng)用程序需要與第三方消息提供者 (比如IBM MQSeries)進(jìn)行交互時(shí),Messaging Bridge就可以承擔(dān)這個(gè)中間角色。我們需要做如下配置:

          • 通過(guò)WebLogic控制臺(tái)建立兩個(gè)WebLogic隊(duì)列:發(fā)送隊(duì)列WLSSendQueue和接收隊(duì)列WLSReceiveQueue。
          • 類似地,通過(guò)MQ資源管理器建立兩個(gè)MQ本地隊(duì)列:發(fā)送隊(duì)列MQSendQueue和接收隊(duì)列MQReceiveQueue。
          • 為 了實(shí)現(xiàn)消息轉(zhuǎn)發(fā)需要建立兩個(gè)Messaging Bridge:WLS2MQBridge 和MQ2WLSBridge 。WLS2MQBridge:將WebLogic發(fā)送隊(duì)列WLSSendQueue的消息轉(zhuǎn)發(fā)到MQ接收隊(duì)列MQReceiveQueue; MQ2WLSBridge:將MQ發(fā)送隊(duì)列MQSendQueue的消息轉(zhuǎn)發(fā)到WebLogic接收隊(duì)列WLSReceiveQueue。
          • 為 了實(shí)現(xiàn)事務(wù)性消息轉(zhuǎn)發(fā), WebLogic需要使用XAQueueConnectionFactory,而MQ需要使用MQXAQueueConnectionFactory。這 就確定了WebLogic需要使用支持XA的連接工廠,MQ必須采用綁定的模式,并且WebLogic和MQ必須安裝在同一臺(tái)機(jī)器上。

          WLS配置

            WebLogic Server 9.1在WebLogic JMS的配置、部署和動(dòng)態(tài)管理方面引入了重要的改進(jìn)。它對(duì)JMS 1.1規(guī)范提供官方支持。此外,在系統(tǒng)中添加了人們期待已久的消息排序高級(jí)特性。XML API的XML消息處理功能得到了增強(qiáng)。在WebLogic 9.1平臺(tái)上使用JMS非常輕松有趣、可靠且迅速。下面是現(xiàn)有新特性中的一些亮點(diǎn)。

          • 自動(dòng)化的 JMS 故障恢復(fù)

              自動(dòng)化的JMS故障恢復(fù)是業(yè)內(nèi)期待已久的特性。JMS利用“Automatic WebLogic Server Migration”特性來(lái)提供自動(dòng)化的JMS故障恢復(fù)。在整個(gè)WebLogic Server實(shí)例進(jìn)行故障恢復(fù)時(shí),JMS也將自動(dòng)從故障中恢復(fù)過(guò)來(lái)。盡管其他的一些JMS服務(wù)器提供商已經(jīng)利用一些復(fù)雜裝置提供了這樣的功能,但 WebLogic 9.1的實(shí)現(xiàn)是最直觀而清晰的。

          • 排序單元

              消息排序是大多數(shù)消息處理應(yīng)用程序的一項(xiàng)基本要求。WebLogic Server JMS即使在集群環(huán)境中也能確保消息的順序處理。它甚至可以定義多個(gè)組來(lái)將消息分組,這樣每個(gè)組都擁有自己的處理順序(如圖1所示)。

            圖1

          • 存儲(chǔ)轉(zhuǎn)發(fā) (SAF)

              WebLogic存儲(chǔ)轉(zhuǎn)發(fā)(store and forward, SAF)服務(wù)使WebLogic Server能在通過(guò)WebLogic Server實(shí)例部署的應(yīng)用程序間可靠地交付信息。SAF的強(qiáng)大功能使得我們可以很容易地將多個(gè)消息服務(wù)鏈接在一起(如圖2所示)。

            圖2

          • Messaging Bridge具有如下優(yōu)點(diǎn):
            • 不需要編碼,純配置,加速你的開(kāi)發(fā);
            • 靈活的體系結(jié)構(gòu),容易配置多個(gè)Messaging Bridges,并且而且可以動(dòng)態(tài)的啟動(dòng)和停止單個(gè)Messaging Bridge;
            • 采用即取即用的MQ 適配器,實(shí)現(xiàn)全面的MQ JMS 支持,能夠設(shè)定MQ 主題查詢;
            • 充分利用WebLogic容器進(jìn)行服務(wù)管理,并且集中所有的Bridges資源在一個(gè)線程池;
            • 全面的事務(wù)處理能力,兩階段事務(wù)處理;
            • 全面的JCA 支持;
            • 確保服務(wù)質(zhì)量和連接管理,實(shí)實(shí)在在的一次性服務(wù);
            • 控制臺(tái)監(jiān)視能力;
            • 集成BEA WebLogic應(yīng)用與外部消息提供商,以便將新的應(yīng)用與現(xiàn)有的投資連接起來(lái)。

          創(chuàng)建Server域

            創(chuàng)建Server Domain, domain名稱jms_domain

          修改啟動(dòng)文件

            修改WebLogic的啟動(dòng)文件startWebLogic.cmd。將IBM MQSeries和IBM MQSeries Java的安裝目錄加到WebLogic path下,同時(shí)將MQ JMS Java類包加入到WebLogic classpath下:

          @rem added the following to configure messaging bridge with local MQSeries installation
          set MQ_INSTALL_PATH=D:\installed\MQ
          set MQ_JAVA_INSTALL_PATH=D:\installed\MQ\Java
          set MQ_JAVA_LIB=%MQ_JAVA_INSTALL_PATH%\lib
          set MQ_CLASSPATH=%MQ_JAVA_LIB%\com.ibm.mq.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%\com.ibm.mqbind.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%\com.ibm.mqjms.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%\fscontext.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%\jms.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%\jndi.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%\jta.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%\ldap.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%\providerutil.jar
          
          set MQ_PATH=%MQ_INSTALL_PATH%\in;%MQ_JAVA_INSTALL_PATH%\in;
                 %MQ_JAVA_INSTALL_PATH%\lib
          set PATH=%MQ_PATH%;%PATH%
          set CLASSPATH=%MQ_CLASSPATH%;%WEBLOGIC_CLASSPATH%;
                 %POINTBASE_CLASSPATH%;%JAVA_HOME%\jre\lib\rt.jar;
                %WL_HOME%\server\lib\webservices.jar;%CLASSPATH%
          

          配置JMS

            注意WLS91的連接工廠和隊(duì)列要到JMS Modules下面設(shè)置:

          • 創(chuàng)建文件后備存儲(chǔ)BridgeFileStore
          • 創(chuàng)建JMS服務(wù)器BridgeJMSServer,和Paging Store設(shè)為" BridgeFileStore" ,Target為adminServer
          • 創(chuàng)建支持XA的連接工廠WLSCFXA,JNDI Name為bridge.wlsCFXA
          • 創(chuàng)建JMS發(fā)送隊(duì)列WLSSendQueue,JNDI名稱為bridge.wlsSendQueue,Target為BridgeJMSServer
          • 創(chuàng)建JMS接收隊(duì)列WLSReceiveQueue,JNDI名稱為bridge.wlsReceiveQueue,Target為BridgeJMSServer

          配置Messaging Bridge Destination

          • JMS Bridge Destination名稱為MQReceiveBridgeDestination
            • Adapter JNDI Name: eis.jms.WLSConnectionFactoryJNDIXA
            • Connection URL為file:/D:/installed/MQ/Queues,
            • Initial Context Factory為com.sun.jndi.fscontext.RefFSContextFactory,
            • Connection Factory JNDI Name為bridge.mqQCFXA,
            • Destination JNDI Name為bridge.mqReceiveQueue
            • Destination Type: Queue
          • JMS Bridge Destination名稱為MQSendBridgeDestination
            • Adapter JNDI Name: eis.jms.WLSConnectionFactoryJNDIXA
            • Connection URL為file:/D:/installed/MQ/Queues,
            • Initial Context Factory為com.sun.jndi.fscontext.RefFSContextFactory,
            • Connection Factory JNDI Name為bridge.mqQCFXA,
            • Destination JNDI Name為bridge.mqSendQueue
            • Destination Type: Queue
          • JMS Bridge Destination名稱為WLSReceiveBridgeDestination
            • Adapter JNDI Name: eis.jms.WLSConnectionFactoryJNDIXA
            • Connection URL為t3://localhost:7001,
            • Initial Context Factory為weblogic.jndi.WLInitialContextFactory,
            • Connection Factory JNDI Name為bridge.wlsCFXA,
            • Destination JNDI Name為bridge.wlsReceiveQueue
            • Destination Type: Queue
            • User Name: weblogic(域配置時(shí)指定的)
            • User Password: weblogic(域配置時(shí)指定的)
          • JMS Bridge Destination名稱為WLSSendBridgeDestination
            • Adapter JNDI Name: eis.jms.WLSConnectionFactoryJNDIXA
            • Connection URL為t3://localhost:7001,
            • Initial Context Factory為weblogic.jndi.WLInitialContextFactory,
            • Connection Factory JNDI Name為bridge.wlsCFXA,
            • Destination JNDI Name為bridge.wlsSendQueue,
            • Destination Type: Queue
            • User Name: weblogic(域配置時(shí)指定的)
            • User Password: weblogic(域配置時(shí)指定的)

          配置Messaging Bridge

          • JMS Bridge名稱為MQ2WLSBridge
            • Source Bridge Destination:  MQSendBridgeDestination
            • Target Bridge Destination:  WLSReceiveBridgeDestination
            • Quality Of Service:      Exactly-Once
            • Started:            Yes
          • JMS Bridge名稱為WLS2MQBridge
            • Source Bridge Destination:  WLSSendBridgeDestination
            • Target Bridge Destination:  MQReceiveBridgeDestination
            • Quality Of Service:      Exactly-Once
            • Started:            Yes

          MQ 配置

            IBM MQSeries是IBM的商業(yè)通訊中間件(Commercial Messaging Middleware)。IBM MQSeries提供一個(gè)具有工業(yè)標(biāo)準(zhǔn),安全,可靠的信息傳輸系統(tǒng)。它的功能是控制和管理一個(gè)集成的商業(yè)應(yīng)用,使得組成這個(gè)商業(yè)應(yīng)用的多個(gè)分支程序(模塊)之間通過(guò)傳遞信息完成整個(gè)工作流程。IBM MQSeries具有特殊的技術(shù)防止信息重復(fù)傳送,確保信息一次且僅一次(once-and-only-once)傳遞,保證傳輸?shù)目煽啃浴1疚氖褂玫?MQ版本為IBM MQSeries 5.3。

            IBM MQSeries基本由一個(gè)消息傳輸系統(tǒng)和一個(gè)應(yīng)用程序接口組成,其資源是消息和隊(duì)列(Messaging and Queuing)。

            隊(duì)列管理器(Queue Manager):管理隊(duì)列的系統(tǒng),實(shí)現(xiàn)網(wǎng)絡(luò)通信,保證消息安全可靠地傳輸?shù)侥康牡亍S糜诖_保隊(duì)列之間的信息提供,包括網(wǎng)絡(luò)中不同系統(tǒng)上的的遠(yuǎn)程隊(duì)列之間的信息提供。并保證網(wǎng)絡(luò)故障或關(guān)閉后的恢復(fù)。

            隊(duì)列:一個(gè)安全的信息存儲(chǔ)區(qū)。因?yàn)樾畔⒋娣旁陉?duì)列中,所以應(yīng)用程序可以相互獨(dú)立的運(yùn)行,以不同的速度,在不同的時(shí)間,在不同的地點(diǎn)。

            本地隊(duì)列:對(duì)程序而言,本地隊(duì)列屬于該程序所連接的隊(duì)列管理器。

            遠(yuǎn)程隊(duì)列:該隊(duì)列不屬于該程序所連接的隊(duì)列管理器,而只是遠(yuǎn)端隊(duì)列管理器的隊(duì)列在本地的定義。

            傳輸隊(duì)列:它是一個(gè)本地隊(duì)列,保存了指定要發(fā)送到遠(yuǎn)端的消息。

            死信隊(duì)列:它是一個(gè)本地隊(duì)列,用于存放無(wú)法傳遞的消息。

            通道:在兩個(gè)隊(duì)列管理器之間建立起來(lái)的數(shù)據(jù)傳輸鏈路。

            應(yīng)用程序接口:應(yīng)用程序和信息系統(tǒng)之間通過(guò)MQSeries API實(shí)現(xiàn)的接口。

          Install MQ

          • 安裝過(guò)程中選擇自定義安裝模式,并確保安裝JMS所需的Java jar包支持如下圖:

            (缺省安裝未包含)

          Install MQ

          確認(rèn)MQ服務(wù)已啟動(dòng)。

            可通過(guò)MicroSoft windows控制面板中管理工具下的服務(wù)控制臺(tái)確認(rèn)。如下圖:

          確認(rèn)MQ服務(wù)已啟動(dòng)

          從程序菜單啟動(dòng)MQ 資源管理器

            如果程序提示試用版過(guò)期,可以通過(guò)修改系統(tǒng)時(shí)間搞定.我就是修改到了2004年。

          通過(guò)MQ資源管理器創(chuàng)建一個(gè)通道

            建立名為BRIDGE.CHANNEL的通道,其他參數(shù)缺省設(shè)置。

          通過(guò)MQ資源管理器創(chuàng)建一個(gè)通道

          通過(guò)MQ資源管理器創(chuàng)建兩個(gè)本地隊(duì)列

            建立兩個(gè)本地隊(duì)名為MQReceiveQueue, MQSendQueue,其他參數(shù)缺省設(shè)置。

          通過(guò)MQ資源管理器創(chuàng)建兩個(gè)本地隊(duì)列

          更新MQ安裝目錄下與JMS配置相關(guān)的文件

            JMSAdmin.config文件位于%MQ_INSTALLL_HOME_PATH%\Java\bin,主要定義JNDI服務(wù)的提供商,即JMS Server Factory和URL。%MQ_INSTALLL_HOME_PATH%\Java\bin目錄下新建目錄bridgeconfig,將JMSAdmin.config文件拷貝到bridgeconfig。

            使用Sun的文件JNDI服務(wù)Factory,故定義

            ?

          INITIAL_CONTEXT_FACTORY=com.sun.jndi.fscontext.RefFSContextFactory
          PROVIDER_URL=file:/D:/installed/MQ/Queues
          SECURITY_AUTHENTICATION=none
          (例子中,MQ安裝目錄%MQ_INSTALLL_HOME_PATH%為:D:/installed/MQ/)
          JMSAdmin.bat文件也位于%MQ_INSTALLL_HOME_PATH%\Java\bin,此文件用于啟動(dòng)MQ的JMS命令行管理界面,要設(shè)置啟動(dòng)JMS命令行管理界面所需環(huán)境變量。在JMSAdmin.bat中添加如下環(huán)境變量:
          set MQ_JAVA_INSTALL_PATH=D:\installed\MQ\Java
          set MQ_JAVA_LIB=%MQ_JAVA_INSTALL_PATH%lib
          set MQ_CLASSPATH=%MQ_JAVA_LIB%com.ibm.mq.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%com.ibm.mqbind.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%com.ibm.mqjms.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%fscontext.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%jms.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%jta.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%ldap.jar
          set MQ_CLASSPATH=%MQ_CLASSPATH%;%MQ_JAVA_LIB%providerutil.jar
          

          進(jìn)入MQ的JMS命令行管理界面綁定MQ的JMS Factory以及JMS本地隊(duì)列

          • 開(kāi)啟MicroSoft Windows的Dos窗口(cmd.exe)
          • 進(jìn)入MQ安裝目錄下的java目錄下的bin目錄
          • 運(yùn)行JMSAdmin.bat并通過(guò)-cfg參數(shù)指定JMSAdmin.config文件位置

              本次例子中輸入:D:\ installed\MQ\Java\bin>jmsadmin -cfg? .\bridgeconfig\jmsadmin.config

            進(jìn)入MQ的JMS命令行管理界面綁定MQ的JMS Factory以及JMS本地隊(duì)列

          • 如上圖所示界面,生成一個(gè)MQXAQueueConnectionFactory對(duì)象,Messaging Bridge將使用這個(gè)工廠對(duì)象建立MQ的XA連接,使用命令DEFINE XAQCF,起名:bridge.mqQCFXA。
          • 生成JMSQueue對(duì)象來(lái)綁定MQ隊(duì)列MQReceiveQueue。
          • 生成JMSQueue對(duì)象來(lái)綁定MQ隊(duì)列MQSendQueue。
          • 使用dis ctx命令,查看目前已有的對(duì)象和綁定,可以看到XA連接工廠和隊(duì)列都已綁定。

          測(cè)試

          MQ發(fā)送,WLS接收

          1. MQ發(fā)送隊(duì)列放入測(cè)試消息

            MQ發(fā)送隊(duì)列放入測(cè)試消息

          2. 在WLS控制臺(tái)監(jiān)測(cè)消息到達(dá)

            在WLS控制臺(tái)監(jiān)測(cè)消息到達(dá)

          WLS發(fā)送,MQ接收

          1. WLS發(fā)送隊(duì)列放入測(cè)試消息

              執(zhí)行下面的代碼,給WLS發(fā)送隊(duì)列放入測(cè)試消息

              ?

            package com.bea;
            import javax.naming.InitialContext;
            import javax.naming.Context;
            import javax.naming.NamingException;
            import javax.jms.*;
            import java.util.Hashtable;
            /**
             * Created by IntelliJ IDEA.
             * User: pmeng
             * Date: 2006-6-3
             * Time: 14:54:08
             */
            public class SendMessageTest {
                public static void main(String[] args) {       
                    try {
                        Hashtable env = new Hashtable();
                        env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
                        env.put(Context.PROVIDER_URL, "t3://localhost:7001");
                        InitialContext ctx = new InitialContext(env);              
                        QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("bridge.wlsCFXA");
                        QueueConnection connection = factory.createQueueConnection();
                        QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
                        Queue queue = (Queue) ctx.lookup("bridge.wlsSendQueue");
                        connection.start();
                        QueueSender queueSender = session.createSender(queue);
                        TextMessage msg = session.createTextMessage();
                        msg.setText("Menghe.");
                        queueSender.send(msg);
                    }
                    catch (NamingException e) {
                        System.out.println("NamingException:" + e.getMessage());
                        e.printStackTrace();
                    }
                    catch (JMSException e) {
                        System.out.println("JMSException:" + e.getMessage());
                        e.printStackTrace();
                    }
                }
            }
            
          2. MQ資源管理器查看接收到的消息

            MQ資源管理器查看接收到的消息

          參考資料

          1. BEA WebLogic Server 8.1 JMS與 IBM MQSeries 集成方案,周海根,
            http://dev2dev.bea.com.cn/techdoc/20040411784.html
          2. BEA WebLogic 8.1 JMS 與IBM MQ v5.3 通過(guò)JMS Message Bridge通信配置,陳仁祥
            http://e-docs.bea.com/wls/docs91/messaging.html

          posted @ 2006-09-03 21:55 rednight 閱讀(352) | 評(píng)論 (0)編輯 收藏

          轉(zhuǎn)自http://www.lrsolution.com/docs/MQvsWLJMS.html


          比較IBM MQSeries和BEA WebLogic JMS Server

          劉睿
          2005年7月

          在面向消息的中間件(MOM)這個(gè)領(lǐng)域,IBM MQSeries (又稱WebSphere MQ)一直是當(dāng)仁不讓的超級(jí)大哥,其它還有一些小兄弟,比如SwiftMQSonicMQ之類。但近年來(lái)隨著J2EE中的JMS規(guī)范的建立,完備地支持JMS的服務(wù)器如雨后春筍般地出現(xiàn),比如BEA WebLogic Server的JMS Server就是其中一個(gè)佼佼者。

          僅僅就JMS規(guī)范來(lái)說(shuō),MQSeries與WebLogic JMS沒(méi)有什么不同之處。但JMS規(guī)范僅僅定義了消息服務(wù)器的一個(gè)開(kāi)發(fā)接口,而且還忽略了許多細(xì)節(jié),所以不同之處就在JMS規(guī)范之外的這些內(nèi)容,很多也是非常重要的。總的來(lái)說(shuō),MQSeries的功能和性能方面明顯占優(yōu),而WebLogic JMS的某些JMS配置更加簡(jiǎn)單易行。

          在本文中,我盡量試圖從客觀的角度分析兩種產(chǎn)品的差異,如有不妥之處,請(qǐng)讀者不吝賜教。

          1. 產(chǎn)品體系架構(gòu)不同造成的差異

          WebLogic JMS是一個(gè)純Java實(shí)現(xiàn)的支持C-S架構(gòu)的實(shí)現(xiàn)JMS規(guī)范的服務(wù)器產(chǎn)品;而MQSeries是使用本地語(yǔ)言(比如在UNIX和Windows上的C語(yǔ)言)編寫的既支持C-S架構(gòu),又支持對(duì)等訪問(wèn)的實(shí)現(xiàn)完備MOM(包括JMS規(guī)范)的產(chǎn)品。于是就產(chǎn)生出以下的不同點(diǎn):

          1.1 MQSeries支持真正的異步數(shù)據(jù)傳輸;而WebLogic JMS不支持。

          異步發(fā)送數(shù)據(jù)到遠(yuǎn)端的消息服務(wù)器,是MQSeries等完備的MOM的特色。JMS規(guī)范規(guī)定了一個(gè)C-S架構(gòu),定義了JMS客戶機(jī)與JMS服務(wù)器的開(kāi)發(fā)接口,并沒(méi)有定義JMS服務(wù)器與JMS服務(wù)器的規(guī)范,而客戶機(jī)方面沒(méi)有任何隊(duì)列,所以只能說(shuō)是規(guī)范了消息的存取,而沒(méi)有規(guī)范消息數(shù)據(jù)的傳輸。因?yàn)镴MS客戶機(jī)并不擁有存放數(shù)據(jù)的隊(duì)列,所以所有發(fā)送的操作都要由應(yīng)用程序來(lái)控制,JMS服務(wù)器本身并不代理傳輸,也不保證數(shù)據(jù)在遠(yuǎn)程隊(duì)列間傳輸?shù)目煽啃浴ebLogic JMS就是這樣的體系。

          這種體系結(jié)構(gòu)有時(shí)候是不能直接滿足應(yīng)用的要求的。首先,為了充分利用資源和提高效率,許多應(yīng)用需要采用異步消息的機(jī)制。其次,許多需要快速返回的應(yīng)用也必須使用異步傳輸。比如電話自動(dòng)語(yǔ)音應(yīng)答(IVR)的程序,某個(gè)操作需要把數(shù)據(jù)傳輸?shù)竭h(yuǎn)程的服務(wù)器上,但是必須立即返回,接受客戶的下一個(gè)按鍵。

          MQSeries通過(guò)通道與傳輸隊(duì)列和遠(yuǎn)程隊(duì)列來(lái)完成這一任務(wù)。能充分利用網(wǎng)絡(luò)的帶寬,甚至支持?jǐn)嗑W(wǎng)續(xù)傳,保證數(shù)據(jù)傳輸?shù)目煽啃浴.?dāng)然,雖然應(yīng)用程序不必作任何工作,但配置方面確實(shí)還要多學(xué)一些概念。

          1.2 MQSeries支持多種語(yǔ)言的開(kāi)發(fā);而WebLogic JMS基本上只支持JAVA

          MQSeries支持的語(yǔ)言包括C, C++, COBOL, JAVA, PL/1, REXX, RPG, Visual Basic (使用COM/ActiveX)等。老板本的MQSeries支持JAVA是通過(guò)一個(gè)叫MA88的SupportPac來(lái)實(shí)現(xiàn),雖然經(jīng)過(guò)廣泛的使用和驗(yàn)證,但給人的感覺(jué)是不太方便。好在從5.3版起(目前最新的是6.0版),JAVA支持已經(jīng)內(nèi)置在MQSeries中。

          WebLogic JMS一般只支持JAVA開(kāi)發(fā)。但BEA也在dev2dev.bea.com網(wǎng)站上提供了一套免費(fèi)的C的支持,稱作“JMS C API”。參見(jiàn)http://dev2dev.bea.com/utilitiestools/environment.html?highlight=utilitiestools。但這個(gè)工具與老的MA88也是不能相提并論的,因?yàn)锽EA并不真正支持它,因此也基本沒(méi)有什么用戶。參見(jiàn)BEA網(wǎng)站上關(guān)于“JMS C API”的警告:

          This is *not* a supported product of BEA. However, if you have questions about this API you can post them to weblogic.developer.interest.jms.

          1.3 純JAVA實(shí)現(xiàn)的利與弊

          MQSeries是用本地語(yǔ)言實(shí)現(xiàn)的,因此帶來(lái)的好處是高性能和高并發(fā)的支持能力。MQSeries相對(duì)WebLogic JMS等產(chǎn)品的性能優(yōu)勢(shì)是非常明顯的,所以MQSeries非常適于企業(yè)級(jí)的大數(shù)據(jù)量和高并發(fā)的數(shù)據(jù)傳輸業(yè)務(wù)。誰(shuí)也無(wú)法想象一個(gè)企業(yè)級(jí)的數(shù)據(jù)應(yīng)用會(huì)采用一個(gè)純Java實(shí)現(xiàn)的數(shù)據(jù)庫(kù),因?yàn)槠湫阅軣o(wú)法滿足要求,對(duì)較大的數(shù)據(jù)傳輸應(yīng)用也是一樣的,純Java實(shí)現(xiàn)的JMS服務(wù)器例如WebLogic JMS無(wú)法滿足其性能的要求。

          純JAVA實(shí)現(xiàn)的JMS服務(wù)器也有其好處,就是與其它的J2EE服務(wù)完美地集成在一起。所以WebLogic的JMS配置顯得更簡(jiǎn)潔。WebSphere+MQSeries也配合得很好,但總是能感覺(jué)到是這兩個(gè)產(chǎn)品。WebLogic JMS的對(duì)象體系完全符合JMS的概念體系。而MQSeries要通過(guò)WebSphere Application Server或者一個(gè)叫JMSAdmin的工具,借助于目錄服務(wù)來(lái)完成MQSeries概念體系到JMS概念體系的映射。應(yīng)該是看到了這件事造成的麻煩,所以IBM在WebSphere v6也提供了一套純JAVA實(shí)現(xiàn)的、與MQSeries可以互操作的JMS服務(wù)器。另外一點(diǎn)是WebLogic不需要WebSphere以及MQSeries那樣的冗長(zhǎng)的CLASSPATH等環(huán)境變量的設(shè)置,這點(diǎn)對(duì)開(kāi)發(fā)人員有吸引力。

          1.4 MQSeries的通信功能更加強(qiáng)大,WebLogic JMS也有自己的一些特色

          JMS對(duì)通信功能的要求很少,所以對(duì)二者對(duì)通信支持能力還是有很大的差別的。總的來(lái)說(shuō),歷史更悠久的MQSeries占優(yōu),但WebLogic JMS也有自己的特色。

          • MQSeries支持支持真正的遠(yuǎn)程異步數(shù)據(jù)傳輸,甚至支持消息的路由,可以“多級(jí)跳”;WebLogic JMS不支持。
          • MQSeries支持消息的分組和分段傳輸,對(duì)于大消息傳輸和不穩(wěn)定的網(wǎng)絡(luò)非常有意義。WebLogic JMS沒(méi)有這方面的功能。
          • 二者都支持SSL、持久性、優(yōu)先級(jí)、超時(shí)等功能。除了完備的SSL實(shí)現(xiàn)之外,MQSeries的安全體系 遭到了一些批評(píng),使用通道的安全出口程序顯得很麻煩,而使用用戶名稱但無(wú)須口令保護(hù)的遠(yuǎn)程數(shù)據(jù)通信,如何能令人滿意?但在這一點(diǎn)上WebLogic JMS也很難說(shuō)就好一些,因?yàn)閃ebLogic JMS僅僅支持C-S的操作,系統(tǒng)本身并不支持遠(yuǎn)程的數(shù)據(jù)傳輸(需要應(yīng)用實(shí)現(xiàn))。
          • WebLogic JMS支持IP多播會(huì)話,能顯著地提高 局域網(wǎng)內(nèi)廣播通信的性能,但這種方式不保證數(shù)據(jù)接收的可靠性,只適于某些特定的應(yīng)用。MQSeries本身不提供此功能,但在Event Broker和Message Broker等MQSeries的升級(jí)產(chǎn)品中提供IP多播的支持。

          1.5 MQSeries的管理功能更加強(qiáng)大

          JMS對(duì)管理功能的要求很少,在這方面MQSeries也有比較明顯的優(yōu)勢(shì)。

          • JMS對(duì)事務(wù)處理的支持包括的對(duì)XASession和XAConnection實(shí)現(xiàn),這一點(diǎn)對(duì)MQSeries和WebLogic JMS是相同的。MQSeries本身還可以作為事務(wù)管理器,協(xié)調(diào)兩階段提交。
          • MQSeries和WebLogic JMS都支持Message Driven Bean作為觸發(fā)新的應(yīng)用的一種方式。WebLogic JMS還支持一種稱作Session Pool的類似的觸發(fā)機(jī)制。但這類觸發(fā)機(jī)制過(guò)于簡(jiǎn)化,也就是每個(gè)消息都觸發(fā)一個(gè)新的線程的應(yīng)用。MQSeries的觸發(fā)機(jī)制更豐富,不但包括這種被稱作Every的方式,還包括First和Depth等方式。另外MQSeries還可以觸發(fā)各種執(zhí)行程序或者M(jìn)QSeries的通道。
          • MQSeries擁有一套完備的日志系統(tǒng),可以進(jìn)行獨(dú)立的系統(tǒng)備份和恢復(fù),因此適于高規(guī)格的數(shù)據(jù)/消息傳輸?shù)膽?yīng)用。WebLogic JMS沒(méi)有這方面的支持。

           

          2. 產(chǎn)品歷史的不同造成的差異

          MQSeries是個(gè)歷史悠久的產(chǎn)品,而WebLogic JMS是個(gè)新兵,因此會(huì)有以下的差異:

          2.1 MQSeries支持更多的系統(tǒng)平臺(tái)

          支持30多種系統(tǒng)平臺(tái)。當(dāng)然值得注意的是某些平臺(tái)的MQSeries是由合作伙伴實(shí)現(xiàn)的。

          WebLogic JMS是個(gè)新產(chǎn)品,支持的平臺(tái)數(shù)與WebLogic Server一樣,只有常用的幾個(gè)。有人說(shuō)所有支持JDK的平臺(tái)都能跑WebLogic JMS的客戶機(jī),這是不正確的說(shuō)法。因?yàn)镴MS是J2EE規(guī)范的一種,J2SE的SDK并不包括JMS的支持,更不要說(shuō)支持WebLogic的J2EE了。

          2.2 MQSeries支持更多的 通信協(xié)議

          MQSeries支持很多通信協(xié)議,但目前在實(shí)踐中常用的是TCP/IP協(xié)議和SNA協(xié)議。

          WebLogic JMS僅支持TCP/IP協(xié)議。

          有些人對(duì)MQSeries的單向通道的概念提出了異議,認(rèn)為增加了配置的復(fù)雜性,僅僅是SNA協(xié)議的需要,而不是TCP/IP協(xié)議的需要。我個(gè)人認(rèn)為這點(diǎn)也不無(wú)一些道理。但是在有防火墻的TCP/IP網(wǎng)絡(luò)上,不同的方向還是有差異的。

           

          3. 群集實(shí)現(xiàn)的差異

          MQSeries與WebLogic JMS在支持群集時(shí),差異比較大,應(yīng)該說(shuō)各有各的特點(diǎn)。

          • MQSeries的群集建立在配置庫(kù)和群集通道基礎(chǔ)之上,可以定義“共享隊(duì)列”;WebLogic JMS的群集建立在WebLogic群集基礎(chǔ)之上,可以定義“分布式隊(duì)列”。
          • MQSeries在寫共享隊(duì)列時(shí),如果發(fā)現(xiàn)本地有,就只寫本地的隊(duì)列(這稱作本地優(yōu)先);如果本地沒(méi)有,就會(huì)輪流寫到所有定義了此共享隊(duì)列的隊(duì)列管理器。MQSeries在讀共享隊(duì)列時(shí),只能從本地取。WebLogic JMS在讀寫分布式隊(duì)列時(shí),不受本地影響,總是進(jìn)行輪流或權(quán)重選擇。聽(tīng)起來(lái)似乎WebLogic JMS的群集更靈活,其實(shí)也不盡然。當(dāng)取得了JMS的對(duì)象QueueSender或QueueReceiver后,WebLogic實(shí)際上已經(jīng)綁定了一個(gè)JMS服務(wù)器的實(shí)例。如果每次寫或讀一個(gè)消息,都重新生成QueueSender或QueueReceiver,雖然比較好地支持了負(fù)載均衡,但勢(shì)必造成很大的性能損失。而MQSeries在輪流寫共享隊(duì)列時(shí),沒(méi)有這方面的問(wèn)題。
          • WebLogic JMS的分布式隊(duì)列有一個(gè)叫做Forward Delay的有意思的屬性,定義了一個(gè)時(shí)間的長(zhǎng)度。系統(tǒng)一旦發(fā)現(xiàn)超過(guò)這個(gè)時(shí)間長(zhǎng)度,還沒(méi)有人讀這個(gè)隊(duì)列,就把它的消息轉(zhuǎn)送給群集中有消費(fèi)者的隊(duì)列。有了這個(gè)屬性,應(yīng)用程序就可以只從一個(gè)JMS服務(wù)器的實(shí)例讀消息了。

          posted @ 2006-09-03 21:53 rednight 閱讀(242) | 評(píng)論 (0)編輯 收藏

          項(xiàng)目中需要使用IloSolver,但沒(méi)人懂,網(wǎng)上資料太少了,不知道誰(shuí)有這方面的資料給發(fā)一份,謝謝了!

          rcashellster@gmail.com

          posted @ 2006-08-31 12:22 rednight 閱讀(330) | 評(píng)論 (0)編輯 收藏

          有兩類線程:用戶線程和守護(hù)線程。用戶線程是那些完成有用工作的線程。 守護(hù)線程是那些僅提供輔助功能的線程。Thread 類提供了 setDaemon() 函數(shù)。Java 程序?qū)⑦\(yùn)行到所有用戶線程終止,然后它將破壞所有的守護(hù)線程。在 Java 虛擬機(jī) (JVM) 中,即使在 main 結(jié)束以后,如果另一個(gè)用戶線程仍在運(yùn)行,則程序仍然可以繼續(xù)運(yùn)行。

          posted @ 2006-08-28 20:21 rednight| 編輯 收藏

          主站蜘蛛池模板: 澳门| 奉节县| 德安县| 客服| 霞浦县| 阜新市| 依安县| 阳信县| 鹤山市| 浦县| 临桂县| 天峻县| 水富县| 盐源县| 梓潼县| 营山县| 东光县| 合阳县| 崇信县| 麻栗坡县| 马山县| 石城县| 阿图什市| 石棉县| 明水县| 罗平县| 长宁区| 内江市| 甘孜| 铜陵市| 紫云| 海城市| 聂拉木县| 黑龙江省| 仁怀市| 盐边县| 雷波县| 壤塘县| 万州区| 小金县| 津市市|