From ffa70727e33eeb8922a667e560bad0619758c08a Mon Sep 17 00:00:00 2001 From: Roman Smolgovsky Date: Mon, 14 Mar 2016 18:05:46 -0700 Subject: [PATCH 1/9] Update KaazingAMQPClientLibrariesFacade.md --- .../KaazingAMQPClientLibrariesFacade.md | 111 ++++++++++-------- 1 file changed, 64 insertions(+), 47 deletions(-) diff --git a/javascript/KaazingAMQPClientLibrariesFacade.md b/javascript/KaazingAMQPClientLibrariesFacade.md index ecc807a..909036e 100644 --- a/javascript/KaazingAMQPClientLibrariesFacade.md +++ b/javascript/KaazingAMQPClientLibrariesFacade.md @@ -1,4 +1,6 @@ # Kaazing JavaScript AMQP Client Libraries Facade +Kaazing JavaScript AMQP Client Libraries Facade simplifies the interaction with Kaazing JavaScript AMQP Client libraries that enable the developers to interact with [AMQP 0-9-1](https://www.rabbitmq.com/tutorials/amqp-concepts.html) brokers via WebSockets. + Kaazing AMQP Client Libraries Facade: • Implements basic publish-subscribe functionality for AMQP protocol to help developers in getting started with their AMQP WebSocket projects • Provide developers with the reference implementations for using Kaazing AMQP JavaScript client libraries @@ -9,16 +11,16 @@ For more information see: ## Organization of the library Library consists of amqpClientFunction that creates AmqpClient object. AmqpClient objects provides the following functionality: - **connect** function - connects client to Kaazing WebSocket AMQP gateway and on success returns via callback a _connection_ object that will be used to create subscriptions. -- ** subscribe ** method of a _connecion_ object that creates publishing endpoint and subscribes to a subscription endpoint. Method returns _subscription_ object that is used for sending messages. +- ** subscribe ** method of a _connection_ object that creates publishing endpoint and subscribes to a subscription endpoint. Method returns via callback a _subscription_ object that is used for sending messages. - **sendMessage** method of a _subscription_ object - sends the message to a publishing endpoint -- **close** function of a _subscription_ object - closes both publishing and subscription. -- **disconnect** method - closes all subscriptions and disconnects client from Kaazing WebSocket AMQP gateway +- **disconnect** function of a _subscription_ object - closes both publishing and subscription. +- **close** method - closes all subscriptions and disconnects client from Kaazing WebSocket AMQP gateway ### **connect** function Connect function implements the following sequence: -1. Create WebSocket and AMQP client factories +- Create WebSocket and AMQP client factories ```javascript var amqpClientFactory = new AmqpClientFactory(); @@ -29,13 +31,13 @@ Connect function implements the following sequence: } ``` -2. Create AMQP client +- Create AMQP client ```javascript amqpClient = amqpClientFactory.createAmqpClient(); ``` -3. Connect to Gateway using amqpClient connect function. Connect function uses has the following parameters: +- Connect to Gateway using amqpClient connect function. Connect function uses has the following parameters: - Connection options. In most common cases it contains of URL, credentials and virtual host (set to ‘/‘) hat specifies the namespace for entities (exchanges and queues) referred to by the protocol. Note that this is not virtual hosting in the HTTP sense. - Callback function that will be called once connection is established. @@ -53,52 +55,51 @@ Connect function implements the following sequence: ``` ### **subscribe** method of connection object -1. Creates subscription object -2. Initializes subscription object - - Opens publishing and consumption (subscription) channels using amqpClient openChannel function that will call on success the callback function that is passed as a parameter: +- Creates and initializes subscription object +- Opens publishing and consumption (subscription) channels using amqpClient openChannel function that will call on success the callback function that is passed as a parameter: - ```javascript - var openHandler=function(){ - publishChannel = amqpClient.openChannel(this.publishChannelOpenHandler); - consumeChannel = amqpClient.openChannel(this.consumeChannelOpenHandler); - } - ``` + ```javascript + var openHandler=function(){ + publishChannel = amqpClient.openChannel(this.publishChannelOpenHandler); + consumeChannel = amqpClient.openChannel(this.consumeChannelOpenHandler); + } + ``` Once the channels are created method returns the _subscription_ object via a callback. During the creation of the channels: - - Publishing channel open handler declares AMQP Exchange of a _fanout_ type thus creating publishing endpoint. +- Publishing channel open handler declares AMQP Exchange of a _fanout_ type thus creating publishing endpoint. - ```javascript - publishChannelOpenHandler:function(that){ - that.publishChannel.declareExchange({exchange: that.topicPub, type: "fanout"}); - } - ``` - - Consumption (or subscription) channel open handler: - 1. Adds an event listener for “message” event providing the ability to receive messages. - 2. Declares subscription queue for the client. Library randomly generates the name for every client. - 3. Binds the queue to a subscription exchange with “broadcastkey” routing key. + ```javascript + publishChannelOpenHandler:function(that){ + that.publishChannel.declareExchange({exchange: that.topicPub, type: "fanout"}); + } + ``` +- Consumption (or subscription) channel open handler: + 1. Adds an event listener for “message” event providing the ability to receive messages. + 2. Declares subscription queue for the client. Library randomly generates the name for every client. + 3. Binds the queue to a subscription exchange with “broadcastkey” routing key. - **Note** For fanout exchanges routing key is not used. For more information about exchanges and routing keys see: [https://www.rabbitmq.com/tutorials/amqp-concepts.html][1] + **Note** For fanout exchanges routing key is not used. For more information about exchanges and routing keys see: [https://www.rabbitmq.com/tutorials/amqp-concepts.html][1] - 4. Starts basic consumer. Basic consumer is started with noAck=true parameter so the client does not need to implement explicit acknowledgement. Another parameter - noLocal - controls whether the client wants to receive its own messages. + 4. Starts basic consumer. Basic consumer is started with noAck=true parameter so the client does not need to implement explicit acknowledgement. Another parameter - noLocal - controls whether the client wants to receive its own messages. - ```javascript - consumeChannelOpenHandler:function(that{ - consumeChannel.addEventListener("message", function(message) { - var body = null; - // Check how the payload was packaged since older browsers like IE7 don't - // support ArrayBuffer. In those cases, a Kaazing ByteBuffer was used instead. - if (typeof(ArrayBuffer) === "undefined") { - body = message.getBodyAsByteBuffer().getString(Charset.UTF8); - } - else { - body = arrayBufferToString(message.getBodyAsArrayBuffer()) - } - that.messageReceivedFunc(body);; + ```javascript + consumeChannelOpenHandler:function(that{ + consumeChannel.addEventListener("message", function(message) { + var body = null; + // Check how the payload was packaged since older browsers like IE7 don't + // support ArrayBuffer. In those cases, a Kaazing ByteBuffer was used instead. + if (typeof(ArrayBuffer) === "undefined") { + body = message.getBodyAsByteBuffer().getString(Charset.UTF8); + } + else { + body = arrayBufferToString(message.getBodyAsArrayBuffer()); + } + that.messageReceivedFunc(body); }); - that.consumeChannel.declareQueue({queue: that.queueName}) - .bindQueue({queue: that.queueName, exchange: that.topicSub, routingKey: routingKey }) - .consumeBasic({queue: that.queueName, consumerTag: that.clientId, noAck: true, noLocal:that.noLocal }) + that.consumeChannel.declareQueue({queue: that.queueName}) + .bindQueue({queue: that.queueName, exchange: that.topicSub, routingKey: routingKey }) + .consumeBasic({queue: that.queueName, consumerTag: that.clientId, noAck: true, noLocal:that.noLocal }) } ``` @@ -138,13 +139,29 @@ sendMessage:function(msg){ } ``` -### **close** function of a subscription object -Due to AMQP nature, nothing has to be performed. +### **disconnect** function of a subscription object +Deletes declared subscription queue and closes the channels: +```javascript + ... + var config = { + replyCode: 0, + replyText, '', + classId: 0, + methodId: 0 + }; + this.consumeChannel.deleteQueue({queue:this.queueName, ifEmpty: false}, function(){ + this.consumeChannel.closeChannel(config, function(){ + this.publishChannel.closeChannel(config, function(){ + + }); + }); + }); +``` -### **disconnect** function +### **close** function Disconnects the client from Kaazing WebSocket AMQP Gateway ```javascript -amqpClient.disconnect(); + amqpClient.disconnect(); ``` From cb98fdd6131764a1ea36f602367a32d18b618ad9 Mon Sep 17 00:00:00 2001 From: Roman Smolgovsky Date: Mon, 14 Mar 2016 18:08:51 -0700 Subject: [PATCH 2/9] Update KaazingAMQPClientLibrariesFacade.md --- .../KaazingAMQPClientLibrariesFacade.md | 59 ++++++++++--------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/javascript/KaazingAMQPClientLibrariesFacade.md b/javascript/KaazingAMQPClientLibrariesFacade.md index 909036e..ef511cf 100644 --- a/javascript/KaazingAMQPClientLibrariesFacade.md +++ b/javascript/KaazingAMQPClientLibrariesFacade.md @@ -22,26 +22,26 @@ Connect function implements the following sequence: - Create WebSocket and AMQP client factories - ```javascript +```javascript var amqpClientFactory = new AmqpClientFactory(); var webSocketFactory; if ($gatewayModule && typeof($gatewayModule.WebSocketFactory) === "function") { webSocketFactory = createWebSocketFactory(); amqpClientFactory.setWebSocketFactory(webSocketFactory); } - ``` +``` - Create AMQP client - ```javascript +```javascript amqpClient = amqpClientFactory.createAmqpClient(); - ``` +``` - Connect to Gateway using amqpClient connect function. Connect function uses has the following parameters: - Connection options. In most common cases it contains of URL, credentials and virtual host (set to ‘/‘) hat specifies the namespace for entities (exchanges and queues) referred to by the protocol. Note that this is not virtual hosting in the HTTP sense. - Callback function that will be called once connection is established. - ```javascript +```javascript var credentials = {username: username, password: password}; var options = { url: url, @@ -52,28 +52,29 @@ Connect function implements the following sequence: var connection=createConnectionObject(amqpClient,connectionInfo.username); connectedFunctionHandle(connection); }); - ``` +``` ### **subscribe** method of connection object - Creates and initializes subscription object - Opens publishing and consumption (subscription) channels using amqpClient openChannel function that will call on success the callback function that is passed as a parameter: - ```javascript +```javascript var openHandler=function(){ publishChannel = amqpClient.openChannel(this.publishChannelOpenHandler); consumeChannel = amqpClient.openChannel(this.consumeChannelOpenHandler); } - ``` +``` Once the channels are created method returns the _subscription_ object via a callback. During the creation of the channels: - Publishing channel open handler declares AMQP Exchange of a _fanout_ type thus creating publishing endpoint. - ```javascript +```javascript publishChannelOpenHandler:function(that){ - that.publishChannel.declareExchange({exchange: that.topicPub, type: "fanout"}); - } - ``` + that.publishChannel.declareExchange({exchange: that.topicPub, type: "fanout"}); + } +``` + - Consumption (or subscription) channel open handler: 1. Adds an event listener for “message” event providing the ability to receive messages. 2. Declares subscription queue for the client. Library randomly generates the name for every client. @@ -83,25 +84,25 @@ Connect function implements the following sequence: 4. Starts basic consumer. Basic consumer is started with noAck=true parameter so the client does not need to implement explicit acknowledgement. Another parameter - noLocal - controls whether the client wants to receive its own messages. - ```javascript - consumeChannelOpenHandler:function(that{ - consumeChannel.addEventListener("message", function(message) { - var body = null; - // Check how the payload was packaged since older browsers like IE7 don't - // support ArrayBuffer. In those cases, a Kaazing ByteBuffer was used instead. - if (typeof(ArrayBuffer) === "undefined") { - body = message.getBodyAsByteBuffer().getString(Charset.UTF8); - } - else { - body = arrayBufferToString(message.getBodyAsArrayBuffer()); - } - that.messageReceivedFunc(body); - }); - that.consumeChannel.declareQueue({queue: that.queueName}) +```javascript + consumeChannelOpenHandler:function(that{ + consumeChannel.addEventListener("message", function(message) { + var body = null; + // Check how the payload was packaged since older browsers like IE7 don't + // support ArrayBuffer. In those cases, a Kaazing ByteBuffer was used instead. + if (typeof(ArrayBuffer) === "undefined") { + body = message.getBodyAsByteBuffer().getString(Charset.UTF8); + } + else { + body = arrayBufferToString(message.getBodyAsArrayBuffer()); + } + that.messageReceivedFunc(body); + }); + that.consumeChannel.declareQueue({queue: that.queueName}) .bindQueue({queue: that.queueName, exchange: that.topicSub, routingKey: routingKey }) .consumeBasic({queue: that.queueName, consumerTag: that.clientId, noAck: true, noLocal:that.noLocal }) - } - ``` + } +``` ### **sendMessage** function of a subscription object Function sets AMQP properties and sends the message to a publishing exchange using specified routing key. From 1f9e1e49a9700717fd90e37a375e48ac578b29a9 Mon Sep 17 00:00:00 2001 From: Roman Smolgovsky Date: Mon, 14 Mar 2016 18:09:41 -0700 Subject: [PATCH 3/9] Update KaazingAMQPClientLibrariesFacade.md --- javascript/KaazingAMQPClientLibrariesFacade.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/KaazingAMQPClientLibrariesFacade.md b/javascript/KaazingAMQPClientLibrariesFacade.md index ef511cf..75ae381 100644 --- a/javascript/KaazingAMQPClientLibrariesFacade.md +++ b/javascript/KaazingAMQPClientLibrariesFacade.md @@ -109,7 +109,7 @@ Function sets AMQP properties and sends the message to a publishing exchange usi **Note:** As mentioned earlier, library creates a fanout type of exchange that does not use routing keys; thus library sets the value of the routing key to 'broadcast'. ```javascript -sendMessage:function(msg){ + sendMessage:function(msg){ if (typeof msg ==="object"){ msg.clientId=this.clientId; msg=JSON.stringify(msg); @@ -137,7 +137,7 @@ sendMessage:function(msg){ props.setUserId(this.user); logInformation("sent","Sending message to "+this.topicPub+": "+ msg, "sent"); this.publishChannel.publishBasic({body: body, properties: props, exchange: this.topicPub, routingKey: routingKey}); - } + } ``` ### **disconnect** function of a subscription object From cf1957bd8f469fc9264e27276ec0e1a09dc8c38f Mon Sep 17 00:00:00 2001 From: Roman Smolgovsky Date: Mon, 14 Mar 2016 18:15:06 -0700 Subject: [PATCH 4/9] Synchronized with the local repository. --- java/KaazingAMQPClientLibrariesFacade.md | 245 ++++++++ java/KaazingJMSClientLibrariesFacade.md | 253 ++++++++ java/README.md | 122 ++++ java/doc/allclasses-frame.html | 35 ++ java/doc/allclasses-noframe.html | 35 ++ .../universal/AmqpClientSubscription.html | 335 ++++++++++ .../client/universal/AmqpMessageEnvelope.html | 313 ++++++++++ .../client/universal/AmqpUniversalClient.html | 334 ++++++++++ .../AmqpUniversalClientTest.TestObject.html | 288 +++++++++ .../universal/AmqpUniversalClientTest.html | 377 ++++++++++++ .../client/universal/ClientException.html | 289 +++++++++ .../client/universal/ClientSubscription.html | 329 ++++++++++ .../client/universal/ErrorsListener.html | 231 +++++++ .../universal/JMSClientSubscription.html | 331 ++++++++++ .../client/universal/JMSUniversalClient.html | 351 +++++++++++ .../JMSUniversalClientTest.TestObject.html | 288 +++++++++ .../universal/JMSUniversalClientTest.html | 377 ++++++++++++ .../client/universal/MessagesListener.html | 231 +++++++ .../universal/SubscriptionConnection.html | 331 ++++++++++ .../client/universal/UniversalClient.html | 261 ++++++++ .../universal/UniversalClientFactory.html | 264 ++++++++ .../universal/UniversalClientProtocol.html | 339 +++++++++++ .../com/kaazing/client/universal/Utils.html | 330 ++++++++++ .../class-use/AmqpClientSubscription.html | 122 ++++ .../class-use/AmqpMessageEnvelope.html | 122 ++++ .../class-use/AmqpUniversalClient.html | 122 ++++ .../AmqpUniversalClientTest.TestObject.html | 122 ++++ .../class-use/AmqpUniversalClientTest.html | 122 ++++ .../universal/class-use/ClientException.html | 271 +++++++++ .../class-use/ClientSubscription.html | 187 ++++++ .../universal/class-use/ErrorsListener.html | 173 ++++++ .../class-use/JMSClientSubscription.html | 122 ++++ .../class-use/JMSUniversalClient.html | 122 ++++ .../JMSUniversalClientTest.TestObject.html | 122 ++++ .../class-use/JMSUniversalClientTest.html | 122 ++++ .../universal/class-use/MessagesListener.html | 166 +++++ .../class-use/SubscriptionConnection.html | 122 ++++ .../universal/class-use/UniversalClient.html | 174 ++++++ .../class-use/UniversalClientFactory.html | 122 ++++ .../class-use/UniversalClientProtocol.html | 175 ++++++ .../client/universal/class-use/Utils.html | 122 ++++ .../client/universal/package-frame.html | 45 ++ .../client/universal/package-summary.html | 261 ++++++++ .../client/universal/package-tree.html | 176 ++++++ .../kaazing/client/universal/package-use.html | 165 +++++ java/doc/constant-values.html | 122 ++++ java/doc/deprecated-list.html | 122 ++++ java/doc/help-doc.html | 223 +++++++ java/doc/index-files/index-1.html | 149 +++++ java/doc/index-files/index-10.html | 147 +++++ java/doc/index-files/index-11.html | 141 +++++ java/doc/index-files/index-12.html | 134 ++++ java/doc/index-files/index-2.html | 153 +++++ java/doc/index-files/index-3.html | 137 +++++ java/doc/index-files/index-4.html | 129 ++++ java/doc/index-files/index-5.html | 133 ++++ java/doc/index-files/index-6.html | 143 +++++ java/doc/index-files/index-7.html | 129 ++++ java/doc/index-files/index-8.html | 135 ++++ java/doc/index-files/index-9.html | 153 +++++ java/doc/index.html | 71 +++ java/doc/overview-tree.html | 180 ++++++ java/doc/package-list | 1 + java/doc/script.js | 30 + java/doc/serialized-form.html | 211 +++++++ java/doc/stylesheet.css | 574 ++++++++++++++++++ java/images/JavaUniversalClient.png | Bin 0 -> 89843 bytes .../universal/AmqpClientSubscription.java | 8 +- .../client/universal/AmqpUniversalClient.java | 11 +- .../client/universal/ClientSubscription.java | 20 +- ...ection.java => JMSClientSubscription.java} | 22 +- .../client/universal/JMSUniversalClient.java | 10 +- .../client/universal/UniversalClient.java | 4 +- .../universal/AmqpUniversalClientTest.java | 6 +- .../universal/JMSUniversalClientTest.java | 6 +- javascript/JavaScriptClient.md | 218 +++---- javascript/KaazingJMSClientLibrariesFacade.md | 39 +- javascript/README.md | 17 +- javascript/src/AmqpUniversalClient.js | 17 +- javascript/src/JMSUniversalClient.js | 10 +- javascript/src/package.json | 2 +- 81 files changed, 12932 insertions(+), 221 deletions(-) create mode 100644 java/KaazingAMQPClientLibrariesFacade.md create mode 100644 java/KaazingJMSClientLibrariesFacade.md create mode 100644 java/README.md create mode 100644 java/doc/allclasses-frame.html create mode 100644 java/doc/allclasses-noframe.html create mode 100644 java/doc/com/kaazing/client/universal/AmqpClientSubscription.html create mode 100644 java/doc/com/kaazing/client/universal/AmqpMessageEnvelope.html create mode 100644 java/doc/com/kaazing/client/universal/AmqpUniversalClient.html create mode 100644 java/doc/com/kaazing/client/universal/AmqpUniversalClientTest.TestObject.html create mode 100644 java/doc/com/kaazing/client/universal/AmqpUniversalClientTest.html create mode 100644 java/doc/com/kaazing/client/universal/ClientException.html create mode 100644 java/doc/com/kaazing/client/universal/ClientSubscription.html create mode 100644 java/doc/com/kaazing/client/universal/ErrorsListener.html create mode 100644 java/doc/com/kaazing/client/universal/JMSClientSubscription.html create mode 100644 java/doc/com/kaazing/client/universal/JMSUniversalClient.html create mode 100644 java/doc/com/kaazing/client/universal/JMSUniversalClientTest.TestObject.html create mode 100644 java/doc/com/kaazing/client/universal/JMSUniversalClientTest.html create mode 100644 java/doc/com/kaazing/client/universal/MessagesListener.html create mode 100644 java/doc/com/kaazing/client/universal/SubscriptionConnection.html create mode 100644 java/doc/com/kaazing/client/universal/UniversalClient.html create mode 100644 java/doc/com/kaazing/client/universal/UniversalClientFactory.html create mode 100644 java/doc/com/kaazing/client/universal/UniversalClientProtocol.html create mode 100644 java/doc/com/kaazing/client/universal/Utils.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/AmqpClientSubscription.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/AmqpMessageEnvelope.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/AmqpUniversalClient.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/AmqpUniversalClientTest.TestObject.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/AmqpUniversalClientTest.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/ClientException.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/ClientSubscription.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/ErrorsListener.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/JMSClientSubscription.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/JMSUniversalClient.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/JMSUniversalClientTest.TestObject.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/JMSUniversalClientTest.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/MessagesListener.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/SubscriptionConnection.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/UniversalClient.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/UniversalClientFactory.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/UniversalClientProtocol.html create mode 100644 java/doc/com/kaazing/client/universal/class-use/Utils.html create mode 100644 java/doc/com/kaazing/client/universal/package-frame.html create mode 100644 java/doc/com/kaazing/client/universal/package-summary.html create mode 100644 java/doc/com/kaazing/client/universal/package-tree.html create mode 100644 java/doc/com/kaazing/client/universal/package-use.html create mode 100644 java/doc/constant-values.html create mode 100644 java/doc/deprecated-list.html create mode 100644 java/doc/help-doc.html create mode 100644 java/doc/index-files/index-1.html create mode 100644 java/doc/index-files/index-10.html create mode 100644 java/doc/index-files/index-11.html create mode 100644 java/doc/index-files/index-12.html create mode 100644 java/doc/index-files/index-2.html create mode 100644 java/doc/index-files/index-3.html create mode 100644 java/doc/index-files/index-4.html create mode 100644 java/doc/index-files/index-5.html create mode 100644 java/doc/index-files/index-6.html create mode 100644 java/doc/index-files/index-7.html create mode 100644 java/doc/index-files/index-8.html create mode 100644 java/doc/index-files/index-9.html create mode 100644 java/doc/index.html create mode 100644 java/doc/overview-tree.html create mode 100644 java/doc/package-list create mode 100644 java/doc/script.js create mode 100644 java/doc/serialized-form.html create mode 100644 java/doc/stylesheet.css create mode 100644 java/images/JavaUniversalClient.png rename java/src/main/java/com/kaazing/client/universal/{SubscriptionConnection.java => JMSClientSubscription.java} (52%) diff --git a/java/KaazingAMQPClientLibrariesFacade.md b/java/KaazingAMQPClientLibrariesFacade.md new file mode 100644 index 0000000..9ed218d --- /dev/null +++ b/java/KaazingAMQPClientLibrariesFacade.md @@ -0,0 +1,245 @@ +# Kaazing Java AMQP Client Libraries Facade +Kaazing Java AMQP Client Libraries Facade simplifies the interaction with Kaazing Java AMQP Client libraries that enable the developers to interact with [AMQP 0-9-1](https://www.rabbitmq.com/tutorials/amqp-concepts.html) brokers via WebSockets. + +Kaazing Java AMQP Client Libraries Facade: +* Implements basic publish-subscribe functionality for AMQP to help developers in getting started with their AMQP WebSocket projects +* Provide developers with the reference implementations for using Kaazing AMQP Java client libraries + +For more information see: +- [Build Java AMQP Clients Using Kaazing WebSocket Gateway](http://kaazing.com/doc/amqp/4.0/dev-java/o_dev_java.html) +- [Use the Kaazing WebSocket Gateway Java AMQP Client API](http://kaazing.com/doc/amqp/4.0/dev-java/p_dev_java_client.html) + +## Organization of the library +UniversalClientFactory's create +Library contains AmqpUniversalClient class (implementing UniversalClient interface) that is created by UniversalClientFactory's _createUniversalClient_ method. AmqpUniversalClient object provides the following functionality: +- **constructor** of AmqpUniversalClient - connects client to Kaazing WebSocket AMQP gateway +- **subscribe** method of AmqpUniversalClient - subscribes to publishing and subscription endpoints and returns an instance of ClientSubscription object. +- **sendMessage** method of ClientSubscription - sends the instances of Serialized Objects to the publishing endpoint +- **disconnect** method of ClientSubscription - closes subscription to publishing and subscription endpoints for this subscription +- **close** method of AmqpUniversalClient - closes all subscriptions and connections + + +### **constructor** of AmqpUniversalClient +Connect function implements the following sequence: + +- Create AMQP client factory and AMQP client + + ```java + amqpClientFactory = AmqpClientFactory.createAmqpClientFactory(); + amqpClient = amqpClientFactory.createAmqpClient(); + ``` +- Register connection listeners + ```java + ... + amqpClient.addConnectionListener(new ConnectionListener() { + + @Override + public void onConnectionOpen(ConnectionEvent e) { + LOGGER.info("Connected to "+url+" message "+e.getMessage()); + fConnected = true; + latch.countDown(); + } + + @Override + public void onConnectionError(ConnectionEvent e) { + LOGGER.error("Connection error to url "+url+"... "+e.getMessage()); + errorsListener.onException(new ClientException("Error connecting to " + url + ": " + e.getMessage())); + latch.countDown(); + } + + @Override + public void onConnectionClose(ConnectionEvent e) { + for (AmqpClientSubscription conn : connections) { + try { + conn.disconnect(); + } catch (ClientException e1) { + errorsListener.onException(new ClientException("Error closing client connection: "+conn.getSubscriptionIdentifier(), e1)); + LOGGER.error("Error closing client connection: "+conn.getSubscriptionIdentifier(), e1); + } + } + LOGGER.info("Closed connection to "+url+"."); + } + + @Override + public void onConnecting(ConnectionEvent e) { + + + } + }); + ``` + We use onConnectionOpen and onConnectionError listeners to wait until connection is either established or failed; we use the countdown latch to wait for either of these events. +- Establish connection using provided login and password + ```java + amqpClient.connect(this.url, "/", login, password); + try { + latch.await(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new ClientException("Exception wating for connection latch connecting to " + this.url, e); + } + if (!fConnected) { + throw new ClientException("Connection to " + this.url + " was not established in 10 sec."); + } + ``` + +### **subscribe** method of of AmqpUniversalClient object +Method executed the following actions: +- Opens publishing channel +```java + AmqpChannel pubChannel = this.amqpClient.openChannel(); +``` +- Adds publishing channel listeners +```java + ... + pubChannel.addChannelListener(new ChannelAdapter() { + @Override + public void onClose(ChannelEvent e) { + + } + + @Override + public void onError(final ChannelEvent e) { + errorsListener.onException(new ClientException("Error creating publishing channel for " + pubTopicName + ": " + e.getMessage())); + LOGGER.error("Error creating publishing channel "+pubTopicName+" for connection to "+url+": "+e.getMessage()); + connectionsLatch.countDown(); + } + + @Override + public void onDeclareExchange(ChannelEvent e) { + LOGGER.info("Created channel "+pubTopicName+" for url "+url); + fPubOpened = true; + connectionsLatch.countDown(); + } + + @Override + public void onOpen(ChannelEvent e) { + pubChannel.declareExchange(pubTopicName, "fanout", false, false, false, null); + } + }); + ... +``` + Opening the channel will trigger _onOpen_ event listener where we declare an exchange. Successful declaring of an exchange will result in triggering of onDeclareExchange event listener and is an indication of a success; onError listener is triggered in an event of any error. We use the countdown latch to wait for either of these events. +- Opens subscription channel +```java + ... + AmqpChannel subChannel = this.amqpClient.openChannel(); +``` +- Registers subscription channel events listeners: +```java + subChannel.addChannelListener(new ChannelAdapter() { + @Override + public void onError(final ChannelEvent e) { + errorsListener.onException(new ClientException("Error creating subscription channel " + subTopicName + ": " + e.getMessage())); + LOGGER.error("Error creating subscription channel "+subTopicName+" for url "+url+": "+e.getMessage()); + connectionsLatch.countDown(); + } + + @Override + public void onConsumeBasic(ChannelEvent e) { + LOGGER.info("Created subscription channel "+subTopicName+" for url "+url); + fSubOpened = true; + connectionsLatch.countDown(); + } + + @Override + public void onMessage(final ChannelEvent e) { + ... + + } + + @Override + public void onOpen(ChannelEvent e) { + subChannel.declareQueue(queueName, false, false, false, false, false, null) + .bindQueue(queueName, subTopicName, ROUTING_KEY, false, null) + .consumeBasic(queueName, clientId, noLocal, false, false, false, null); + } + }); +``` + Once the channel is successfully opened, onOpen event listener will be call where we: + - declare a new queue + - bind the queue to an exchange with 'broadcast' routing key + - start basic consumer for the queue. + **Note** For fanout exchanges routing key is not used. For more information about exchanges and routing keys see: [https://www.rabbitmq.com/tutorials/amqp-concepts.html](https://www.rabbitmq.com/tutorials/amqp-concepts.html). + + Once consumer is started, onConsumeBasic event listener is called which is an indication that channel is successfully opened. onError listener is triggered in an event of any error. We use the countdown latch to wait for either of these events. + onMessage event listener is called every time we will receive a message from an exchange. In this method we: + - Allocates the buffer and read the data from the event body that contains serialized object. + - Deserialize the object and make sure it an instance of our AmqpMessageEnvelope. The reason to use an envelope it contains application identifier that is used for messages filtering for the AMQP brokers that do not support noLocal functionality (functionality that prevents the client to received its own messages when publishing and subscription endpoints are the same). + - calls onMessage method of MessagesListener object passing it received object. +```java + byte[] bytes = new byte[e.getBody().remaining()]; + e.getBody().get(bytes); + try { + Serializable object=Utils.deserialize(bytes); + if (!(object instanceof AmqpMessageEnvelope)){ + errorsListener.onException(new ClientException("Received object is not an instance of AmqpMessageEnvelope; received from " + subTopicName)); + LOGGER.error("Received object is not an instance of AmqpMessageEnvelope; received from " + subTopicName +" for url"+url); + return; + } + AmqpMessageEnvelope messageEnvelope=(AmqpMessageEnvelope)object; + if (noLocal && messageEnvelope.getClientId().equals(appId)){ + LOGGER.debug("Received message ["+messageEnvelope.toString()+"] on topic "+subTopicName+", connection to "+url+" is ignored as it came from the same client and noLocal is set!"); + return; + } + LOGGER.debug("Received message ["+messageEnvelope.getData().toString()+"] on topic "+subTopicName+", connection to "+url); + messageListener.onMessage(messageEnvelope.getData()); + } catch (ClassNotFoundException | IOException e1) { + errorsListener.onException(new ClientException("Cannot deserialize an object from the message received from " + subTopicName, e1)); + LOGGER.error("Cannot deserialize an object from the message received from " + subTopicName +" for url"+url); + return; + } +``` + +Once the channels are opened, they are stored in an AmqpClientSubscription object (subclass of ClientSubscription object) for future use. Created instance of ClientSubscription object is registered with AmqpUniversalClient. + +### **sendMessage** method of AmqpClientSubscription object +Method sets AMQP properties and sends the message to a publishing exchange using specified routing key. +**Note:** As mentioned earlier, library creates a fanout type of exchange that does not use routing keys; thus library sets the value of the routing key to 'broadcast'. +We use AmqpMessageEnvelope to store application identifier that may be needed for filtering of the message. +Serialized object is stored in the ByteBuffer that is sent to the channel along with AMQP properties. + +```java + ... + AmqpMessageEnvelope messageEnvelope=new AmqpMessageEnvelope(this.appId, message); + byte[] serializedObject; + try { + serializedObject = Utils.serialize(messageEnvelope); + } catch (IOException e) { + throw new ClientException("Cannot serialize message " + message + " to send over subscription " + this.getSubscriptionIdentifier(), e); + } + ByteBuffer buffer = ByteBuffer.allocate(serializedObject.length); + buffer.put(serializedObject); + buffer.flip(); + + Timestamp ts = new Timestamp(System.currentTimeMillis()); + AmqpProperties props = new AmqpProperties(); + props.setMessageId("1"); + props.setCorrelationId("4"); + props.setAppId(appId); + props.setUserId(userId); + props.setPriority(6); + props.setDeliveryMode(1); + props.setTimestamp(ts); + + this.pubChannel.publishBasic(buffer, props, this.pubChannelName, AmqpUniversalClient.ROUTING_KEY, false, false); +``` + +### **disconnect** method of AmqpClientSubscription object +Deletes the declared subscription queue and closes the channels +```java + this.subChannel.deleteQueue(this.queueName, false, false, false); + + this.pubChannel.closeChannel(0, "", 0, 0); + this.subChannel.closeChannel(0, "", 0, 0); +``` + +### **close** method of AmqpUniversalClient object +Disconnects all opened subscriptions, disconnects Amqp client. +```java + ... + for (AmqpClientSubscription conn : this.connections) { + conn.disconnect(); + } + this.amqpClient.disconnect(); +``` + + diff --git a/java/KaazingJMSClientLibrariesFacade.md b/java/KaazingJMSClientLibrariesFacade.md new file mode 100644 index 0000000..964a8cc --- /dev/null +++ b/java/KaazingJMSClientLibrariesFacade.md @@ -0,0 +1,253 @@ +# Kaazing Java JMS Client Libraries Facade +Kaazing Java JMS Client Libraries Facade simplifies the interaction with Kaazing Java JMS Client libraries that enable the developers to interact with [JMS](http://docs.oracle.com/javaee/6/tutorial/doc/bncdx.html) brokers via WebSockets. + +Kaazing Java JMS Client Libraries Facade: +* Implements basic publish-subscribe functionality for JMS to help developers in getting started with their JMS WebSocket projects +* Provide developers with the reference implementations for using Kaazing JMS Java client libraries + +For more information see: +- [Build Java JMS Clients Using Kaazing WebSocket Gateway - JMS Edition](http://developer.kaazing.com/documentation/jms/4.0/dev-java/o_dev_java.html) +- [Use the Kaazing WebSocket Gateway Java JMS Client API](http://developer.kaazing.com/documentation/jms/4.0/dev-java/p_dev_java_client.html) + +## Organization of the library +UniversalClientFactory's create +Library contains JMSUniversalClient class (implementing UniversalClient interface) that is created by UniversalClientFactory's _createUniversalClient_ method. JMSUniversalClient object provides the following functionality: +- **constructor** of JMSUniversalClient - connects client to Kaazing WebSocket JMS gateway +- **subscribe** method of JMSUniversalClient - subscribes to publishing and subscription endpoints and returns an instance of ClientSubscription object. +- **sendMessage** method of ClientSubscription - sends the instances of Serialized Objects to the publishing endpoint +- **disconnect** method of ClientSubscription - closes subscription to publishing and subscription endpoints for this subscription +- **close** method of JMSUniversalClient - closes all subscriptions and connections + +### **constructor** of JMSUniversalClient +Constructor implements the following sequence: + +- Locate JMS connection factory using JNDI: + + ```java + Properties env = new Properties(); + env.setProperty("java.naming.factory.initial", "com.kaazing.gateway.jms.client.JmsInitialContextFactory"); + + try { + jndiInitialContext = new InitialContext(env); + } catch (NamingException e1) { + throw new ClientException("Error creating initial context factory for JMS!", e1); + } + env.put(JmsInitialContext.CONNECTION_TIMEOUT, "15000"); + try { + connectionFactory = (ConnectionFactory) jndiInitialContext.lookup("ConnectionFactory"); + } catch (NamingException e) { + throw new ClientException("Error locating connection factory for JMS!", e); + } + JmsConnectionFactory jmsConnectionFactory = (JmsConnectionFactory) connectionFactory; + ``` + +- Create connection. To create connection: + - Set the gateway URL connection for JMS connection factory. + - Create WebSocket factory + - Create connection passing login and password: + ```java + ... + jmsConnectionFactory.setGatewayLocation(url); + WebSocketFactory webSocketFactory = jmsConnectionFactory.getWebSocketFactory(); + webSocketFactory.setDefaultRedirectPolicy(HttpRedirectPolicy.ALWAYS); + try { + connection = connectionFactory.createConnection(login, password); + } catch (JMSException e) { + throw new ClientException("Error connecting to gateway with " + url.toString() + ", credentials " + login + "/" + password, e); + } + ... + ``` +- Register the ErrorsListener object that is passed to the constructor with the connection to be a listener for any errors and exceptions: + ```java + ... + try { + connection.setExceptionListener(this); + } catch (JMSException e) { + throw new ClientException("Error setting exceptions listener. Connection: " + url.toString() + ", credentials " + login + "/" + password, e); + } + ... + ``` + +- Create __session__ in auto-acknowledgement mode. In this mode session automatically acknowledges a client's receipt of a message either when the session has successfully returned from a call to receive or when the message listener the session has called to process the message successfully returns. + ```java + ... + try + { + session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + } catch (JMSException e) { + throw new ClientException("Error creating session. Connection: " + url.toString() + ", credentials " + login + "/" + password, e); + } + ... + ``` +- Start the connection + ```java + try + { + connection.start(); + } catch (JMSException e) { + throw new ClientException("Error starting connection: " + url.toString() + ", credentials " + login + "/" + password, e); + } + ``` +Once object is successfully constructed it is ready to create subscriptions. + + +### **subscribe** method of of JMSUniversalClient object +Method executed the following actions: + +- Creates subscription destination + + ```java + Destination subDestination; + try { + subDestination = (Destination) jndiInitialContext.lookup("/topic/" + subTopicName); + } catch (NamingException e) { + throw new ClientException("Cannot locate subscription topic " + subTopicName, e); + } + ``` +- Creates message Consumer. + _In order to prevent client from receiving its own messages consumer may be created with the query that will filter out the messages with the 'appId' string property set to this client application ID - a randomly generated GUID._ + ```java + ... + MessageConsumer consumer; + try { + + if (noLocal){ + clientId=UUID.randomUUID().toString(); + consumer = session.createConsumer(subDestination, "clientId<>'"+clientId+"'"); + } + else + consumer = session.createConsumer(subDestination); + } catch (JMSException e) { + throw new ClientException("Cannot create consumer for subscription topic " + subTopicName, e); + } + ... + ``` +- Registers an instance of ... passed to the method to be a message listener. + ```java + ... + try + { + consumer.setMessageListener(new MessageListenerImpl(messageListener, this.errorsListener, subTopicName)); + } catch (JMSException e) { + throw new ClientException("Cannot create messages listener for subscription topic " + subTopicName, e); + } + ... + ``` + + We use MessageLinstenerImpl wrapper class that implements MessageListener to convert the ByteMessage object received from the wire to an instance of Serializable object that was sent. + ```java + ... + if (message instanceof BytesMessage) { + try { + BytesMessage bytesMessage = ((BytesMessage) message); + long len = bytesMessage.getBodyLength(); + byte b[] = new byte[(int) len]; + bytesMessage.readBytes(b); + Serializable object; + try { + object = Utils.deserialize(b); + LOGGER.debug("Received message ["+object.toString()+"] on topic "+destination+", connection to "+url); + this.listener.onMessage(object); + } catch (ClassNotFoundException | IOException e) { + this.errorsListener.onException(new ClientException("Cannot deserialize an object from the message received from " + destination, e)); + LOGGER.error("Cannot deserialize an object from the message received from " + destination+" connection to "+url, e); + return; + } + + } catch (JMSException e) { + this.errorsListener.onException(new ClientException("Error receiving message from destination " + destination, e)); + LOGGER.error("Error receiving message from destination " + destination+" connection to "+url, e); + } + } else { + this.errorsListener.onException(new ClientException("Received a message of unexpected type " + message.getClass().getName() + " for a destination " + destination)); + LOGGER.error("Received a message of unexpected type " + message.getClass().getName() + destination+" connection to "+url); + } + ... + ``` + +- Create publishing destination and producer + ```java + Destination pubDestination; + try { + pubDestination = (Destination) jndiInitialContext.lookup("/topic/" + pubTopicName); + } catch (NamingException e) { + throw new ClientException("Cannot locate publishing topic " + pubTopicName, e); + } + MessageProducer producer; + try { + producer = session.createProducer(pubDestination); + } catch (JMSException e) { + throw new ClientException("Cannot create producer for publishing topic " + pubTopicName, e); + } + ``` + + Session, producer and consumer are stored in an JMSClientSubscription object (subclass of ClientSubscription object) for future use. Created instance of ClientSubscription object is registered with JMSUniversalClient. + +### **sendMessage** method of JMSClientSubscription object +Function creates a binary message and sends it using the following steps. + - Creates bytes message and serializes Java object to it. + ```java + BytesMessage bytesMessage; + try { + bytesMessage = session.createBytesMessage(); + } catch (JMSException e) { + throw new ClientException("Subscription: "+this.getSubscriptionIdentifier()+" - Cannot create a BytesMessage for an object " + message.toString(), e); + } + try { + bytesMessage.writeBytes(Utils.serialize(message)); + } catch (JMSException e) { + throw new ClientException("Subscription: "+this.getSubscriptionIdentifier()+" - Cannot write bytes to set the payload of a BytesMessage for an object " + message.toString(), e); + } catch (IOException e) { + throw new ClientException("Subscription: "+this.getSubscriptionIdentifier()+" - Cannot serialize an object " + message.toString(), e); + } + ``` + - _If needed_, sets string property clientId. This property will be used to ignore receiving your own messages which may be applicable if publishing and subscription endpoints are the same. + ```java + ... + if (clientId!=null){ + try { + bytesMessage.setStringProperty("clientId", clientId); + } catch (JMSException e) { + throw new ClientException("Subscription: "+this.getSubscriptionIdentifier()+" - Cannot set a string property client id to "+clientId+" for an object " + message.toString(), e); + } + } + ... + ``` + - Send message to the publishing endpoing + ```java + ... + try { + producer.send(bytesMessage); + } catch (JMSException e) { + throw new ClientException("Subscription: "+this.getSubscriptionIdentifier()+" - Cannot sent and object message for an object " + message.toString(), e); + } + ... + ``` + +### **disconnect** method of JMSClientSubscription object +Closes producer and consumer. + +```java + try { + this.producer.close(); + } catch (JMSException e) { + throw new ClientException("Subscription: "+this.getSubscriptionIdentifier()+" - Error closing producer.",e); + } + try { + this.consumer.close(); + } catch (JMSException e) { + throw new ClientException("Subscription: "+this.getSubscriptionIdentifier()+" - Error closing consumer.",e); + } +``` + +**close** method of JMSUniversalClient +Disconnects all opened subscriptions, closes session and connection. + +```java + for(JMSClientSubscription connection: this.connections){ + connection.disconnect(); + } + this.connection.stop(); + this.session.close(); + this.connection.close(); +``` \ No newline at end of file diff --git a/java/README.md b/java/README.md new file mode 100644 index 0000000..9104201 --- /dev/null +++ b/java/README.md @@ -0,0 +1,122 @@ +# Universal Clients for Java Applications +The [Kaazing Java WebSocket Universal Clients][2] library uses the same [Java AMQP Client Libraries Facade][3] and [Java JMS Client Libraries Facade][4] for interaction with Kaazing AMQP and JMS client libraries. +Please, refer to the links above for the details about the details of the usage and implementations. + +## Using the Client Libraries +- Using Gradle +``` +'com.kaazing.client:universal-client:1.0+' +``` +- Using Maven +``` + + com.kaazing.client + universal-client + 1.0+ + +``` + +### Obtaining and Configuring Kaazing Gateway +The Kaazing Universal WebSocket clients depend on the Kaazing WebSocket Gateway (KWG) being installed on one or more servers. KWG supports two protocols, AMQP and JMS. Read [Obtaining and configuring Kaazing Gateways and related Servers](https://github.com/kaazing/universal-client/blob/develop/ObtainingGateways.md) for more information. + +### Using the Library +- Create an instance of the Universal Client Library. + ```java + try (UniversalClient universalClient = UniversalClientFactory.createUniversalClient(UniversalClientProtocol.amqp, // Protocol + new URI("ws://localhost:8001/amqp"), // Kaazing Gateway URL + "guest", // Login to use to connect to Kaazing Gateway + "guest", // Password to use to connect to Kaazing Gateway + new ErrorsListener() { // Error listener callback - simply printerrors + @Override + public void onException(ClientException exception) { + System.err.println("Exception occurred! " + exception.getMessage()); + } + });) { + + ... + + }; + ``` + +- Establish a connection + ```java + try (UniversalClient universalClient = UniversalClientFactory.createUniversalClient(UniversalClientProtocol.amqp, // Protocol + new URI("ws://localhost:8001/amqp"), // Kaazing Gateway URL + "guest", // Login to use to connect to Kaazing Gateway + "guest", // Password to use to connect to Kaazing Gateway + new ErrorsListener() { // Error listener callback - simply printerrors + @Override + public void onException(ClientException exception) { + System.err.println("Exception occurred! " + exception.getMessage()); + } + });) { + + ClientSubscription subscription = universalClient.subscribe("test", // publishing point + "test", // subscription point + new MessagesListener() { // Message listener - simply print messages + @Override + public void onMessage(Serializable message) { + System.out.println("Received message: " + message.toString()); + } + + }; + ``` +- Send message + ```java + try (UniversalClient universalClient = UniversalClientFactory.createUniversalClient(UniversalClientProtocol.amqp, // Protocol + new URI("ws://localhost:8001/amqp"), // Kaazing Gateway URL + "guest", // Login to use to connect to Kaazing Gateway + "guest", // Password to use to connect to Kaazing Gateway + new ErrorsListener() { // Error listener callback - simply printerrors + @Override + public void onException(ClientException exception) { + System.err.println("Exception occurred! " + exception.getMessage()); + } + });) { + + ClientSubscription subscription = universalClient.subscribe("test", // publishing point + "test", // subscription point + new MessagesListener() { // Message listener - simply print messages + @Override + public void onMessage(Serializable message) { + System.out.println("Received message: " + message.toString()); + } + + // Send as a text + subscription.sendMessage(text); + // Send as an object + subscription.sendMessage(new SomeObjectMessage()); + + + }; + ``` + +## Organization of Kaazing JavaScript Universal Client + +![][image-1] + +As shown on the diagram above, Kaazing Universal Client works as following: +- Instantiates required Client Facade Library based on specified protocol that will interact with necessary Kaazing Java Client Libraries +- Pass the data to and from the Kaazing Java Client libraries via instantiated Client Facade Library + +For more information about Client Facade libraries see +[AMQP Client Libraries Facade][2] and [JMS Client Libraries Facade][3]. + + +## Documentation + +### AMQP +- [How to Build Java Clients Using Kaazing WebSocket Gateway](http://developer.kaazing.com/documentation/amqp/4.0/dev-java/o_dev_java.html) +- [Use the Kaazing WebSocket Gateway Java AMQP Client Library](http://developer.kaazing.com/documentation/amqp/4.0/dev-java/p_dev_java_client.html) + +### JMS +- [Build Java JMS Clients Using Kaazing WebSocket Gateway - JMS Edition](http://developer.kaazing.com/documentation/jms/4.0/dev-java/o_dev_java.html) +- [Use the Kaazing WebSocket Gateway Java JMS Client API](http://developer.kaazing.com/documentation/jms/4.0/dev-java/p_dev_java_client.html) + + +[2]: JavaClient.md "Java library" +[3]: KaazingAMQPClientLibrariesFacade.md +[4]: KaazingJMSClientLibrariesFacade.md +[image-1]: images/JavaUniversalClient.png "Java Universal Client" + + diff --git a/java/doc/allclasses-frame.html b/java/doc/allclasses-frame.html new file mode 100644 index 0000000..099267b --- /dev/null +++ b/java/doc/allclasses-frame.html @@ -0,0 +1,35 @@ + + + + + +All Classes + + + + + +

All Classes

+ + + diff --git a/java/doc/allclasses-noframe.html b/java/doc/allclasses-noframe.html new file mode 100644 index 0000000..3989f8a --- /dev/null +++ b/java/doc/allclasses-noframe.html @@ -0,0 +1,35 @@ + + + + + +All Classes + + + + + +

All Classes

+ + + diff --git a/java/doc/com/kaazing/client/universal/AmqpClientSubscription.html b/java/doc/com/kaazing/client/universal/AmqpClientSubscription.html new file mode 100644 index 0000000..2c041bd --- /dev/null +++ b/java/doc/com/kaazing/client/universal/AmqpClientSubscription.html @@ -0,0 +1,335 @@ + + + + + +AmqpClientSubscription + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Class AmqpClientSubscription

+
+
+ +
+
    +
  • +
    +
    +
    public class AmqpClientSubscription
    +extends ClientSubscription
    +
    Contains information specific to AMQP subscriptions
    +
    +
    Author:
    +
    romans
    +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Summary

      + + + + + + + + +
      Constructors 
      Constructor and Description
      AmqpClientSubscription(java.lang.String subscriptionIdentifier, + java.lang.String appId, + java.lang.String userId, + java.lang.String pubChannelName, + java.lang.String queueName, + com.kaazing.net.ws.amqp.AmqpChannel pubChannel, + com.kaazing.net.ws.amqp.AmqpChannel subChannel) 
      +
    • +
    + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + +
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethod and Description
      voiddisconnect() +
      Closes both publishing and subscription endpoints
      +
      voidsendMessage(java.io.Serializable message) +
      Sends the message over established subscription to the publishing point
      +
      + +
        +
      • + + +

        Methods inherited from class java.lang.Object

        +equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • +
      +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        AmqpClientSubscription

        +
        public AmqpClientSubscription(java.lang.String subscriptionIdentifier,
        +                              java.lang.String appId,
        +                              java.lang.String userId,
        +                              java.lang.String pubChannelName,
        +                              java.lang.String queueName,
        +                              com.kaazing.net.ws.amqp.AmqpChannel pubChannel,
        +                              com.kaazing.net.ws.amqp.AmqpChannel subChannel)
        +
      • +
      +
    • +
    + + +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/AmqpMessageEnvelope.html b/java/doc/com/kaazing/client/universal/AmqpMessageEnvelope.html new file mode 100644 index 0000000..4ac224f --- /dev/null +++ b/java/doc/com/kaazing/client/universal/AmqpMessageEnvelope.html @@ -0,0 +1,313 @@ + + + + + +AmqpMessageEnvelope + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Class AmqpMessageEnvelope

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • com.kaazing.client.universal.AmqpMessageEnvelope
    • +
    +
  • +
+
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    java.io.Serializable
    +
    +
    +
    +
    public class AmqpMessageEnvelope
    +extends java.lang.Object
    +implements java.io.Serializable
    +
    Adds the sender ID to the message so it can be used for noLocal filtering when it is not supported by the server
    +
    +
    Author:
    +
    romans
    +
    See Also:
    +
    Serialized Form
    +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Summary

      + + + + + + + + +
      Constructors 
      Constructor and Description
      AmqpMessageEnvelope(java.lang.String clientId, + java.io.Serializable data) 
      +
    • +
    + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + + + + + +
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethod and Description
      java.lang.StringgetClientId() 
      java.io.SerializablegetData() 
      java.lang.StringtoString() 
      +
        +
      • + + +

        Methods inherited from class java.lang.Object

        +equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
      • +
      +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        AmqpMessageEnvelope

        +
        public AmqpMessageEnvelope(java.lang.String clientId,
        +                           java.io.Serializable data)
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        getClientId

        +
        public java.lang.String getClientId()
        +
      • +
      + + + +
        +
      • +

        getData

        +
        public java.io.Serializable getData()
        +
      • +
      + + + +
        +
      • +

        toString

        +
        public java.lang.String toString()
        +
        +
        Overrides:
        +
        toString in class java.lang.Object
        +
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/AmqpUniversalClient.html b/java/doc/com/kaazing/client/universal/AmqpUniversalClient.html new file mode 100644 index 0000000..1bcb92b --- /dev/null +++ b/java/doc/com/kaazing/client/universal/AmqpUniversalClient.html @@ -0,0 +1,334 @@ + + + + + +AmqpUniversalClient + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Class AmqpUniversalClient

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • com.kaazing.client.universal.AmqpUniversalClient
    • +
    +
  • +
+
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    UniversalClient, java.lang.AutoCloseable
    +
    +
    +
    +
    public class AmqpUniversalClient
    +extends java.lang.Object
    +implements UniversalClient
    +
    AMQP specific implmentation of Universal client
    +
    +
    Author:
    +
    romans
    +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Summary

      + + + + + + + + +
      Constructors 
      Constructor and Description
      AmqpUniversalClient(java.net.URI url, + java.lang.String login, + java.lang.String password, + ErrorsListener errorsListener) 
      +
    • +
    + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + +
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethod and Description
      voidclose() 
      ClientSubscriptionsubscribe(java.lang.String pubTopicName, + java.lang.String subTopicName, + MessagesListener messageListener, + boolean noLocal) +
      Connects client to pub/sub endpoints
      +
      +
        +
      • + + +

        Methods inherited from class java.lang.Object

        +equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • +
      +
    • +
    +
  • +
+
+
+
    +
  • + + + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        close

        +
        public void close()
        +           throws java.lang.Exception
        +
        +
        Specified by:
        +
        close in interface java.lang.AutoCloseable
        +
        Throws:
        +
        java.lang.Exception
        +
        +
      • +
      + + + +
        +
      • +

        subscribe

        +
        public ClientSubscription subscribe(java.lang.String pubTopicName,
        +                                    java.lang.String subTopicName,
        +                                    MessagesListener messageListener,
        +                                    boolean noLocal)
        +                             throws ClientException
        +
        Description copied from interface: UniversalClient
        +
        Connects client to pub/sub endpoints
        +
        +
        Specified by:
        +
        subscribe in interface UniversalClient
        +
        Parameters:
        +
        pubTopicName - name of publishing topic
        +
        subTopicName - name of subscription topic
        +
        messageListener - callback to receive messages
        +
        noLocal - if true client will not receive its own messages (applicable only when pub and sub points are the same)
        +
        Returns:
        +
        subscription information
        +
        Throws:
        +
        ClientException - indicates that error occurred
        +
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/AmqpUniversalClientTest.TestObject.html b/java/doc/com/kaazing/client/universal/AmqpUniversalClientTest.TestObject.html new file mode 100644 index 0000000..046d817 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/AmqpUniversalClientTest.TestObject.html @@ -0,0 +1,288 @@ + + + + + +AmqpUniversalClientTest.TestObject + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Class AmqpUniversalClientTest.TestObject

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • com.kaazing.client.universal.AmqpUniversalClientTest.TestObject
    • +
    +
  • +
+
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    java.io.Serializable
    +
    +
    +
    Enclosing class:
    +
    AmqpUniversalClientTest
    +
    +
    +
    +
    public static class AmqpUniversalClientTest.TestObject
    +extends java.lang.Object
    +implements java.io.Serializable
    +
    +
    See Also:
    +
    Serialized Form
    +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Summary

      + + + + + + + + +
      Constructors 
      Constructor and Description
      TestObject(int a, + java.lang.String b) 
      +
    • +
    + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + +
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethod and Description
      java.lang.StringtoString() 
      +
        +
      • + + +

        Methods inherited from class java.lang.Object

        +equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
      • +
      +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        TestObject

        +
        public TestObject(int a,
        +                  java.lang.String b)
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        toString

        +
        public java.lang.String toString()
        +
        +
        Overrides:
        +
        toString in class java.lang.Object
        +
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/AmqpUniversalClientTest.html b/java/doc/com/kaazing/client/universal/AmqpUniversalClientTest.html new file mode 100644 index 0000000..dc1b5c2 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/AmqpUniversalClientTest.html @@ -0,0 +1,377 @@ + + + + + +AmqpUniversalClientTest + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Class AmqpUniversalClientTest

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • com.kaazing.client.universal.AmqpUniversalClientTest
    • +
    +
  • +
+
+
    +
  • +
    +
    +
    public class AmqpUniversalClientTest
    +extends java.lang.Object
    +
    +
    Author:
    +
    romans
    +
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        AmqpUniversalClientTest

        +
        public AmqpUniversalClientTest()
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        setUp

        +
        public void setUp()
        +           throws ClientException,
        +                  java.net.URISyntaxException
        +
        +
        Throws:
        +
        ClientException
        +
        java.net.URISyntaxException
        +
        +
      • +
      + + + +
        +
      • +

        testString

        +
        public void testString()
        +                throws ClientException,
        +                       java.lang.InterruptedException
        +
        +
        Throws:
        +
        ClientException
        +
        java.lang.InterruptedException
        +
        +
      • +
      + + + +
        +
      • +

        testObject

        +
        public void testObject()
        +                throws ClientException,
        +                       java.lang.InterruptedException
        +
        +
        Throws:
        +
        ClientException
        +
        java.lang.InterruptedException
        +
        +
      • +
      + + + +
        +
      • +

        testNoLocal

        +
        public void testNoLocal()
        +                 throws ClientException,
        +                        java.lang.InterruptedException
        +
        +
        Throws:
        +
        ClientException
        +
        java.lang.InterruptedException
        +
        +
      • +
      + + + +
        +
      • +

        shutDown

        +
        public void shutDown()
        +              throws java.lang.Exception
        +
        +
        Throws:
        +
        java.lang.Exception
        +
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/ClientException.html b/java/doc/com/kaazing/client/universal/ClientException.html new file mode 100644 index 0000000..a4c6bdf --- /dev/null +++ b/java/doc/com/kaazing/client/universal/ClientException.html @@ -0,0 +1,289 @@ + + + + + +ClientException + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Class ClientException

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • java.lang.Throwable
    • +
    • +
        +
      • java.lang.Exception
      • +
      • +
          +
        • com.kaazing.client.universal.ClientException
        • +
        +
      • +
      +
    • +
    +
  • +
+
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    java.io.Serializable
    +
    +
    +
    +
    public class ClientException
    +extends java.lang.Exception
    +
    Contains the exception reported by Universal Client
    +
    +
    Author:
    +
    romans
    +
    See Also:
    +
    Serialized Form
    +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Summary

      + + + + + + + + + + + + + + +
      Constructors 
      Constructor and Description
      ClientException(java.lang.String text) 
      ClientException(java.lang.String text, + java.lang.Throwable t) 
      ClientException(java.lang.Throwable t) 
      +
    • +
    + +
      +
    • + + +

      Method Summary

      +
        +
      • + + +

        Methods inherited from class java.lang.Throwable

        +addSuppressed, fillInStackTrace, getCause, getLocalizedMessage, getMessage, getStackTrace, getSuppressed, initCause, printStackTrace, printStackTrace, printStackTrace, setStackTrace, toString
      • +
      +
        +
      • + + +

        Methods inherited from class java.lang.Object

        +equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
      • +
      +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        ClientException

        +
        public ClientException(java.lang.String text,
        +                       java.lang.Throwable t)
        +
      • +
      + + + +
        +
      • +

        ClientException

        +
        public ClientException(java.lang.String text)
        +
      • +
      + + + +
        +
      • +

        ClientException

        +
        public ClientException(java.lang.Throwable t)
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/ClientSubscription.html b/java/doc/com/kaazing/client/universal/ClientSubscription.html new file mode 100644 index 0000000..a774507 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/ClientSubscription.html @@ -0,0 +1,329 @@ + + + + + +ClientSubscription + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Class ClientSubscription

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • com.kaazing.client.universal.ClientSubscription
    • +
    +
  • +
+
+
    +
  • +
    +
    Direct Known Subclasses:
    +
    AmqpClientSubscription, JMSClientSubscription
    +
    +
    +
    +
    public abstract class ClientSubscription
    +extends java.lang.Object
    +
    Contains information about subscription
    +
    +
    Author:
    +
    romans
    +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Summary

      + + + + + + + + +
      Constructors 
      Constructor and Description
      ClientSubscription(java.lang.String subscriptionIdentifier) +
      Construct the subscription object.
      +
      +
    • +
    + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + + + + + +
      All Methods Instance Methods Abstract Methods Concrete Methods 
      Modifier and TypeMethod and Description
      abstract voiddisconnect() +
      Closes both publishing and subscription endpoints
      +
      java.lang.StringgetSubscriptionIdentifier() 
      abstract voidsendMessage(java.io.Serializable message) +
      Sends the message over established subscription to the publishing point
      +
      +
        +
      • + + +

        Methods inherited from class java.lang.Object

        +equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • +
      +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        ClientSubscription

        +
        public ClientSubscription(java.lang.String subscriptionIdentifier)
        +
        Construct the subscription object. The constructor should be overwritten by the implementation classes.
        +
        +
        Parameters:
        +
        subscriptionIdentifier - Identification of the subscription that is automatically generated when subscription is created.
        +
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        sendMessage

        +
        public abstract void sendMessage(java.io.Serializable message)
        +                          throws ClientException
        +
        Sends the message over established subscription to the publishing point
        +
        +
        Parameters:
        +
        message - message to send
        +
        Throws:
        +
        ClientException - indicates that error occurred
        +
        +
      • +
      + + + +
        +
      • +

        disconnect

        +
        public abstract void disconnect()
        +                         throws ClientException
        +
        Closes both publishing and subscription endpoints
        +
        +
        Throws:
        +
        ClientException - indicates that error occurred
        +
        +
      • +
      + + + +
        +
      • +

        getSubscriptionIdentifier

        +
        public java.lang.String getSubscriptionIdentifier()
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/ErrorsListener.html b/java/doc/com/kaazing/client/universal/ErrorsListener.html new file mode 100644 index 0000000..4c4d20c --- /dev/null +++ b/java/doc/com/kaazing/client/universal/ErrorsListener.html @@ -0,0 +1,231 @@ + + + + + +ErrorsListener + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Interface ErrorsListener

+
+
+
+
    +
  • +
    +
    +
    public interface ErrorsListener
    +
    Provides implementation for calback to handle the errors
    +
    +
    Author:
    +
    romans
    +
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        onException

        +
        void onException(ClientException exception)
        +
        Called by the Universal Client when exception occurs
        +
        +
        Parameters:
        +
        exception - exception reported by the client
        +
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/JMSClientSubscription.html b/java/doc/com/kaazing/client/universal/JMSClientSubscription.html new file mode 100644 index 0000000..5276ce3 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/JMSClientSubscription.html @@ -0,0 +1,331 @@ + + + + + +JMSClientSubscription + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Class JMSClientSubscription

+
+
+ +
+
    +
  • +
    +
    +
    public class JMSClientSubscription
    +extends ClientSubscription
    +
    Contains information specific to JMS subscriptions
    +
    +
    Author:
    +
    romans
    +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Summary

      + + + + + + + + +
      Constructors 
      Constructor and Description
      JMSClientSubscription(java.lang.String clientId, + java.lang.String subscriptionIdentifier, + javax.jms.Session session, + javax.jms.MessageProducer producer, + javax.jms.MessageConsumer consumer) 
      +
    • +
    + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + +
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethod and Description
      voiddisconnect() +
      Closes both publishing and subscription endpoints
      +
      voidsendMessage(java.io.Serializable message) +
      Sends the message over established subscription to the publishing point
      +
      + +
        +
      • + + +

        Methods inherited from class java.lang.Object

        +equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • +
      +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        JMSClientSubscription

        +
        public JMSClientSubscription(java.lang.String clientId,
        +                             java.lang.String subscriptionIdentifier,
        +                             javax.jms.Session session,
        +                             javax.jms.MessageProducer producer,
        +                             javax.jms.MessageConsumer consumer)
        +
      • +
      +
    • +
    + + +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/JMSUniversalClient.html b/java/doc/com/kaazing/client/universal/JMSUniversalClient.html new file mode 100644 index 0000000..c2e45c3 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/JMSUniversalClient.html @@ -0,0 +1,351 @@ + + + + + +JMSUniversalClient + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Class JMSUniversalClient

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • com.kaazing.client.universal.JMSUniversalClient
    • +
    +
  • +
+
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    UniversalClient, java.lang.AutoCloseable, javax.jms.ExceptionListener
    +
    +
    +
    +
    public class JMSUniversalClient
    +extends java.lang.Object
    +implements javax.jms.ExceptionListener, UniversalClient
    +
    JMS specific implementation of Universal Client
    +
    +
    Author:
    +
    romans
    +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Summary

      + + + + + + + + +
      Constructors 
      Constructor and Description
      JMSUniversalClient(java.net.URI url, + java.lang.String login, + java.lang.String password, + ErrorsListener errorsListener) 
      +
    • +
    + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + + + + + +
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethod and Description
      voidclose() 
      voidonException(javax.jms.JMSException exception) 
      ClientSubscriptionsubscribe(java.lang.String pubTopicName, + java.lang.String subTopicName, + MessagesListener messageListener, + boolean noLocal) +
      Connects client to pub/sub endpoints
      +
      +
        +
      • + + +

        Methods inherited from class java.lang.Object

        +equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • +
      +
    • +
    +
  • +
+
+
+
    +
  • + + + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        subscribe

        +
        public ClientSubscription subscribe(java.lang.String pubTopicName,
        +                                    java.lang.String subTopicName,
        +                                    MessagesListener messageListener,
        +                                    boolean noLocal)
        +                             throws ClientException
        +
        Description copied from interface: UniversalClient
        +
        Connects client to pub/sub endpoints
        +
        +
        Specified by:
        +
        subscribe in interface UniversalClient
        +
        Parameters:
        +
        pubTopicName - name of publishing topic
        +
        subTopicName - name of subscription topic
        +
        messageListener - callback to receive messages
        +
        noLocal - if true client will not receive its own messages (applicable only when pub and sub points are the same)
        +
        Returns:
        +
        subscription information
        +
        Throws:
        +
        ClientException - indicates that error occurred
        +
        +
      • +
      + + + +
        +
      • +

        onException

        +
        public void onException(javax.jms.JMSException exception)
        +
        +
        Specified by:
        +
        onException in interface javax.jms.ExceptionListener
        +
        +
      • +
      + + + +
        +
      • +

        close

        +
        public void close()
        +           throws java.lang.Exception
        +
        +
        Specified by:
        +
        close in interface java.lang.AutoCloseable
        +
        Throws:
        +
        java.lang.Exception
        +
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/JMSUniversalClientTest.TestObject.html b/java/doc/com/kaazing/client/universal/JMSUniversalClientTest.TestObject.html new file mode 100644 index 0000000..c0b8c5a --- /dev/null +++ b/java/doc/com/kaazing/client/universal/JMSUniversalClientTest.TestObject.html @@ -0,0 +1,288 @@ + + + + + +JMSUniversalClientTest.TestObject + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Class JMSUniversalClientTest.TestObject

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • com.kaazing.client.universal.JMSUniversalClientTest.TestObject
    • +
    +
  • +
+
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    java.io.Serializable
    +
    +
    +
    Enclosing class:
    +
    JMSUniversalClientTest
    +
    +
    +
    +
    public static class JMSUniversalClientTest.TestObject
    +extends java.lang.Object
    +implements java.io.Serializable
    +
    +
    See Also:
    +
    Serialized Form
    +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Summary

      + + + + + + + + +
      Constructors 
      Constructor and Description
      TestObject(int a, + java.lang.String b) 
      +
    • +
    + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + +
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethod and Description
      java.lang.StringtoString() 
      +
        +
      • + + +

        Methods inherited from class java.lang.Object

        +equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
      • +
      +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        TestObject

        +
        public TestObject(int a,
        +                  java.lang.String b)
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        toString

        +
        public java.lang.String toString()
        +
        +
        Overrides:
        +
        toString in class java.lang.Object
        +
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/JMSUniversalClientTest.html b/java/doc/com/kaazing/client/universal/JMSUniversalClientTest.html new file mode 100644 index 0000000..619c085 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/JMSUniversalClientTest.html @@ -0,0 +1,377 @@ + + + + + +JMSUniversalClientTest + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Class JMSUniversalClientTest

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • com.kaazing.client.universal.JMSUniversalClientTest
    • +
    +
  • +
+
+
    +
  • +
    +
    +
    public class JMSUniversalClientTest
    +extends java.lang.Object
    +
    +
    Author:
    +
    romans
    +
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        JMSUniversalClientTest

        +
        public JMSUniversalClientTest()
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        setUp

        +
        public void setUp()
        +           throws ClientException,
        +                  java.net.URISyntaxException
        +
        +
        Throws:
        +
        ClientException
        +
        java.net.URISyntaxException
        +
        +
      • +
      + + + +
        +
      • +

        testString

        +
        public void testString()
        +                throws ClientException,
        +                       java.lang.InterruptedException
        +
        +
        Throws:
        +
        ClientException
        +
        java.lang.InterruptedException
        +
        +
      • +
      + + + +
        +
      • +

        testObject

        +
        public void testObject()
        +                throws ClientException,
        +                       java.lang.InterruptedException
        +
        +
        Throws:
        +
        ClientException
        +
        java.lang.InterruptedException
        +
        +
      • +
      + + + +
        +
      • +

        testNoLocal

        +
        public void testNoLocal()
        +                 throws ClientException,
        +                        java.lang.InterruptedException
        +
        +
        Throws:
        +
        ClientException
        +
        java.lang.InterruptedException
        +
        +
      • +
      + + + +
        +
      • +

        shutDown

        +
        public void shutDown()
        +              throws java.lang.Exception
        +
        +
        Throws:
        +
        java.lang.Exception
        +
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/MessagesListener.html b/java/doc/com/kaazing/client/universal/MessagesListener.html new file mode 100644 index 0000000..7d7542f --- /dev/null +++ b/java/doc/com/kaazing/client/universal/MessagesListener.html @@ -0,0 +1,231 @@ + + + + + +MessagesListener + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Interface MessagesListener

+
+
+
+
    +
  • +
    +
    +
    public interface MessagesListener
    +
    Listener for the messages received by Universal Client
    +
    +
    Author:
    +
    romans
    +
    +
  • +
+
+
+
    +
  • + + +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        onMessage

        +
        void onMessage(java.io.Serializable message)
        +
        Called when message is received
        +
        +
        Parameters:
        +
        message - body of the message
        +
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/SubscriptionConnection.html b/java/doc/com/kaazing/client/universal/SubscriptionConnection.html new file mode 100644 index 0000000..2f45bc1 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/SubscriptionConnection.html @@ -0,0 +1,331 @@ + + + + + +SubscriptionConnection + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Class SubscriptionConnection

+
+
+ +
+
    +
  • +
    +
    +
    public class SubscriptionConnection
    +extends ClientSubscription
    +
    Contains information specific to JMS subscriptions
    +
    +
    Author:
    +
    romans
    +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Summary

      + + + + + + + + +
      Constructors 
      Constructor and Description
      SubscriptionConnection(java.lang.String clientId, + java.lang.String connectionIdentifier, + javax.jms.Session session, + javax.jms.MessageProducer producer, + javax.jms.MessageConsumer consumer) 
      +
    • +
    + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + +
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethod and Description
      voiddisconnect() +
      Closes connection to both publishing and subscription endpoints
      +
      voidsendMessage(java.io.Serializable message) +
      Sends the message over established connection to the publishing point
      +
      + +
        +
      • + + +

        Methods inherited from class java.lang.Object

        +equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • +
      +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        SubscriptionConnection

        +
        public SubscriptionConnection(java.lang.String clientId,
        +                              java.lang.String connectionIdentifier,
        +                              javax.jms.Session session,
        +                              javax.jms.MessageProducer producer,
        +                              javax.jms.MessageConsumer consumer)
        +
      • +
      +
    • +
    + + +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/UniversalClient.html b/java/doc/com/kaazing/client/universal/UniversalClient.html new file mode 100644 index 0000000..2eeb5d3 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/UniversalClient.html @@ -0,0 +1,261 @@ + + + + + +UniversalClient + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Interface UniversalClient

+
+
+
+
    +
  • +
    +
    All Superinterfaces:
    +
    java.lang.AutoCloseable
    +
    +
    +
    All Known Implementing Classes:
    +
    AmqpUniversalClient, JMSUniversalClient
    +
    +
    +
    +
    public interface UniversalClient
    +extends java.lang.AutoCloseable
    +
    Interface for Kaazing protocol independent universal client
    +
    +
    Author:
    +
    romans
    +
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        subscribe

        +
        ClientSubscription subscribe(java.lang.String pubTopicName,
        +                             java.lang.String subTopicName,
        +                             MessagesListener messageListener,
        +                             boolean noLocal)
        +                      throws ClientException
        +
        Connects client to pub/sub endpoints
        +
        +
        Parameters:
        +
        pubTopicName - name of publishing topic
        +
        subTopicName - name of subscription topic
        +
        messageListener - callback to receive messages
        +
        noLocal - if true client will not receive its own messages (applicable only when pub and sub points are the same)
        +
        Returns:
        +
        subscription information
        +
        Throws:
        +
        ClientException - indicates that error occurred
        +
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/UniversalClientFactory.html b/java/doc/com/kaazing/client/universal/UniversalClientFactory.html new file mode 100644 index 0000000..d03f45e --- /dev/null +++ b/java/doc/com/kaazing/client/universal/UniversalClientFactory.html @@ -0,0 +1,264 @@ + + + + + +UniversalClientFactory + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Class UniversalClientFactory

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • com.kaazing.client.universal.UniversalClientFactory
    • +
    +
  • +
+
+
    +
  • +
    +
    +
    public class UniversalClientFactory
    +extends java.lang.Object
    +
    Factory to create an instance of Universal Client
    +
    +
    Author:
    +
    romans
    +
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        createUniversalClient

        +
        public static UniversalClient createUniversalClient(UniversalClientProtocol protocol,
        +                                                    java.net.URI url,
        +                                                    java.lang.String login,
        +                                                    java.lang.String password,
        +                                                    ErrorsListener errorsListener)
        +                                             throws ClientException
        +
        Constructs an instance of Universal client specific to protocols
        +
        +
        Parameters:
        +
        protocol - Protocol to use
        +
        url - URL to Kaazing Gateway
        +
        login - Login to use with Kaazing Gateway
        +
        password - Login to use with Kaazing Gateway
        +
        errorsListener - Callback to handle client errors
        +
        Returns:
        +
        instance of Universal Client specific to a selected protocol
        +
        Throws:
        +
        ClientException - indicates an error
        +
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/UniversalClientProtocol.html b/java/doc/com/kaazing/client/universal/UniversalClientProtocol.html new file mode 100644 index 0000000..97f4579 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/UniversalClientProtocol.html @@ -0,0 +1,339 @@ + + + + + +UniversalClientProtocol + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Enum UniversalClientProtocol

+
+
+
    +
  • java.lang.Object
  • +
  • + +
  • +
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Enum Constant Summary

      + + + + + + + + + + + +
      Enum Constants 
      Enum Constant and Description
      amqp 
      jms 
      +
    • +
    + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + +
      All Methods Static Methods Concrete Methods 
      Modifier and TypeMethod and Description
      static UniversalClientProtocolvalueOf(java.lang.String name) +
      Returns the enum constant of this type with the specified name.
      +
      static UniversalClientProtocol[]values() +
      Returns an array containing the constants of this enum type, in +the order they are declared.
      +
      +
        +
      • + + +

        Methods inherited from class java.lang.Enum

        +compareTo, equals, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
      • +
      +
        +
      • + + +

        Methods inherited from class java.lang.Object

        +getClass, notify, notifyAll, wait, wait, wait
      • +
      +
    • +
    +
  • +
+
+
+
    +
  • + + + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        values

        +
        public static UniversalClientProtocol[] values()
        +
        Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
        +for (UniversalClientProtocol c : UniversalClientProtocol.values())
        +    System.out.println(c);
        +
        +
        +
        Returns:
        +
        an array containing the constants of this enum type, in the order they are declared
        +
        +
      • +
      + + + +
        +
      • +

        valueOf

        +
        public static UniversalClientProtocol valueOf(java.lang.String name)
        +
        Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.)
        +
        +
        Parameters:
        +
        name - the name of the enum constant to be returned.
        +
        Returns:
        +
        the enum constant with the specified name
        +
        Throws:
        +
        java.lang.IllegalArgumentException - if this enum type has no constant with the specified name
        +
        java.lang.NullPointerException - if the argument is null
        +
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/Utils.html b/java/doc/com/kaazing/client/universal/Utils.html new file mode 100644 index 0000000..17fb684 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/Utils.html @@ -0,0 +1,330 @@ + + + + + +Utils + + + + + + + + + + + + +
+
com.kaazing.client.universal
+

Class Utils

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • com.kaazing.client.universal.Utils
    • +
    +
  • +
+
+
    +
  • +
    +
    +
    public class Utils
    +extends java.lang.Object
    +
    Provides implementation of commonly used utils
    +
    +
    Author:
    +
    romans
    +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Summary

      + + + + + + + + +
      Constructors 
      Constructor and Description
      Utils() 
      +
    • +
    + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + + + + + +
      All Methods Static Methods Concrete Methods 
      Modifier and TypeMethod and Description
      static java.io.Serializabledeserialize(byte[] bytes) +
      Deserializes the object from byte array
      +
      static java.lang.StringgenerateIdentifier(java.lang.String url, + java.lang.String pubTopicName, + java.lang.String subTopicName) 
      static byte[]serialize(java.io.Serializable obj) +
      Serializes java object to bytes
      +
      +
        +
      • + + +

        Methods inherited from class java.lang.Object

        +equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • +
      +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        Utils

        +
        public Utils()
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        serialize

        +
        public static byte[] serialize(java.io.Serializable obj)
        +                        throws java.io.IOException
        +
        Serializes java object to bytes
        +
        +
        Parameters:
        +
        obj - Object to serialize
        +
        Returns:
        +
        byte array containing serialized objects
        +
        Throws:
        +
        java.io.IOException - indicates that object cannot be serialized
        +
        +
      • +
      + + + +
        +
      • +

        deserialize

        +
        public static java.io.Serializable deserialize(byte[] bytes)
        +                                        throws java.io.IOException,
        +                                               java.lang.ClassNotFoundException
        +
        Deserializes the object from byte array
        +
        +
        Parameters:
        +
        bytes - byte array containing the object
        +
        Returns:
        +
        Deserialized object
        +
        Throws:
        +
        java.io.IOException - indicates that deserialization cannot be performed due to IO error
        +
        java.lang.ClassNotFoundException - indicates that deserialization cannot be performed due to the abscence of suitable class
        +
        +
      • +
      + + + +
        +
      • +

        generateIdentifier

        +
        public static java.lang.String generateIdentifier(java.lang.String url,
        +                                                  java.lang.String pubTopicName,
        +                                                  java.lang.String subTopicName)
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/AmqpClientSubscription.html b/java/doc/com/kaazing/client/universal/class-use/AmqpClientSubscription.html new file mode 100644 index 0000000..99ee1b2 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/AmqpClientSubscription.html @@ -0,0 +1,122 @@ + + + + + +Uses of Class com.kaazing.client.universal.AmqpClientSubscription + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.AmqpClientSubscription

+
+
No usage of com.kaazing.client.universal.AmqpClientSubscription
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/AmqpMessageEnvelope.html b/java/doc/com/kaazing/client/universal/class-use/AmqpMessageEnvelope.html new file mode 100644 index 0000000..a179911 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/AmqpMessageEnvelope.html @@ -0,0 +1,122 @@ + + + + + +Uses of Class com.kaazing.client.universal.AmqpMessageEnvelope + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.AmqpMessageEnvelope

+
+
No usage of com.kaazing.client.universal.AmqpMessageEnvelope
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/AmqpUniversalClient.html b/java/doc/com/kaazing/client/universal/class-use/AmqpUniversalClient.html new file mode 100644 index 0000000..0352704 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/AmqpUniversalClient.html @@ -0,0 +1,122 @@ + + + + + +Uses of Class com.kaazing.client.universal.AmqpUniversalClient + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.AmqpUniversalClient

+
+
No usage of com.kaazing.client.universal.AmqpUniversalClient
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/AmqpUniversalClientTest.TestObject.html b/java/doc/com/kaazing/client/universal/class-use/AmqpUniversalClientTest.TestObject.html new file mode 100644 index 0000000..5a9fd07 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/AmqpUniversalClientTest.TestObject.html @@ -0,0 +1,122 @@ + + + + + +Uses of Class com.kaazing.client.universal.AmqpUniversalClientTest.TestObject + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.AmqpUniversalClientTest.TestObject

+
+
No usage of com.kaazing.client.universal.AmqpUniversalClientTest.TestObject
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/AmqpUniversalClientTest.html b/java/doc/com/kaazing/client/universal/class-use/AmqpUniversalClientTest.html new file mode 100644 index 0000000..fc92a79 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/AmqpUniversalClientTest.html @@ -0,0 +1,122 @@ + + + + + +Uses of Class com.kaazing.client.universal.AmqpUniversalClientTest + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.AmqpUniversalClientTest

+
+
No usage of com.kaazing.client.universal.AmqpUniversalClientTest
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/ClientException.html b/java/doc/com/kaazing/client/universal/class-use/ClientException.html new file mode 100644 index 0000000..3a09853 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/ClientException.html @@ -0,0 +1,271 @@ + + + + + +Uses of Class com.kaazing.client.universal.ClientException + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.ClientException

+
+
+ +
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/ClientSubscription.html b/java/doc/com/kaazing/client/universal/class-use/ClientSubscription.html new file mode 100644 index 0000000..3562fb6 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/ClientSubscription.html @@ -0,0 +1,187 @@ + + + + + +Uses of Class com.kaazing.client.universal.ClientSubscription + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.ClientSubscription

+
+
+ +
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/ErrorsListener.html b/java/doc/com/kaazing/client/universal/class-use/ErrorsListener.html new file mode 100644 index 0000000..7b7c305 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/ErrorsListener.html @@ -0,0 +1,173 @@ + + + + + +Uses of Interface com.kaazing.client.universal.ErrorsListener + + + + + + + + + + + +
+

Uses of Interface
com.kaazing.client.universal.ErrorsListener

+
+
+ +
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/JMSClientSubscription.html b/java/doc/com/kaazing/client/universal/class-use/JMSClientSubscription.html new file mode 100644 index 0000000..a12659d --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/JMSClientSubscription.html @@ -0,0 +1,122 @@ + + + + + +Uses of Class com.kaazing.client.universal.JMSClientSubscription + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.JMSClientSubscription

+
+
No usage of com.kaazing.client.universal.JMSClientSubscription
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/JMSUniversalClient.html b/java/doc/com/kaazing/client/universal/class-use/JMSUniversalClient.html new file mode 100644 index 0000000..0a9c4df --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/JMSUniversalClient.html @@ -0,0 +1,122 @@ + + + + + +Uses of Class com.kaazing.client.universal.JMSUniversalClient + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.JMSUniversalClient

+
+
No usage of com.kaazing.client.universal.JMSUniversalClient
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/JMSUniversalClientTest.TestObject.html b/java/doc/com/kaazing/client/universal/class-use/JMSUniversalClientTest.TestObject.html new file mode 100644 index 0000000..ba8fb03 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/JMSUniversalClientTest.TestObject.html @@ -0,0 +1,122 @@ + + + + + +Uses of Class com.kaazing.client.universal.JMSUniversalClientTest.TestObject + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.JMSUniversalClientTest.TestObject

+
+
No usage of com.kaazing.client.universal.JMSUniversalClientTest.TestObject
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/JMSUniversalClientTest.html b/java/doc/com/kaazing/client/universal/class-use/JMSUniversalClientTest.html new file mode 100644 index 0000000..ba6bc80 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/JMSUniversalClientTest.html @@ -0,0 +1,122 @@ + + + + + +Uses of Class com.kaazing.client.universal.JMSUniversalClientTest + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.JMSUniversalClientTest

+
+
No usage of com.kaazing.client.universal.JMSUniversalClientTest
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/MessagesListener.html b/java/doc/com/kaazing/client/universal/class-use/MessagesListener.html new file mode 100644 index 0000000..2bf924f --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/MessagesListener.html @@ -0,0 +1,166 @@ + + + + + +Uses of Interface com.kaazing.client.universal.MessagesListener + + + + + + + + + + + +
+

Uses of Interface
com.kaazing.client.universal.MessagesListener

+
+
+ +
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/SubscriptionConnection.html b/java/doc/com/kaazing/client/universal/class-use/SubscriptionConnection.html new file mode 100644 index 0000000..ea6868b --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/SubscriptionConnection.html @@ -0,0 +1,122 @@ + + + + + +Uses of Class com.kaazing.client.universal.SubscriptionConnection + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.SubscriptionConnection

+
+
No usage of com.kaazing.client.universal.SubscriptionConnection
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/UniversalClient.html b/java/doc/com/kaazing/client/universal/class-use/UniversalClient.html new file mode 100644 index 0000000..de04950 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/UniversalClient.html @@ -0,0 +1,174 @@ + + + + + +Uses of Interface com.kaazing.client.universal.UniversalClient + + + + + + + + + + + +
+

Uses of Interface
com.kaazing.client.universal.UniversalClient

+
+
+ +
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/UniversalClientFactory.html b/java/doc/com/kaazing/client/universal/class-use/UniversalClientFactory.html new file mode 100644 index 0000000..1b93861 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/UniversalClientFactory.html @@ -0,0 +1,122 @@ + + + + + +Uses of Class com.kaazing.client.universal.UniversalClientFactory + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.UniversalClientFactory

+
+
No usage of com.kaazing.client.universal.UniversalClientFactory
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/UniversalClientProtocol.html b/java/doc/com/kaazing/client/universal/class-use/UniversalClientProtocol.html new file mode 100644 index 0000000..246d89b --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/UniversalClientProtocol.html @@ -0,0 +1,175 @@ + + + + + +Uses of Class com.kaazing.client.universal.UniversalClientProtocol + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.UniversalClientProtocol

+
+
+ +
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/class-use/Utils.html b/java/doc/com/kaazing/client/universal/class-use/Utils.html new file mode 100644 index 0000000..521c229 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/class-use/Utils.html @@ -0,0 +1,122 @@ + + + + + +Uses of Class com.kaazing.client.universal.Utils + + + + + + + + + + + +
+

Uses of Class
com.kaazing.client.universal.Utils

+
+
No usage of com.kaazing.client.universal.Utils
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/package-frame.html b/java/doc/com/kaazing/client/universal/package-frame.html new file mode 100644 index 0000000..7555b5c --- /dev/null +++ b/java/doc/com/kaazing/client/universal/package-frame.html @@ -0,0 +1,45 @@ + + + + + +com.kaazing.client.universal + + + + + +

com.kaazing.client.universal

+ + + diff --git a/java/doc/com/kaazing/client/universal/package-summary.html b/java/doc/com/kaazing/client/universal/package-summary.html new file mode 100644 index 0000000..35fcbf1 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/package-summary.html @@ -0,0 +1,261 @@ + + + + + +com.kaazing.client.universal + + + + + + + + + + + +
+

Package com.kaazing.client.universal

+
+
+ +
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/package-tree.html b/java/doc/com/kaazing/client/universal/package-tree.html new file mode 100644 index 0000000..06a2099 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/package-tree.html @@ -0,0 +1,176 @@ + + + + + +com.kaazing.client.universal Class Hierarchy + + + + + + + + + + + +
+

Hierarchy For Package com.kaazing.client.universal

+
+
+

Class Hierarchy

+ +

Interface Hierarchy

+ +

Enum Hierarchy

+
    +
  • java.lang.Object +
      +
    • java.lang.Enum<E> (implements java.lang.Comparable<T>, java.io.Serializable) + +
    • +
    +
  • +
+
+ + + + + + diff --git a/java/doc/com/kaazing/client/universal/package-use.html b/java/doc/com/kaazing/client/universal/package-use.html new file mode 100644 index 0000000..0290188 --- /dev/null +++ b/java/doc/com/kaazing/client/universal/package-use.html @@ -0,0 +1,165 @@ + + + + + +Uses of Package com.kaazing.client.universal + + + + + + + + + + + +
+

Uses of Package
com.kaazing.client.universal

+
+
+ +
+ + + + + + diff --git a/java/doc/constant-values.html b/java/doc/constant-values.html new file mode 100644 index 0000000..f6f7bb6 --- /dev/null +++ b/java/doc/constant-values.html @@ -0,0 +1,122 @@ + + + + + +Constant Field Values + + + + + + + + + + + +
+

Constant Field Values

+

Contents

+
+ + + + + + diff --git a/java/doc/deprecated-list.html b/java/doc/deprecated-list.html new file mode 100644 index 0000000..0b58968 --- /dev/null +++ b/java/doc/deprecated-list.html @@ -0,0 +1,122 @@ + + + + + +Deprecated List + + + + + + + + +
+ + + + + + + +
+ + +
+

Deprecated API

+

Contents

+
+ +
+ + + + + + + +
+ + + + diff --git a/java/doc/help-doc.html b/java/doc/help-doc.html new file mode 100644 index 0000000..2204d2f --- /dev/null +++ b/java/doc/help-doc.html @@ -0,0 +1,223 @@ + + + + + +API Help + + + + + + + + + + + +
+

How This API Document Is Organized

+
This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
+
+
+
    +
  • +

    Package

    +

    Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain six categories:

    +
      +
    • Interfaces (italic)
    • +
    • Classes
    • +
    • Enums
    • +
    • Exceptions
    • +
    • Errors
    • +
    • Annotation Types
    • +
    +
  • +
  • +

    Class/Interface

    +

    Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:

    +
      +
    • Class inheritance diagram
    • +
    • Direct Subclasses
    • +
    • All Known Subinterfaces
    • +
    • All Known Implementing Classes
    • +
    • Class/interface declaration
    • +
    • Class/interface description
    • +
    +
      +
    • Nested Class Summary
    • +
    • Field Summary
    • +
    • Constructor Summary
    • +
    • Method Summary
    • +
    +
      +
    • Field Detail
    • +
    • Constructor Detail
    • +
    • Method Detail
    • +
    +

    Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.

    +
  • +
  • +

    Annotation Type

    +

    Each annotation type has its own separate page with the following sections:

    +
      +
    • Annotation Type declaration
    • +
    • Annotation Type description
    • +
    • Required Element Summary
    • +
    • Optional Element Summary
    • +
    • Element Detail
    • +
    +
  • +
  • +

    Enum

    +

    Each enum has its own separate page with the following sections:

    +
      +
    • Enum declaration
    • +
    • Enum description
    • +
    • Enum Constant Summary
    • +
    • Enum Constant Detail
    • +
    +
  • +
  • +

    Use

    +

    Each documented package, class and interface has its own Use page. This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its Use page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A. You can access this page by first going to the package, class or interface, then clicking on the "Use" link in the navigation bar.

    +
  • +
  • +

    Tree (Class Hierarchy)

    +

    There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with java.lang.Object. The interfaces do not inherit from java.lang.Object.

    +
      +
    • When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
    • +
    • When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.
    • +
    +
  • +
  • +

    Deprecated API

    +

    The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.

    +
  • +
  • +

    Index

    +

    The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.

    +
  • +
  • +

    Prev/Next

    +

    These links take you to the next or previous class, interface, package, or related page.

    +
  • +
  • +

    Frames/No Frames

    +

    These links show and hide the HTML frames. All pages are available with or without frames.

    +
  • +
  • +

    All Classes

    +

    The All Classes link shows all classes and interfaces except non-static nested types.

    +
  • +
  • +

    Serialized Form

    +

    Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.

    +
  • +
  • +

    Constant Field Values

    +

    The Constant Field Values page lists the static final fields and their values.

    +
  • +
+This help file applies to API documentation generated using the standard doclet.
+ + + + + + diff --git a/java/doc/index-files/index-1.html b/java/doc/index-files/index-1.html new file mode 100644 index 0000000..9149da1 --- /dev/null +++ b/java/doc/index-files/index-1.html @@ -0,0 +1,149 @@ + + + + + +A-Index + + + + + + + + +
+ + + + + + + +
+ + +
A C D E G J M O S T U V  + + +

A

+
+
AmqpClientSubscription - Class in com.kaazing.client.universal
+
+
Contains information specific to AMQP subscriptions
+
+
AmqpClientSubscription(String, String, String, String, String, AmqpChannel, AmqpChannel) - Constructor for class com.kaazing.client.universal.AmqpClientSubscription
+
 
+
AmqpMessageEnvelope - Class in com.kaazing.client.universal
+
+
Adds the sender ID to the message so it can be used for noLocal filtering when it is not supported by the server
+
+
AmqpMessageEnvelope(String, Serializable) - Constructor for class com.kaazing.client.universal.AmqpMessageEnvelope
+
 
+
AmqpUniversalClient - Class in com.kaazing.client.universal
+
+
AMQP specific implmentation of Universal client
+
+
AmqpUniversalClient(URI, String, String, ErrorsListener) - Constructor for class com.kaazing.client.universal.AmqpUniversalClient
+
 
+
AmqpUniversalClientTest - Class in com.kaazing.client.universal
+
 
+
AmqpUniversalClientTest() - Constructor for class com.kaazing.client.universal.AmqpUniversalClientTest
+
 
+
AmqpUniversalClientTest.TestObject - Class in com.kaazing.client.universal
+
 
+
+A C D E G J M O S T U V 
+ +
+ + + + + + + +
+ + + + diff --git a/java/doc/index-files/index-10.html b/java/doc/index-files/index-10.html new file mode 100644 index 0000000..8a1ac5b --- /dev/null +++ b/java/doc/index-files/index-10.html @@ -0,0 +1,147 @@ + + + + + +T-Index + + + + + + + + +
+ + + + + + + +
+ + +
A C D E G J M O S T U V  + + +

T

+
+
testNoLocal() - Method in class com.kaazing.client.universal.AmqpUniversalClientTest
+
 
+
testNoLocal() - Method in class com.kaazing.client.universal.JMSUniversalClientTest
+
 
+
testObject() - Method in class com.kaazing.client.universal.AmqpUniversalClientTest
+
 
+
TestObject(int, String) - Constructor for class com.kaazing.client.universal.AmqpUniversalClientTest.TestObject
+
 
+
testObject() - Method in class com.kaazing.client.universal.JMSUniversalClientTest
+
 
+
TestObject(int, String) - Constructor for class com.kaazing.client.universal.JMSUniversalClientTest.TestObject
+
 
+
testString() - Method in class com.kaazing.client.universal.AmqpUniversalClientTest
+
 
+
testString() - Method in class com.kaazing.client.universal.JMSUniversalClientTest
+
 
+
toString() - Method in class com.kaazing.client.universal.AmqpMessageEnvelope
+
 
+
toString() - Method in class com.kaazing.client.universal.AmqpUniversalClientTest.TestObject
+
 
+
toString() - Method in class com.kaazing.client.universal.JMSUniversalClientTest.TestObject
+
 
+
+A C D E G J M O S T U V 
+ +
+ + + + + + + +
+ + + + diff --git a/java/doc/index-files/index-11.html b/java/doc/index-files/index-11.html new file mode 100644 index 0000000..14d6739 --- /dev/null +++ b/java/doc/index-files/index-11.html @@ -0,0 +1,141 @@ + + + + + +U-Index + + + + + + + + +
+ + + + + + + +
+ + +
A C D E G J M O S T U V  + + +

U

+
+
UniversalClient - Interface in com.kaazing.client.universal
+
+
Interface for Kaazing protocol independent universal client
+
+
UniversalClientFactory - Class in com.kaazing.client.universal
+
+
Factory to create an instance of Universal Client
+
+
UniversalClientProtocol - Enum in com.kaazing.client.universal
+
 
+
Utils - Class in com.kaazing.client.universal
+
+
Provides implementation of commonly used utils
+
+
Utils() - Constructor for class com.kaazing.client.universal.Utils
+
 
+
+A C D E G J M O S T U V 
+ +
+ + + + + + + +
+ + + + diff --git a/java/doc/index-files/index-12.html b/java/doc/index-files/index-12.html new file mode 100644 index 0000000..097b17f --- /dev/null +++ b/java/doc/index-files/index-12.html @@ -0,0 +1,134 @@ + + + + + +V-Index + + + + + + + + +
+ + + + + + + +
+ + +
A C D E G J M O S T U V  + + +

V

+
+
valueOf(String) - Static method in enum com.kaazing.client.universal.UniversalClientProtocol
+
+
Returns the enum constant of this type with the specified name.
+
+
values() - Static method in enum com.kaazing.client.universal.UniversalClientProtocol
+
+
Returns an array containing the constants of this enum type, in +the order they are declared.
+
+
+A C D E G J M O S T U V 
+ +
+ + + + + + + +
+ + + + diff --git a/java/doc/index-files/index-2.html b/java/doc/index-files/index-2.html new file mode 100644 index 0000000..3c45ce4 --- /dev/null +++ b/java/doc/index-files/index-2.html @@ -0,0 +1,153 @@ + + + + + +C-Index + + + + + + + + +
+ + + + + + + +
+ + +
A C D E G J M O S T U V  + + +

C

+
+
ClientException - Exception in com.kaazing.client.universal
+
+
Contains the exception reported by Universal Client
+
+
ClientException(String, Throwable) - Constructor for exception com.kaazing.client.universal.ClientException
+
 
+
ClientException(String) - Constructor for exception com.kaazing.client.universal.ClientException
+
 
+
ClientException(Throwable) - Constructor for exception com.kaazing.client.universal.ClientException
+
 
+
ClientSubscription - Class in com.kaazing.client.universal
+
+
Contains information about subscription
+
+
ClientSubscription(String) - Constructor for class com.kaazing.client.universal.ClientSubscription
+
+
Construct the subscription object.
+
+
close() - Method in class com.kaazing.client.universal.AmqpUniversalClient
+
 
+
close() - Method in class com.kaazing.client.universal.JMSUniversalClient
+
 
+
com.kaazing.client.universal - package com.kaazing.client.universal
+
 
+
createUniversalClient(UniversalClientProtocol, URI, String, String, ErrorsListener) - Static method in class com.kaazing.client.universal.UniversalClientFactory
+
+
Constructs an instance of Universal client specific to protocols
+
+
+A C D E G J M O S T U V 
+ +
+ + + + + + + +
+ + + + diff --git a/java/doc/index-files/index-3.html b/java/doc/index-files/index-3.html new file mode 100644 index 0000000..2a2a6a5 --- /dev/null +++ b/java/doc/index-files/index-3.html @@ -0,0 +1,137 @@ + + + + + +D-Index + + + + + + + + +
+ + + + + + + +
+ + +
A C D E G J M O S T U V  + + +

D

+
+
deserialize(byte[]) - Static method in class com.kaazing.client.universal.Utils
+
+
Deserializes the object from byte array
+
+
disconnect() - Method in class com.kaazing.client.universal.AmqpClientSubscription
+
 
+
disconnect() - Method in class com.kaazing.client.universal.ClientSubscription
+
+
Closes both publishing and subscription endpoints
+
+
disconnect() - Method in class com.kaazing.client.universal.JMSClientSubscription
+
 
+
+A C D E G J M O S T U V 
+ +
+ + + + + + + +
+ + + + diff --git a/java/doc/index-files/index-4.html b/java/doc/index-files/index-4.html new file mode 100644 index 0000000..813f777 --- /dev/null +++ b/java/doc/index-files/index-4.html @@ -0,0 +1,129 @@ + + + + + +E-Index + + + + + + + + +
+ + + + + + + +
+ + +
A C D E G J M O S T U V  + + +

E

+
+
ErrorsListener - Interface in com.kaazing.client.universal
+
+
Provides implementation for calback to handle the errors
+
+
+A C D E G J M O S T U V 
+ +
+ + + + + + + +
+ + + + diff --git a/java/doc/index-files/index-5.html b/java/doc/index-files/index-5.html new file mode 100644 index 0000000..62eb018 --- /dev/null +++ b/java/doc/index-files/index-5.html @@ -0,0 +1,133 @@ + + + + + +G-Index + + + + + + + + +
+ + + + + + + +
+ + +
A C D E G J M O S T U V  + + +

G

+
+
generateIdentifier(String, String, String) - Static method in class com.kaazing.client.universal.Utils
+
 
+
getClientId() - Method in class com.kaazing.client.universal.AmqpMessageEnvelope
+
 
+
getData() - Method in class com.kaazing.client.universal.AmqpMessageEnvelope
+
 
+
getSubscriptionIdentifier() - Method in class com.kaazing.client.universal.ClientSubscription
+
 
+
+A C D E G J M O S T U V 
+ +
+ + + + + + + +
+ + + + diff --git a/java/doc/index-files/index-6.html b/java/doc/index-files/index-6.html new file mode 100644 index 0000000..2fee8ff --- /dev/null +++ b/java/doc/index-files/index-6.html @@ -0,0 +1,143 @@ + + + + + +J-Index + + + + + + + + +
+ + + + + + + +
+ + +
A C D E G J M O S T U V  + + +

J

+
+
JMSClientSubscription - Class in com.kaazing.client.universal
+
+
Contains information specific to JMS subscriptions
+
+
JMSClientSubscription(String, String, Session, MessageProducer, MessageConsumer) - Constructor for class com.kaazing.client.universal.JMSClientSubscription
+
 
+
JMSUniversalClient - Class in com.kaazing.client.universal
+
+
JMS specific implementation of Universal Client
+
+
JMSUniversalClient(URI, String, String, ErrorsListener) - Constructor for class com.kaazing.client.universal.JMSUniversalClient
+
 
+
JMSUniversalClientTest - Class in com.kaazing.client.universal
+
 
+
JMSUniversalClientTest() - Constructor for class com.kaazing.client.universal.JMSUniversalClientTest
+
 
+
JMSUniversalClientTest.TestObject - Class in com.kaazing.client.universal
+
 
+
+A C D E G J M O S T U V 
+ +
+ + + + + + + +
+ + + + diff --git a/java/doc/index-files/index-7.html b/java/doc/index-files/index-7.html new file mode 100644 index 0000000..2bd93cb --- /dev/null +++ b/java/doc/index-files/index-7.html @@ -0,0 +1,129 @@ + + + + + +M-Index + + + + + + + + +
+ + + + + + + +
+ + +
A C D E G J M O S T U V  + + +

M

+
+
MessagesListener - Interface in com.kaazing.client.universal
+
+
Listener for the messages received by Universal Client
+
+
+A C D E G J M O S T U V 
+ +
+ + + + + + + +
+ + + + diff --git a/java/doc/index-files/index-8.html b/java/doc/index-files/index-8.html new file mode 100644 index 0000000..8f7d008 --- /dev/null +++ b/java/doc/index-files/index-8.html @@ -0,0 +1,135 @@ + + + + + +O-Index + + + + + + + + +
+ + + + + + + +
+ + +
A C D E G J M O S T U V  + + +

O

+
+
onException(ClientException) - Method in interface com.kaazing.client.universal.ErrorsListener
+
+
Called by the Universal Client when exception occurs
+
+
onException(JMSException) - Method in class com.kaazing.client.universal.JMSUniversalClient
+
 
+
onMessage(Serializable) - Method in interface com.kaazing.client.universal.MessagesListener
+
+
Called when message is received
+
+
+A C D E G J M O S T U V 
+ +
+ + + + + + + +
+ + + + diff --git a/java/doc/index-files/index-9.html b/java/doc/index-files/index-9.html new file mode 100644 index 0000000..b5938a2 --- /dev/null +++ b/java/doc/index-files/index-9.html @@ -0,0 +1,153 @@ + + + + + +S-Index + + + + + + + + +
+ + + + + + + +
+ + +
A C D E G J M O S T U V  + + +

S

+
+
sendMessage(Serializable) - Method in class com.kaazing.client.universal.AmqpClientSubscription
+
 
+
sendMessage(Serializable) - Method in class com.kaazing.client.universal.ClientSubscription
+
+
Sends the message over established subscription to the publishing point
+
+
sendMessage(Serializable) - Method in class com.kaazing.client.universal.JMSClientSubscription
+
 
+
serialize(Serializable) - Static method in class com.kaazing.client.universal.Utils
+
+
Serializes java object to bytes
+
+
setUp() - Method in class com.kaazing.client.universal.AmqpUniversalClientTest
+
 
+
setUp() - Method in class com.kaazing.client.universal.JMSUniversalClientTest
+
 
+
shutDown() - Method in class com.kaazing.client.universal.AmqpUniversalClientTest
+
 
+
shutDown() - Method in class com.kaazing.client.universal.JMSUniversalClientTest
+
 
+
subscribe(String, String, MessagesListener, boolean) - Method in class com.kaazing.client.universal.AmqpUniversalClient
+
 
+
subscribe(String, String, MessagesListener, boolean) - Method in class com.kaazing.client.universal.JMSUniversalClient
+
 
+
subscribe(String, String, MessagesListener, boolean) - Method in interface com.kaazing.client.universal.UniversalClient
+
+
Connects client to pub/sub endpoints
+
+
+A C D E G J M O S T U V 
+ +
+ + + + + + + +
+ + + + diff --git a/java/doc/index.html b/java/doc/index.html new file mode 100644 index 0000000..cfcd673 --- /dev/null +++ b/java/doc/index.html @@ -0,0 +1,71 @@ + + + + + +Generated Documentation (Untitled) + + + + + + +<noscript> +<div>JavaScript is disabled on your browser.</div> +</noscript> +<h2>Frame Alert</h2> +<p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="com/kaazing/client/universal/package-summary.html">Non-frame version</a>.</p> + + + diff --git a/java/doc/overview-tree.html b/java/doc/overview-tree.html new file mode 100644 index 0000000..88d95cc --- /dev/null +++ b/java/doc/overview-tree.html @@ -0,0 +1,180 @@ + + + + + +Class Hierarchy + + + + + + + + + + + +
+

Hierarchy For All Packages

+Package Hierarchies: + +
+
+

Class Hierarchy

+ +

Interface Hierarchy

+ +

Enum Hierarchy

+
    +
  • java.lang.Object +
      +
    • java.lang.Enum<E> (implements java.lang.Comparable<T>, java.io.Serializable) + +
    • +
    +
  • +
+
+ + + + + + diff --git a/java/doc/package-list b/java/doc/package-list new file mode 100644 index 0000000..748199e --- /dev/null +++ b/java/doc/package-list @@ -0,0 +1 @@ +com.kaazing.client.universal diff --git a/java/doc/script.js b/java/doc/script.js new file mode 100644 index 0000000..b346356 --- /dev/null +++ b/java/doc/script.js @@ -0,0 +1,30 @@ +function show(type) +{ + count = 0; + for (var key in methods) { + var row = document.getElementById(key); + if ((methods[key] & type) != 0) { + row.style.display = ''; + row.className = (count++ % 2) ? rowColor : altColor; + } + else + row.style.display = 'none'; + } + updateTabs(type); +} + +function updateTabs(type) +{ + for (var value in tabs) { + var sNode = document.getElementById(tabs[value][0]); + var spanNode = sNode.firstChild; + if (value == type) { + sNode.className = activeTableTab; + spanNode.innerHTML = tabs[value][1]; + } + else { + sNode.className = tableTab; + spanNode.innerHTML = "" + tabs[value][1] + ""; + } + } +} diff --git a/java/doc/serialized-form.html b/java/doc/serialized-form.html new file mode 100644 index 0000000..0742872 --- /dev/null +++ b/java/doc/serialized-form.html @@ -0,0 +1,211 @@ + + + + + +Serialized Form + + + + + + + + + + + +
+

Serialized Form

+
+
+ +
+ + + + + + diff --git a/java/doc/stylesheet.css b/java/doc/stylesheet.css new file mode 100644 index 0000000..98055b2 --- /dev/null +++ b/java/doc/stylesheet.css @@ -0,0 +1,574 @@ +/* Javadoc style sheet */ +/* +Overall document style +*/ + +@import url('resources/fonts/dejavu.css'); + +body { + background-color:#ffffff; + color:#353833; + font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; + font-size:14px; + margin:0; +} +a:link, a:visited { + text-decoration:none; + color:#4A6782; +} +a:hover, a:focus { + text-decoration:none; + color:#bb7a2a; +} +a:active { + text-decoration:none; + color:#4A6782; +} +a[name] { + color:#353833; +} +a[name]:hover { + text-decoration:none; + color:#353833; +} +pre { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; +} +h1 { + font-size:20px; +} +h2 { + font-size:18px; +} +h3 { + font-size:16px; + font-style:italic; +} +h4 { + font-size:13px; +} +h5 { + font-size:12px; +} +h6 { + font-size:11px; +} +ul { + list-style-type:disc; +} +code, tt { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + padding-top:4px; + margin-top:8px; + line-height:1.4em; +} +dt code { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + padding-top:4px; +} +table tr td dt code { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + vertical-align:top; + padding-top:4px; +} +sup { + font-size:8px; +} +/* +Document title and Copyright styles +*/ +.clear { + clear:both; + height:0px; + overflow:hidden; +} +.aboutLanguage { + float:right; + padding:0px 21px; + font-size:11px; + z-index:200; + margin-top:-9px; +} +.legalCopy { + margin-left:.5em; +} +.bar a, .bar a:link, .bar a:visited, .bar a:active { + color:#FFFFFF; + text-decoration:none; +} +.bar a:hover, .bar a:focus { + color:#bb7a2a; +} +.tab { + background-color:#0066FF; + color:#ffffff; + padding:8px; + width:5em; + font-weight:bold; +} +/* +Navigation bar styles +*/ +.bar { + background-color:#4D7A97; + color:#FFFFFF; + padding:.8em .5em .4em .8em; + height:auto;/*height:1.8em;*/ + font-size:11px; + margin:0; +} +.topNav { + background-color:#4D7A97; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; + font-size:12px; +} +.bottomNav { + margin-top:10px; + background-color:#4D7A97; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; + font-size:12px; +} +.subNav { + background-color:#dee3e9; + float:left; + width:100%; + overflow:hidden; + font-size:12px; +} +.subNav div { + clear:left; + float:left; + padding:0 0 5px 6px; + text-transform:uppercase; +} +ul.navList, ul.subNavList { + float:left; + margin:0 25px 0 0; + padding:0; +} +ul.navList li{ + list-style:none; + float:left; + padding: 5px 6px; + text-transform:uppercase; +} +ul.subNavList li{ + list-style:none; + float:left; +} +.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited { + color:#FFFFFF; + text-decoration:none; + text-transform:uppercase; +} +.topNav a:hover, .bottomNav a:hover { + text-decoration:none; + color:#bb7a2a; + text-transform:uppercase; +} +.navBarCell1Rev { + background-color:#F8981D; + color:#253441; + margin: auto 5px; +} +.skipNav { + position:absolute; + top:auto; + left:-9999px; + overflow:hidden; +} +/* +Page header and footer styles +*/ +.header, .footer { + clear:both; + margin:0 20px; + padding:5px 0 0 0; +} +.indexHeader { + margin:10px; + position:relative; +} +.indexHeader span{ + margin-right:15px; +} +.indexHeader h1 { + font-size:13px; +} +.title { + color:#2c4557; + margin:10px 0; +} +.subTitle { + margin:5px 0 0 0; +} +.header ul { + margin:0 0 15px 0; + padding:0; +} +.footer ul { + margin:20px 0 5px 0; +} +.header ul li, .footer ul li { + list-style:none; + font-size:13px; +} +/* +Heading styles +*/ +div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { + background-color:#dee3e9; + border:1px solid #d0d9e0; + margin:0 0 6px -8px; + padding:7px 5px; +} +ul.blockList ul.blockList ul.blockList li.blockList h3 { + background-color:#dee3e9; + border:1px solid #d0d9e0; + margin:0 0 6px -8px; + padding:7px 5px; +} +ul.blockList ul.blockList li.blockList h3 { + padding:0; + margin:15px 0; +} +ul.blockList li.blockList h2 { + padding:0px 0 20px 0; +} +/* +Page layout container styles +*/ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { + clear:both; + padding:10px 20px; + position:relative; +} +.indexContainer { + margin:10px; + position:relative; + font-size:12px; +} +.indexContainer h2 { + font-size:13px; + padding:0 0 3px 0; +} +.indexContainer ul { + margin:0; + padding:0; +} +.indexContainer ul li { + list-style:none; + padding-top:2px; +} +.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt { + font-size:12px; + font-weight:bold; + margin:10px 0 0 0; + color:#4E4E4E; +} +.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { + margin:5px 0 10px 0px; + font-size:14px; + font-family:'DejaVu Sans Mono',monospace; +} +.serializedFormContainer dl.nameValue dt { + margin-left:1px; + font-size:1.1em; + display:inline; + font-weight:bold; +} +.serializedFormContainer dl.nameValue dd { + margin:0 0 0 1px; + font-size:1.1em; + display:inline; +} +/* +List styles +*/ +ul.horizontal li { + display:inline; + font-size:0.9em; +} +ul.inheritance { + margin:0; + padding:0; +} +ul.inheritance li { + display:inline; + list-style:none; +} +ul.inheritance li ul.inheritance { + margin-left:15px; + padding-left:15px; + padding-top:1px; +} +ul.blockList, ul.blockListLast { + margin:10px 0 10px 0; + padding:0; +} +ul.blockList li.blockList, ul.blockListLast li.blockList { + list-style:none; + margin-bottom:15px; + line-height:1.4; +} +ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList { + padding:0px 20px 5px 10px; + border:1px solid #ededed; + background-color:#f8f8f8; +} +ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList { + padding:0 0 5px 8px; + background-color:#ffffff; + border:none; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockList { + margin-left:0; + padding-left:0; + padding-bottom:15px; + border:none; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast { + list-style:none; + border-bottom:none; + padding-bottom:0; +} +table tr td dl, table tr td dl dt, table tr td dl dd { + margin-top:0; + margin-bottom:1px; +} +/* +Table styles +*/ +.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary { + width:100%; + border-left:1px solid #EEE; + border-right:1px solid #EEE; + border-bottom:1px solid #EEE; +} +.overviewSummary, .memberSummary { + padding:0px; +} +.overviewSummary caption, .memberSummary caption, .typeSummary caption, +.useSummary caption, .constantsSummary caption, .deprecatedSummary caption { + position:relative; + text-align:left; + background-repeat:no-repeat; + color:#253441; + font-weight:bold; + clear:none; + overflow:hidden; + padding:0px; + padding-top:10px; + padding-left:1px; + margin:0px; + white-space:pre; +} +.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, +.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link, +.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, +.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, +.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active, +.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, +.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited { + color:#FFFFFF; +} +.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, +.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + padding-bottom:7px; + display:inline-block; + float:left; + background-color:#F8981D; + border: none; + height:16px; +} +.memberSummary caption span.activeTableTab span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + margin-right:3px; + display:inline-block; + float:left; + background-color:#F8981D; + height:16px; +} +.memberSummary caption span.tableTab span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + margin-right:3px; + display:inline-block; + float:left; + background-color:#4D7A97; + height:16px; +} +.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab { + padding-top:0px; + padding-left:0px; + padding-right:0px; + background-image:none; + float:none; + display:inline; +} +.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, +.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd { + display:none; + width:5px; + position:relative; + float:left; + background-color:#F8981D; +} +.memberSummary .activeTableTab .tabEnd { + display:none; + width:5px; + margin-right:3px; + position:relative; + float:left; + background-color:#F8981D; +} +.memberSummary .tableTab .tabEnd { + display:none; + width:5px; + margin-right:3px; + position:relative; + background-color:#4D7A97; + float:left; + +} +.overviewSummary td, .memberSummary td, .typeSummary td, +.useSummary td, .constantsSummary td, .deprecatedSummary td { + text-align:left; + padding:0px 0px 12px 10px; +} +th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th, +td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{ + vertical-align:top; + padding-right:0px; + padding-top:8px; + padding-bottom:3px; +} +th.colFirst, th.colLast, th.colOne, .constantsSummary th { + background:#dee3e9; + text-align:left; + padding:8px 3px 3px 7px; +} +td.colFirst, th.colFirst { + white-space:nowrap; + font-size:13px; +} +td.colLast, th.colLast { + font-size:13px; +} +td.colOne, th.colOne { + font-size:13px; +} +.overviewSummary td.colFirst, .overviewSummary th.colFirst, +.useSummary td.colFirst, .useSummary th.colFirst, +.overviewSummary td.colOne, .overviewSummary th.colOne, +.memberSummary td.colFirst, .memberSummary th.colFirst, +.memberSummary td.colOne, .memberSummary th.colOne, +.typeSummary td.colFirst{ + width:25%; + vertical-align:top; +} +td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { + font-weight:bold; +} +.tableSubHeadingColor { + background-color:#EEEEFF; +} +.altColor { + background-color:#FFFFFF; +} +.rowColor { + background-color:#EEEEEF; +} +/* +Content styles +*/ +.description pre { + margin-top:0; +} +.deprecatedContent { + margin:0; + padding:10px 0; +} +.docSummary { + padding:0; +} + +ul.blockList ul.blockList ul.blockList li.blockList h3 { + font-style:normal; +} + +div.block { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; +} + +td.colLast div { + padding-top:0px; +} + + +td.colLast a { + padding-bottom:3px; +} +/* +Formatting effect styles +*/ +.sourceLineNo { + color:green; + padding:0 30px 0 0; +} +h1.hidden { + visibility:hidden; + overflow:hidden; + font-size:10px; +} +.block { + display:block; + margin:3px 10px 2px 0px; + color:#474747; +} +.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, +.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, +.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink { + font-weight:bold; +} +.deprecationComment, .emphasizedPhrase, .interfaceName { + font-style:italic; +} + +div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase, +div.block div.block span.interfaceName { + font-style:normal; +} + +div.contentContainer ul.blockList li.blockList h2{ + padding-bottom:0px; +} diff --git a/java/images/JavaUniversalClient.png b/java/images/JavaUniversalClient.png new file mode 100644 index 0000000000000000000000000000000000000000..c7324d0119ddc204cc6c06430e3a2bb2d77a4e15 GIT binary patch literal 89843 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

*)(Z#MV!v+k6PKj}&LZmGt)uhd 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 literal 0 HcmV?d00001 diff --git a/java/src/main/java/com/kaazing/client/universal/AmqpClientSubscription.java b/java/src/main/java/com/kaazing/client/universal/AmqpClientSubscription.java index baee3d1..76df607 100644 --- a/java/src/main/java/com/kaazing/client/universal/AmqpClientSubscription.java +++ b/java/src/main/java/com/kaazing/client/universal/AmqpClientSubscription.java @@ -27,8 +27,8 @@ public class AmqpClientSubscription extends ClientSubscription { private String pubChannelName; private String queueName; - public AmqpClientSubscription(String connectionIdentifier, String appId, String userId, String pubChannelName, String queueName, AmqpChannel pubChannel, AmqpChannel subChannel) { - super(connectionIdentifier); + public AmqpClientSubscription(String subscriptionIdentifier, String appId, String userId, String pubChannelName, String queueName, AmqpChannel pubChannel, AmqpChannel subChannel) { + super(subscriptionIdentifier); this.pubChannel = pubChannel; this.subChannel = subChannel; this.pubChannelName = pubChannelName; @@ -44,7 +44,7 @@ public void sendMessage(Serializable message) throws ClientException { try { serializedObject = Utils.serialize(messageEnvelope); } catch (IOException e) { - throw new ClientException("Cannot serialize message " + message + " to send over connection " + this.getConnectionIdentifier(), e); + throw new ClientException("Cannot serialize message " + message + " to send over subscription " + this.getSubscriptionIdentifier(), e); } ByteBuffer buffer = ByteBuffer.allocate(serializedObject.length); buffer.put(serializedObject); @@ -61,7 +61,7 @@ public void sendMessage(Serializable message) throws ClientException { props.setTimestamp(ts); this.pubChannel.publishBasic(buffer, props, this.pubChannelName, AmqpUniversalClient.ROUTING_KEY, false, false); - AmqpUniversalClient.LOGGER.debug("Sent message [" + message.toString() + "] to connection to " + this.getConnectionIdentifier()); + AmqpUniversalClient.LOGGER.debug("Sent message [" + message.toString() + "] to subscription to " + this.getSubscriptionIdentifier()); } @Override diff --git a/java/src/main/java/com/kaazing/client/universal/AmqpUniversalClient.java b/java/src/main/java/com/kaazing/client/universal/AmqpUniversalClient.java index 65baec2..63da712 100644 --- a/java/src/main/java/com/kaazing/client/universal/AmqpUniversalClient.java +++ b/java/src/main/java/com/kaazing/client/universal/AmqpUniversalClient.java @@ -72,8 +72,8 @@ public void onConnectionClose(ConnectionEvent e) { try { conn.disconnect(); } catch (ClientException e1) { - errorsListener.onException(new ClientException("Error closing client connection: "+conn.getConnectionIdentifier(), e1)); - LOGGER.error("Error closing client connection: "+conn.getConnectionIdentifier(), e1); + errorsListener.onException(new ClientException("Error closing client connection: "+conn.getSubscriptionIdentifier(), e1)); + LOGGER.error("Error closing client connection: "+conn.getSubscriptionIdentifier(), e1); } } LOGGER.info("Closed connection to "+url+"."); @@ -107,7 +107,7 @@ public void close() throws Exception { } @Override - public ClientSubscription connect(String pubTopicName, String subTopicName, MessagesListener messageListener, boolean noLocal) throws ClientException { + public ClientSubscription subscribe(String pubTopicName, String subTopicName, MessagesListener messageListener, boolean noLocal) throws ClientException { CountDownLatch connectionsLatch = new CountDownLatch(2); AmqpChannel pubChannel = this.amqpClient.openChannel(); fPubOpened = false; @@ -185,10 +185,9 @@ public void onMessage(final ChannelEvent e) { @Override public void onOpen(ChannelEvent e) { - // TODO: decide on what to do with noLocal subChannel.declareQueue(queueName, false, false, false, false, false, null) - .bindQueue(queueName, subTopicName, ROUTING_KEY, false, null) - .consumeBasic(queueName, clientId, noLocal, false, false, false, null); + .bindQueue(queueName, subTopicName, ROUTING_KEY, false, null) + .consumeBasic(queueName, clientId, noLocal, false, false, false, null); } }); diff --git a/java/src/main/java/com/kaazing/client/universal/ClientSubscription.java b/java/src/main/java/com/kaazing/client/universal/ClientSubscription.java index 27824f4..8b0ccba 100644 --- a/java/src/main/java/com/kaazing/client/universal/ClientSubscription.java +++ b/java/src/main/java/com/kaazing/client/universal/ClientSubscription.java @@ -11,30 +11,30 @@ * */ public abstract class ClientSubscription { - private final String connectionIdentifier; + private final String subscriptionIdentifier; /** - * Construct the connection object. The constructor should be overwritten by the implementation classes. - * @param connectionIdentifier + * Construct the subscription object. The constructor should be overwritten by the implementation classes. + * @param subscriptionIdentifier Identification of the subscription that is automatically generated when subscription is created. */ - public ClientSubscription(String connectionIdentifier){ - this.connectionIdentifier=connectionIdentifier; + public ClientSubscription(String subscriptionIdentifier){ + this.subscriptionIdentifier=subscriptionIdentifier; } /** - * Sends the message over established connection to the publishing point + * Sends the message over established subscription to the publishing point * @param message message to send * @throws ClientException indicates that error occurred */ public abstract void sendMessage(Serializable message) throws ClientException; /** - * Closes connection to both publishing and subscription endpoints - * @throws ClientException + * Closes both publishing and subscription endpoints + * @throws ClientException indicates that error occurred */ public abstract void disconnect() throws ClientException; - public String getConnectionIdentifier() { - return connectionIdentifier; + public String getSubscriptionIdentifier() { + return subscriptionIdentifier; } } diff --git a/java/src/main/java/com/kaazing/client/universal/SubscriptionConnection.java b/java/src/main/java/com/kaazing/client/universal/JMSClientSubscription.java similarity index 52% rename from java/src/main/java/com/kaazing/client/universal/SubscriptionConnection.java rename to java/src/main/java/com/kaazing/client/universal/JMSClientSubscription.java index 631da6e..6b46d54 100644 --- a/java/src/main/java/com/kaazing/client/universal/SubscriptionConnection.java +++ b/java/src/main/java/com/kaazing/client/universal/JMSClientSubscription.java @@ -17,15 +17,15 @@ * @author romans * */ -public class SubscriptionConnection extends ClientSubscription { +public class JMSClientSubscription extends ClientSubscription { private final MessageProducer producer; private final MessageConsumer consumer; private boolean opened=true; private final Session session; private String clientId; - public SubscriptionConnection(String clientId, String connectionIdentifier, Session session, MessageProducer producer, MessageConsumer consumer) { - super(connectionIdentifier); + public JMSClientSubscription(String clientId, String subscriptionIdentifier, Session session, MessageProducer producer, MessageConsumer consumer) { + super(subscriptionIdentifier); this.producer=producer; this.consumer=consumer; this.session=session; @@ -38,27 +38,27 @@ public void sendMessage(Serializable message) throws ClientException { try { bytesMessage = session.createBytesMessage(); } catch (JMSException e) { - throw new ClientException("Connection: "+this.getConnectionIdentifier()+" - Cannot create a BytesMessage for an object " + message.toString(), e); + throw new ClientException("Subscription: "+this.getSubscriptionIdentifier()+" - Cannot create a BytesMessage for an object " + message.toString(), e); } try { bytesMessage.writeBytes(Utils.serialize(message)); } catch (JMSException e) { - throw new ClientException("Connection: "+this.getConnectionIdentifier()+" - Cannot write bytes to set the payload of a BytesMessage for an object " + message.toString(), e); + throw new ClientException("Subscription: "+this.getSubscriptionIdentifier()+" - Cannot write bytes to set the payload of a BytesMessage for an object " + message.toString(), e); } catch (IOException e) { - throw new ClientException("Connection: "+this.getConnectionIdentifier()+" - Cannot serialize an object " + message.toString(), e); + throw new ClientException("Subscription: "+this.getSubscriptionIdentifier()+" - Cannot serialize an object " + message.toString(), e); } if (clientId!=null){ try { bytesMessage.setStringProperty("clientId", clientId); } catch (JMSException e) { - throw new ClientException("Connection: "+this.getConnectionIdentifier()+" - Cannot set a string property client id to "+clientId+" for an object " + message.toString(), e); + throw new ClientException("Subscription: "+this.getSubscriptionIdentifier()+" - Cannot set a string property client id to "+clientId+" for an object " + message.toString(), e); } } try { producer.send(bytesMessage); - JMSUniversalClient.LOGGER.debug("Sent message ["+message.toString()+"] to connection to "+this.getConnectionIdentifier()); + JMSUniversalClient.LOGGER.debug("Sent message ["+message.toString()+"] to subscription to "+this.getSubscriptionIdentifier()); } catch (JMSException e) { - throw new ClientException("Connection: "+this.getConnectionIdentifier()+" - Cannot sent and object message for an object " + message.toString(), e); + throw new ClientException("Subscription: "+this.getSubscriptionIdentifier()+" - Cannot sent and object message for an object " + message.toString(), e); } } @@ -69,12 +69,12 @@ public void disconnect() throws ClientException { try { this.producer.close(); } catch (JMSException e) { - throw new ClientException("Connection: "+this.getConnectionIdentifier()+" - Error closing producer for connection "+this.getConnectionIdentifier(),e); + throw new ClientException("Subscription: "+this.getSubscriptionIdentifier()+" - Error closing producer.",e); } try { this.consumer.close(); } catch (JMSException e) { - throw new ClientException("Connection: "+this.getConnectionIdentifier()+" - Error closing consumer for connection "+this.getConnectionIdentifier(),e); + throw new ClientException("Subscription: "+this.getSubscriptionIdentifier()+" - Error closing consumer.",e); } opened=false; } diff --git a/java/src/main/java/com/kaazing/client/universal/JMSUniversalClient.java b/java/src/main/java/com/kaazing/client/universal/JMSUniversalClient.java index 9b38972..68bc078 100644 --- a/java/src/main/java/com/kaazing/client/universal/JMSUniversalClient.java +++ b/java/src/main/java/com/kaazing/client/universal/JMSUniversalClient.java @@ -44,7 +44,7 @@ public class JMSUniversalClient implements ExceptionListener, UniversalClient { private final ConnectionFactory connectionFactory; private Connection connection; private Session session; - private List connections=new ArrayList<>(); + private List connections=new ArrayList<>(); private String url; protected static Logger LOGGER=LoggerFactory.getLogger(JMSUniversalClient.class); @@ -97,7 +97,7 @@ public JMSUniversalClient(URI url, String login, String password, ErrorsListener * @see com.kaazing.client.universal.UniversalClientProtocolImpl#connect(java.lang.String, java.lang.String, com.kaazing.client.universal.MessagesListener, boolean) */ @Override - public ClientSubscription connect(String pubTopicName, String subTopicName, MessagesListener messageListener, boolean noLocal) throws ClientException { + public ClientSubscription subscribe(String pubTopicName, String subTopicName, MessagesListener messageListener, boolean noLocal) throws ClientException { String clientId=null; Destination subDestination; try { @@ -128,7 +128,7 @@ public ClientSubscription connect(String pubTopicName, String subTopicName, Mess try { pubDestination = (Destination) jndiInitialContext.lookup("/topic/" + pubTopicName); } catch (NamingException e) { - throw new ClientException("Cannot locate publicshing topic " + pubTopicName, e); + throw new ClientException("Cannot locate publishing topic " + pubTopicName, e); } MessageProducer producer; try { @@ -137,7 +137,7 @@ public ClientSubscription connect(String pubTopicName, String subTopicName, Mess throw new ClientException("Cannot create producer for publishing topic " + pubTopicName, e); } LOGGER.info("Connected to publishing topic "+pubTopicName+" for connection to "+this.url); - SubscriptionConnection clientConnection=new SubscriptionConnection(clientId, Utils.generateIdentifier(this.url, pubTopicName, subTopicName), this.session, producer, consumer); + JMSClientSubscription clientConnection=new JMSClientSubscription(clientId, Utils.generateIdentifier(this.url, pubTopicName, subTopicName), this.session, producer, consumer); this.connections.add(clientConnection); return clientConnection; } @@ -198,7 +198,7 @@ public void onMessage(Message message) { */ @Override public void close() throws Exception { - for(SubscriptionConnection connection: this.connections){ + for(JMSClientSubscription connection: this.connections){ connection.disconnect(); } this.connection.stop(); diff --git a/java/src/main/java/com/kaazing/client/universal/UniversalClient.java b/java/src/main/java/com/kaazing/client/universal/UniversalClient.java index 358efa6..cb36864 100644 --- a/java/src/main/java/com/kaazing/client/universal/UniversalClient.java +++ b/java/src/main/java/com/kaazing/client/universal/UniversalClient.java @@ -15,8 +15,8 @@ public interface UniversalClient extends AutoCloseable{ * @param subTopicName name of subscription topic * @param messageListener callback to receive messages * @param noLocal if true client will not receive its own messages (applicable only when pub and sub points are the same) - * @return connection information + * @return subscription information * @throws ClientException indicates that error occurred */ - public ClientSubscription connect(String pubTopicName, String subTopicName, MessagesListener messageListener, boolean noLocal) throws ClientException; + public ClientSubscription subscribe(String pubTopicName, String subTopicName, MessagesListener messageListener, boolean noLocal) throws ClientException; } \ No newline at end of file diff --git a/java/src/test/java/com/kaazing/client/universal/AmqpUniversalClientTest.java b/java/src/test/java/com/kaazing/client/universal/AmqpUniversalClientTest.java index 39293d3..7be1fd2 100644 --- a/java/src/test/java/com/kaazing/client/universal/AmqpUniversalClientTest.java +++ b/java/src/test/java/com/kaazing/client/universal/AmqpUniversalClientTest.java @@ -45,7 +45,7 @@ public void onException(ClientException exception) { @Test public void testString() throws ClientException, InterruptedException { - ClientSubscription connection = amqpClient.connect("test", "test", new MessagesListener() { + ClientSubscription connection = amqpClient.subscribe("test", "test", new MessagesListener() { @Override public void onMessage(Serializable message) { @@ -64,7 +64,7 @@ public void onMessage(Serializable message) { @Test public void testObject() throws ClientException, InterruptedException { - ClientSubscription connection = amqpClient.connect("test", "test", new MessagesListener() { + ClientSubscription connection = amqpClient.subscribe("test", "test", new MessagesListener() { @Override public void onMessage(Serializable message) { @@ -82,7 +82,7 @@ public void onMessage(Serializable message) { @Test public void testNoLocal() throws ClientException, InterruptedException { - ClientSubscription connection = amqpClient.connect("test", "test", new MessagesListener() { + ClientSubscription connection = amqpClient.subscribe("test", "test", new MessagesListener() { @Override public void onMessage(Serializable message) { diff --git a/java/src/test/java/com/kaazing/client/universal/JMSUniversalClientTest.java b/java/src/test/java/com/kaazing/client/universal/JMSUniversalClientTest.java index 09b61ad..0ef0096 100644 --- a/java/src/test/java/com/kaazing/client/universal/JMSUniversalClientTest.java +++ b/java/src/test/java/com/kaazing/client/universal/JMSUniversalClientTest.java @@ -45,7 +45,7 @@ public void onException(ClientException exception) { @Test public void testString() throws ClientException, InterruptedException { - ClientSubscription connection = jmsClient.connect("test", "test", new MessagesListener() { + ClientSubscription connection = jmsClient.subscribe("test", "test", new MessagesListener() { @Override public void onMessage(Serializable message) { @@ -64,7 +64,7 @@ public void onMessage(Serializable message) { @Test public void testObject() throws ClientException, InterruptedException { - ClientSubscription connection = jmsClient.connect("test", "test", new MessagesListener() { + ClientSubscription connection = jmsClient.subscribe("test", "test", new MessagesListener() { @Override public void onMessage(Serializable message) { @@ -83,7 +83,7 @@ public void onMessage(Serializable message) { @Test public void testNoLocal() throws ClientException, InterruptedException { - ClientSubscription connection = jmsClient.connect("test", "test", new MessagesListener() { + ClientSubscription connection = jmsClient.subscribe("test", "test", new MessagesListener() { @Override public void onMessage(Serializable message) { diff --git a/javascript/JavaScriptClient.md b/javascript/JavaScriptClient.md index 2332c9b..a5274d7 100644 --- a/javascript/JavaScriptClient.md +++ b/javascript/JavaScriptClient.md @@ -1,5 +1,5 @@ # Kaazing JavaScript Universal Client for Javascript -This library is intended to be used with 'plain JavaScript' application; it provides JavaScript function that returns an object that can be used in the client application to interact with Kaazing Gateway. +This library is intended to be used with 'plain JavaScript', AngularJS, ReactJS applications (see [Kaazing JavaScript Starter Applications](https://github.com/kaazing/javascript.getting.started) and [Kaazing Examples and Tutorials](https://github.com/kaazing/tutorials)); it provides JavaScript function that returns an object that can be used in the client application to interact with Kaazing Gateway. ## Using the Library ### Install the library @@ -45,7 +45,7 @@ This library is intended to be used with 'plain JavaScript' application; it prov Where: - **protocol**: Specifies protocol that should be used for communications: jms - for communication with Kaazing JMS Gateway, amqp - for communication with Kaazing AMQP Gateway. -- Establish a connection within your controller +- Establish a connection ```javascript ... @@ -53,120 +53,85 @@ This library is intended to be used with 'plain JavaScript' application; it prov ... $(document).ready(function () { - client.connect(url, username, password, topicP, topicS, noLocal, messageDestinationFuncHandle,loggerFuncHandle); - - ... + client.connect(connectionInfo, // Connection info + onError, // callback function to process errors + function(connection){ + ... + } } ``` Where: - - **url**: Connection URL (e.g. ws://localhost:8001/amqp or ws://localhost:8001/jms) - - **username**: User name to be used to establish connection - - **password**: User password to be used to establish connection - - **topicP**: Name of the publishing endpoint - AMQP exchange used for publishing or JMS Topic - - **topicS**: Name of the subscription endpoint - AMQP exchange used for subscription or JMS Topic - - **noLocal**: Flag indicating whether the client wants to receive its own messages (true) or not (false). That flag should be used when publishing and subscription endpoints are the same. - - **messageDestinationFuncHandle**: Function that will be used to process received messages from subscription endpoint in a format: _function(messageBody)_ - - **errorFuncHandle**: function that is used for error handling in a format of _function(error)_ - - **loggerFuncHandle**: function that is used for logging events in a format of _function(severity, message)_ - - **connectFunctionHandle**: function this is called when connection is established in a format: _function()_ -- Add disconnect on window close (shown method uses JQuery): + - **coonectionInfo**: Connection information that contains _URL_ (e.g. ws://localhost:8001/amqp or ws://localhost:8001/jms), _username_(user name to be used to establish connection) and _password_(user password to be used to establish connection) + - **onError**: function that is used for error handling in a format of _function(error)_. + - _callback function_ to receive a connection object once connection is established. + + **Note:** If you want to add a logger to log library messages, add the following after creating the client: ```javascript - ... - - var client=UniversalClientDef(protocol); - ... - - $(document).ready(function () { - client.connect(url, username, password, topicP, topicS, noLocal, messageDestinationFuncHandle, errorFuncHandle, loggerFuncHandle, connectFunctionHandle); - - ... - $( window ).unload(function() { - // Disconnect - client.disconnect(); - }); - + + var logWebSocketMessage = function (cls, msg) { + ... } - - ``` -- To send messages use sendMessage(msg) method - where _**msg**_ is message to be sent. If _**msg**_ is not a string it will be converted to JSON. Be sure to send the message only after the connection has been successfully initialized (the connectFunctionHandle() callback is an ideal place for it). - ```javascript - ... - var client=UniversalClientDef(protocol); - ... + // Set the logger function + client.loggerFuncHandle=logWebSocketMessage; - var sendMessage=function(msg){ - // Send message - client.sendMessage(msg); - } - - - $(document).ready(function () { - client.connect(url, username, password, topicP, topicS, noLocal, messageDestinationFuncHandle, errorFuncHandle, loggerFuncHandle, connectFunctionHandle); - - ... - $( window ).unload(function() { - // Disconnect - client.disconnect(); - }); - - } ``` -- When message is received, service will call a function registered as **messageDestinationFuncHandle** as shown above. E.g. - +- Subscribe to the topics of interest ```javascript ... var client=UniversalClientDef(protocol); ... - var sendMessage=function(msg){ - // Send message - client.sendMessage(msg); - } - - var processReceivedCommand=function(cmd){ - // Process received message - } - $(document).ready(function () { - client.connect(url, username, password, topicP, topicS, noLocal, processReceivedCommand,errorFuncHandle, loggerFuncHandle, connectFunctionHandle); - - ... - $( window ).unload(function() { - // Disconnect - client.disconnect(); - }); + var subscription; + client.connect(connectionInfo, // Connection info + onError, // callback function to process errors + function(connection){ + connection.subscribe(topicP, // Topic to send message + topicS, // Topic to subscribe to receive messsages + onMessage, // callback function to process received messages + noLocal, // noLocal flag set to false - allow receiving your own messages + function(subscription){ + subscription=subscr; + }); + } + } } - - ``` -- To handle WebSocket errors, specify the function **errorFuncHandle** or pass _null_ if not needed. E.g.: + + ``` + + Where: + - **topicP**: Name of the publishing endpoint - AMQP exchange used for publishing or JMS Topic + - **topicS**: Name of the subscription endpoint - AMQP exchange used for subscription or JMS Topic + - **noLocal**: Flag indicating whether the client wants to receive its own messages (true) or not (false). That flag should be used when publishing and subscription endpoints are the same. + - **onMessage**: Function that will be used to process received messages from subscription endpoint in a format of _function(message)_ + - _callback function_ to receive subscription object + **Note** Multiple subscriptions are allowed within single connection! +- Add disconnect on window close (shown method uses JQuery): ```javascript ... var client=UniversalClientDef(protocol); ... - var sendMessage=function(msg){ - // Send message - client.sendMessage(msg); - } - - var processReceivedCommand=function(cmd){ - // Process received message - } - - var handleWebSocketError = function (error) { - // Habdle WebSocket error - } - $(document).ready(function () { - client.connect(url, username, password, topicP, topicS, noLocal, processReceivedCommand,handleWebSocketError, loggerFuncHandle, connectFunctionHandle); - + var subscription; + client.connect(connectionInfo, // Connection info + onError, // callback function to process errors + function(connection){ + connection.subscribe(topicP, // Topic to send message + topicS, // Topic to subscribe to receive messsages + onMessage, // callback function to process received message + noLocal, // noLocal flag set to false - allow receiving your own messages + function(subscription){ + subscription=subscr; + }); + } + } ... $( window ).unload(function() { // Disconnect @@ -174,45 +139,10 @@ This library is intended to be used with 'plain JavaScript' application; it prov }); } - ``` - -- To log WebSocket related events, specify the function **loggerFuncHandle** or pass null if not needed. E.g.: - ```javascript - ... - - var client=UniversalClientDef(protocol); - ... - - var sendMessage=function(msg){ - // Send message - client.sendMessage(msg); - } - - var processReceivedCommand=function(cmd){ - // Process received message - } - - var handleWebSocketError = function (error) { - // Habdle WebSocket error - } - - var logWebSocketMessage = function (cls, msg) { - // Log WebSocket messages - } - - $(document).ready(function () { - client.connect(url, username, password, topicP, topicS, noLocal, processReceivedCommand,handleWebSocketError, logWebSocketMessage, connectFunctionHandle); - - ... - $( window ).unload(function() { - // Disconnect - client.disconnect(); - }); - } ``` - -- To perform post-connect initalizations, specify the function **connectFunctionHandle** or pass null if not needed. E.g.: +- To send messages use sendMessage(msg) method of a subscription object + where _**msg**_ JavaScript object to be sent (as a JSON string). ```javascript ... @@ -221,29 +151,24 @@ This library is intended to be used with 'plain JavaScript' application; it prov var sendMessage=function(msg){ // Send message - client.sendMessage(msg); - } - - var processReceivedCommand=function(cmd){ - // Process received message - } - - var handleWebSocketError = function (error) { - // Habdle WebSocket error - } - - var logWebSocketMessage = function (cls, msg) { - // Log WebSocket messages - } - - var onWebSocketConnected = function () { - // Do some post-connect initialization + subscrpiption.sendMessage(msg); } $(document).ready(function () { - client.connect(url, username, password, topicP, topicS, noLocal, processReceivedCommand,handleWebSocketError, logWebSocketMessage, onWebSocketConnected); - + var subscription; + client.connect(connectionInfo, // Connection info + onError, // callback function to process errors + function(connection){ + connection.subscribe(topicP, // Topic to send message + topicS, // Topic to subscribe to receive messsages + onMessage, // callback function to process received message + noLocal, // noLocal flag set to false - allow receiving your own messages + function(subscription){ + subscription=subscr; + }); + } + } ... $( window ).unload(function() { // Disconnect @@ -252,6 +177,7 @@ This library is intended to be used with 'plain JavaScript' application; it prov } ``` + ## Organization of Kaazing JavaScript Universal Client ![][image-1] diff --git a/javascript/KaazingJMSClientLibrariesFacade.md b/javascript/KaazingJMSClientLibrariesFacade.md index 90ce881..e867982 100644 --- a/javascript/KaazingJMSClientLibrariesFacade.md +++ b/javascript/KaazingJMSClientLibrariesFacade.md @@ -1,28 +1,31 @@ # Kaazing Javascript JMS Client Libraries Facade +Kaazing JavaScript JMS Client Libraries Facade simplifies the interaction with Kaazing JavaScript JMS Client libraries that enable the developers to interact with [JMS](http://docs.oracle.com/javaee/6/tutorial/doc/bncdx.html) brokers via WebSockets. + Kaazing JavaScript JMS Client Libraries Facade: * Implements basic publish-subscribe functionality for JMS to help developers in getting started with their JMS WebSocket projects -* Provide developers with the reference implementations for using Kaazing AMQP JavaScript client libraries +* Provide developers with the reference implementations for using Kaazing JMS JavaScript client libraries For more information see: -- [Build JavaScript JMS Clients Using Kaazing WebSocket Gateway - JMS Edition](http://developer.kaazing.com/documentation/jms/4.0/dev-js/o_dev_js.html) -- [Use the Kaazing WebSocket Gateway JavaScript JMS Client API](http://developer.kaazing.com/documentation/jms/4.0/dev-js/p_dev_js_client.html) +- [Build JavaScript JMS Clients Using Kaazing WebSocket Gateway - JMS Edition](http://kaazing.com/doc/jms/4.0/dev-js/o_dev_js.html) +- [Use the Kaazing WebSocket Gateway JavaScript JMS Client API](http://kaazing.com/doc/jms/4.0/dev-js/p_dev_js_client.html) ## Organization of the library -Library consists of jmsClientFunction that creates JMSClient object. JMSClient objects provides the following functionality: -- **connect** function - connects client to Kaazing WebSocket JMS gateway, creates publishing endpoint and subscribes to a subscription endpoint -- **disconnect** function - disconnects client from Kaazing WebSocket JMS gateway -- **sendMessage** function - sends the message to a publishing endpoint +- **connect** function - connects client to Kaazing WebSocket JMS gateway and on success returns via callback a _connection_ object that will be used to create subscriptions. +- ** subscribe ** method of a _connection_ object that creates publishing endpoint and subscribes to a subscription endpoint. Method returns via callback a _subscription_ object that is used for sending messages. +- **sendMessage** method of a _subscription_ object - sends the message to a publishing endpoint +- **disconnect** function of a _subscription_ object - closes both publishing and subscription. +- **close** method - closes all subscriptions and disconnects client from Kaazing WebSocket AMQP gateway ### **connect** function Connect function implements the following sequence: -1. Create JMS connection factory +- Create JMS connection factory ```javascript var jmsConnectionFactory = new JmsConnectionFactory(url); ``` -2. Create connection. createConnection function of JmsConnectionFactory takes three parameters: login, password and a callback function that will be called upon completion. Function returns the future that is checked in a callback function for exceptions. +- Create connection. createConnection function of JmsConnectionFactory takes three parameters: login, password and a callback function that will be called upon completion. Function returns the future that is checked in a callback function for exceptions. ```javascript var connectionFuture = jmsConnectionFactory.createConnection(username, password, function () { @@ -48,13 +51,13 @@ Connect function implements the following sequence: }) ``` -3. Once connection is created, callback function does the following: + Once connection is created, callback function does the following: 1. Obtains the connection from the connectionFuture that was returned by createConection. 2. Sets exception listener to handle exceptions. 3. Creates session using createSession method. Session is created with auto-acknowledgement. 4. Starts the connection using start function passing to it a callback function. -4. Once connection is started, connection object is returned for the subscription to be created using __subscribe__ method. +- Once connection is started, connection object is returned for the subscription to be created using __subscribe__ method. ### **subscribe** method of connection object Method executed the following actions: @@ -104,7 +107,7 @@ Function creates text message and sends it. In order to prevent client from rece } ``` -### **close** function of a subscription object +### **disconnect** function of a subscription object Function closes producer and consumer that were created during the subscription call. ```javascript @@ -114,8 +117,8 @@ Function closes producer and consumer that were created during the subscription }) ``` -### **disconnect** function -Closes all subscriptions (causing closing of their producer and consumer), session and connection in a chain of callbacks. +### **close** function +Closes all subscriptions (causing closing of their producer and consumer), stops the connection and then closes session and connection in a chain of callbacks. ```javascript JMSClient.disconnect=function(){ @@ -125,11 +128,13 @@ Closes all subscriptions (causing closing of their producer and consumer), sessi ... Wait while all the subscriptions are closed... - session.close(function () { - connection.close(function () { + connection.stop(function(){ + session.close(function () { + connection.close(function () { + }); + }); }); - }); } ``` diff --git a/javascript/README.md b/javascript/README.md index 797086d..47a40e9 100644 --- a/javascript/README.md +++ b/javascript/README.md @@ -1,7 +1,7 @@ # Universal Clients for JavaScript Applications The [Kaazing JavaScript WebSocket Universal Clients][2] library that can be also used with AngularJS, ReactJS and so on. -Both implementation use the same underlying [JavaScript AMQP Client Libraries Facade][3] and [JavaScript JMS Client Libraries Facade][4] scripts for interaction with Kaazing AMQP and JMS client libraries. +The library uses [JavaScript AMQP Client Libraries Facade][3] and [JavaScript JMS Client Libraries Facade][4] scripts for interaction with Kaazing AMQP and JMS client libraries. Please, refer to the links above for the details about the details of the usage and implementations. ## Using the Client Libraries @@ -10,13 +10,14 @@ Please, refer to the links above for the details about the details of the usage - Install NodeJS - please refer to the [NodeJS downloads page][9] for the installer that is appropriate for your OS - Update npm `sudo npm update npm -g` -- Install bower: + +- Install bower `sudo npm install -g bower` -- Install Kaazing Universal Javascript client libraries +- Install Kaazing Universal Javascript client libraries `bower install kaazing-javascript-univeral-client` -__Note__: If you used prior versions of the library you may want to clean bower cache by running: +__Note__: If you used prior versions of the library you may want to clean bower cache by running: `bower cache clean` #### Using the library @@ -36,11 +37,11 @@ Add the following to your main html page (index.html): - Install NodeJS - please refer to the [NodeJS downloads page][9] for the installer that is appropriate for your OS - Update npm `sudo npm update npm -g` -- Install RequireJS libraries +- Install RequireJS libraries `npm install requirejs` -- Install jQuery libraries - `npm install requirejs` -- Install Kaazing Universal Javascript client libraries +- Install jQuery libraries + `npm install requirejs` +- Install Kaazing Universal Javascript client libraries `npm install kaazing-javascript-universal-client` #### Using the library diff --git a/javascript/src/AmqpUniversalClient.js b/javascript/src/AmqpUniversalClient.js index fdca848..d8ab13f 100644 --- a/javascript/src/AmqpUniversalClient.js +++ b/javascript/src/AmqpUniversalClient.js @@ -211,6 +211,21 @@ var amqpClientFunction=function(logInformation){ props.setUserId(this.user); logInformation("sent","Sending message to "+this.topicPub+": "+ msg, "sent"); this.publishChannel.publishBasic({body: body, properties: props, exchange: this.topicPub, routingKey: routingKey}); + }, + disconnect:function(){ + var config = { + replyCode: 0, + replyText, '', + classId: 0, + methodId: 0 + }; + this.consumeChannel.deleteQueue({queue:this.queueName, ifEmpty: false}, function(){ + this.consumeChannel.closeChannel(config, function(){ + this.publishChannel.closeChannel(config, function(){ + + }); + }); + }); } }; return SubscriptionObject; @@ -286,7 +301,7 @@ var amqpClientFunction=function(logInformation){ /** * Disconnects from Kaazing WebSocket AMQP Gateway */ - AmqpClient.disconnect=function(){ + AmqpClient.close=function(){ amqpClient.disconnect(); } diff --git a/javascript/src/JMSUniversalClient.js b/javascript/src/JMSUniversalClient.js index 9b6984c..8792668 100644 --- a/javascript/src/JMSUniversalClient.js +++ b/javascript/src/JMSUniversalClient.js @@ -91,7 +91,7 @@ var jmsClientFunction=function(logInformation){ /** * Closes the subscrpiption and releases all the resources. */ - close:function(){ + disconnect:function(){ if (this.subscribed){ this.closed.resolve(); } @@ -216,14 +216,16 @@ var jmsClientFunction=function(logInformation){ /** * Disconnects from Kaazing WebSocket JMS Gateway, closes all the subscription and releases all the resources. */ - JMSClient.disconnect=function(){ + JMSClient.close=function(){ for(var i=0;i Date: Mon, 14 Mar 2016 18:17:29 -0700 Subject: [PATCH 5/9] Update KaazingAMQPClientLibrariesFacade.md --- java/KaazingAMQPClientLibrariesFacade.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/java/KaazingAMQPClientLibrariesFacade.md b/java/KaazingAMQPClientLibrariesFacade.md index 9ed218d..54f46f6 100644 --- a/java/KaazingAMQPClientLibrariesFacade.md +++ b/java/KaazingAMQPClientLibrariesFacade.md @@ -154,17 +154,19 @@ Method executed the following actions: } }); ``` - Once the channel is successfully opened, onOpen event listener will be call where we: - - declare a new queue - - bind the queue to an exchange with 'broadcast' routing key - - start basic consumer for the queue. - **Note** For fanout exchanges routing key is not used. For more information about exchanges and routing keys see: [https://www.rabbitmq.com/tutorials/amqp-concepts.html](https://www.rabbitmq.com/tutorials/amqp-concepts.html). + +Once the channel is successfully opened, onOpen event listener will be called where we: + - declare a new queue + - bind the queue to an exchange with 'broadcast' routing key + - start basic consumer for the queue. + **Note** For fanout exchanges routing key is not used. For more information about exchanges and routing keys see: [https://www.rabbitmq.com/tutorials/amqp-concepts.html](https://www.rabbitmq.com/tutorials/amqp-concepts.html). - Once consumer is started, onConsumeBasic event listener is called which is an indication that channel is successfully opened. onError listener is triggered in an event of any error. We use the countdown latch to wait for either of these events. - onMessage event listener is called every time we will receive a message from an exchange. In this method we: - - Allocates the buffer and read the data from the event body that contains serialized object. - - Deserialize the object and make sure it an instance of our AmqpMessageEnvelope. The reason to use an envelope it contains application identifier that is used for messages filtering for the AMQP brokers that do not support noLocal functionality (functionality that prevents the client to received its own messages when publishing and subscription endpoints are the same). - - calls onMessage method of MessagesListener object passing it received object. +Once consumer is started, onConsumeBasic event listener is called which is an indication that channel is successfully opened. onError listener is triggered in an event of any error. We use the countdown latch to wait for either of these events. +onMessage event listener is called every time we will receive a message from an exchange. In this method we: + - Allocates the buffer and read the data from the event body that contains serialized object. + - Deserialize the object and make sure it an instance of our AmqpMessageEnvelope. The reason to use an envelope it contains application identifier that is used for messages filtering for the AMQP brokers that do not support noLocal functionality (functionality that prevents the client to received its own messages when publishing and subscription endpoints are the same). + - calls onMessage method of MessagesListener object passing it received object. + ```java byte[] bytes = new byte[e.getBody().remaining()]; e.getBody().get(bytes); From 95119531e506b1d21bdfe7f6d93b65b277af241b Mon Sep 17 00:00:00 2001 From: Roman Smolgovsky Date: Mon, 14 Mar 2016 18:20:02 -0700 Subject: [PATCH 6/9] Update KaazingAMQPClientLibrariesFacade.md --- java/KaazingAMQPClientLibrariesFacade.md | 60 +++++++++++++++--------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/java/KaazingAMQPClientLibrariesFacade.md b/java/KaazingAMQPClientLibrariesFacade.md index 54f46f6..df07263 100644 --- a/java/KaazingAMQPClientLibrariesFacade.md +++ b/java/KaazingAMQPClientLibrariesFacade.md @@ -24,12 +24,12 @@ Connect function implements the following sequence: - Create AMQP client factory and AMQP client - ```java +```java amqpClientFactory = AmqpClientFactory.createAmqpClientFactory(); amqpClient = amqpClientFactory.createAmqpClient(); - ``` +``` - Register connection listeners - ```java +```java ... amqpClient.addConnectionListener(new ConnectionListener() { @@ -66,10 +66,12 @@ Connect function implements the following sequence: } }); - ``` + ... +``` We use onConnectionOpen and onConnectionError listeners to wait until connection is either established or failed; we use the countdown latch to wait for either of these events. - Establish connection using provided login and password - ```java +```java + ... amqpClient.connect(this.url, "/", login, password); try { latch.await(10, TimeUnit.SECONDS); @@ -79,13 +81,16 @@ Connect function implements the following sequence: if (!fConnected) { throw new ClientException("Connection to " + this.url + " was not established in 10 sec."); } - ``` + ... +``` ### **subscribe** method of of AmqpUniversalClient object Method executed the following actions: - Opens publishing channel ```java + ... AmqpChannel pubChannel = this.amqpClient.openChannel(); + ... ``` - Adds publishing channel listeners ```java @@ -122,9 +127,11 @@ Method executed the following actions: ```java ... AmqpChannel subChannel = this.amqpClient.openChannel(); + ... ``` - Registers subscription channel events listeners: ```java + ... subChannel.addChannelListener(new ChannelAdapter() { @Override public void onError(final ChannelEvent e) { @@ -153,6 +160,7 @@ Method executed the following actions: .consumeBasic(queueName, clientId, noLocal, false, false, false, null); } }); + ... ``` Once the channel is successfully opened, onOpen event listener will be called where we: @@ -168,27 +176,31 @@ onMessage event listener is called every time we will receive a message from an - calls onMessage method of MessagesListener object passing it received object. ```java + ... byte[] bytes = new byte[e.getBody().remaining()]; e.getBody().get(bytes); - try { - Serializable object=Utils.deserialize(bytes); - if (!(object instanceof AmqpMessageEnvelope)){ - errorsListener.onException(new ClientException("Received object is not an instance of AmqpMessageEnvelope; received from " + subTopicName)); - LOGGER.error("Received object is not an instance of AmqpMessageEnvelope; received from " + subTopicName +" for url"+url); - return; - } - AmqpMessageEnvelope messageEnvelope=(AmqpMessageEnvelope)object; - if (noLocal && messageEnvelope.getClientId().equals(appId)){ - LOGGER.debug("Received message ["+messageEnvelope.toString()+"] on topic "+subTopicName+", connection to "+url+" is ignored as it came from the same client and noLocal is set!"); - return; + try + { + Serializable object=Utils.deserialize(bytes); + if (!(object instanceof AmqpMessageEnvelope)){ + errorsListener.onException(new ClientException("Received object is not an instance of AmqpMessageEnvelope; received from " + subTopicName)); + LOGGER.error("Received object is not an instance of AmqpMessageEnvelope; received from " + subTopicName +" for url"+url); + return; } - LOGGER.debug("Received message ["+messageEnvelope.getData().toString()+"] on topic "+subTopicName+", connection to "+url); - messageListener.onMessage(messageEnvelope.getData()); - } catch (ClassNotFoundException | IOException e1) { - errorsListener.onException(new ClientException("Cannot deserialize an object from the message received from " + subTopicName, e1)); - LOGGER.error("Cannot deserialize an object from the message received from " + subTopicName +" for url"+url); + AmqpMessageEnvelope messageEnvelope=(AmqpMessageEnvelope)object; + if (noLocal && messageEnvelope.getClientId().equals(appId)){ + LOGGER.debug("Received message ["+messageEnvelope.toString()+"] on topic "+subTopicName+", connection to "+url+" is ignored as it came from the same client and noLocal is set!"); return; + } + LOGGER.debug("Received message ["+messageEnvelope.getData().toString()+"] on topic "+subTopicName+", connection to "+url); + messageListener.onMessage(messageEnvelope.getData()); + } + catch (ClassNotFoundException | IOException e1) { + errorsListener.onException(new ClientException("Cannot deserialize an object from the message received from " + subTopicName, e1)); + LOGGER.error("Cannot deserialize an object from the message received from " + subTopicName +" for url"+url); + return; } + ... ``` Once the channels are opened, they are stored in an AmqpClientSubscription object (subclass of ClientSubscription object) for future use. Created instance of ClientSubscription object is registered with AmqpUniversalClient. @@ -223,15 +235,18 @@ Serialized object is stored in the ByteBuffer that is sent to the channel along props.setTimestamp(ts); this.pubChannel.publishBasic(buffer, props, this.pubChannelName, AmqpUniversalClient.ROUTING_KEY, false, false); + ... ``` ### **disconnect** method of AmqpClientSubscription object Deletes the declared subscription queue and closes the channels ```java + ... this.subChannel.deleteQueue(this.queueName, false, false, false); this.pubChannel.closeChannel(0, "", 0, 0); this.subChannel.closeChannel(0, "", 0, 0); + ... ``` ### **close** method of AmqpUniversalClient object @@ -242,6 +257,7 @@ Disconnects all opened subscriptions, disconnects Amqp client. conn.disconnect(); } this.amqpClient.disconnect(); + ... ``` From 92cd091a1ba88aecaa1485dbe66922eadae5b2da Mon Sep 17 00:00:00 2001 From: Roman Smolgovsky Date: Mon, 14 Mar 2016 18:24:10 -0700 Subject: [PATCH 7/9] Update KaazingJMSClientLibrariesFacade.md --- java/KaazingJMSClientLibrariesFacade.md | 111 +++++++++++++----------- 1 file changed, 58 insertions(+), 53 deletions(-) diff --git a/java/KaazingJMSClientLibrariesFacade.md b/java/KaazingJMSClientLibrariesFacade.md index 964a8cc..710cfe6 100644 --- a/java/KaazingJMSClientLibrariesFacade.md +++ b/java/KaazingJMSClientLibrariesFacade.md @@ -23,7 +23,7 @@ Constructor implements the following sequence: - Locate JMS connection factory using JNDI: - ```java +```java Properties env = new Properties(); env.setProperty("java.naming.factory.initial", "com.kaazing.gateway.jms.client.JmsInitialContextFactory"); @@ -39,13 +39,13 @@ Constructor implements the following sequence: throw new ClientException("Error locating connection factory for JMS!", e); } JmsConnectionFactory jmsConnectionFactory = (JmsConnectionFactory) connectionFactory; - ``` +``` - Create connection. To create connection: - Set the gateway URL connection for JMS connection factory. - Create WebSocket factory - Create connection passing login and password: - ```java +```java ... jmsConnectionFactory.setGatewayLocation(url); WebSocketFactory webSocketFactory = jmsConnectionFactory.getWebSocketFactory(); @@ -56,9 +56,9 @@ Constructor implements the following sequence: throw new ClientException("Error connecting to gateway with " + url.toString() + ", credentials " + login + "/" + password, e); } ... - ``` +``` - Register the ErrorsListener object that is passed to the constructor with the connection to be a listener for any errors and exceptions: - ```java +```java ... try { connection.setExceptionListener(this); @@ -66,28 +66,30 @@ Constructor implements the following sequence: throw new ClientException("Error setting exceptions listener. Connection: " + url.toString() + ", credentials " + login + "/" + password, e); } ... - ``` +``` - Create __session__ in auto-acknowledgement mode. In this mode session automatically acknowledges a client's receipt of a message either when the session has successfully returned from a call to receive or when the message listener the session has called to process the message successfully returns. - ```java +```java ... - try - { + try { session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); } catch (JMSException e) { throw new ClientException("Error creating session. Connection: " + url.toString() + ", credentials " + login + "/" + password, e); } ... - ``` +``` - Start the connection - ```java - try - { - connection.start(); - } catch (JMSException e) { - throw new ClientException("Error starting connection: " + url.toString() + ", credentials " + login + "/" + password, e); +```java + ... + try { + connection.start(); + } + catch (JMSException e) { + throw new ClientException("Error starting connection: " + url.toString() + ", credentials " + login + "/" + password, e); } - ``` + ... +``` + Once object is successfully constructed it is ready to create subscriptions. @@ -96,21 +98,22 @@ Method executed the following actions: - Creates subscription destination - ```java +```java + ... Destination subDestination; try { subDestination = (Destination) jndiInitialContext.lookup("/topic/" + subTopicName); } catch (NamingException e) { throw new ClientException("Cannot locate subscription topic " + subTopicName, e); } - ``` + ... +``` - Creates message Consumer. _In order to prevent client from receiving its own messages consumer may be created with the query that will filter out the messages with the 'appId' string property set to this client application ID - a randomly generated GUID._ - ```java +```java ... MessageConsumer consumer; try { - if (noLocal){ clientId=UUID.randomUUID().toString(); consumer = session.createConsumer(subDestination, "clientId<>'"+clientId+"'"); @@ -121,9 +124,9 @@ Method executed the following actions: throw new ClientException("Cannot create consumer for subscription topic " + subTopicName, e); } ... - ``` +``` - Registers an instance of ... passed to the method to be a message listener. - ```java +```java ... try { @@ -132,41 +135,42 @@ Method executed the following actions: throw new ClientException("Cannot create messages listener for subscription topic " + subTopicName, e); } ... - ``` +``` We use MessageLinstenerImpl wrapper class that implements MessageListener to convert the ByteMessage object received from the wire to an instance of Serializable object that was sent. - ```java +```java ... if (message instanceof BytesMessage) { - try { - BytesMessage bytesMessage = ((BytesMessage) message); - long len = bytesMessage.getBodyLength(); - byte b[] = new byte[(int) len]; - bytesMessage.readBytes(b); - Serializable object; - try { - object = Utils.deserialize(b); - LOGGER.debug("Received message ["+object.toString()+"] on topic "+destination+", connection to "+url); - this.listener.onMessage(object); - } catch (ClassNotFoundException | IOException e) { - this.errorsListener.onException(new ClientException("Cannot deserialize an object from the message received from " + destination, e)); - LOGGER.error("Cannot deserialize an object from the message received from " + destination+" connection to "+url, e); - return; - } - - } catch (JMSException e) { - this.errorsListener.onException(new ClientException("Error receiving message from destination " + destination, e)); - LOGGER.error("Error receiving message from destination " + destination+" connection to "+url, e); - } - } else { - this.errorsListener.onException(new ClientException("Received a message of unexpected type " + message.getClass().getName() + " for a destination " + destination)); - LOGGER.error("Received a message of unexpected type " + message.getClass().getName() + destination+" connection to "+url); + try { + BytesMessage bytesMessage = ((BytesMessage) message); + long len = bytesMessage.getBodyLength(); + byte b[] = new byte[(int) len]; + bytesMessage.readBytes(b); + Serializable object; + try { + object = Utils.deserialize(b); + LOGGER.debug("Received message ["+object.toString()+"] on topic "+destination+", connection to "+url); + this.listener.onMessage(object); + } catch (ClassNotFoundException | IOException e) { + this.errorsListener.onException(new ClientException("Cannot deserialize an object from the message received from " + destination, e)); + LOGGER.error("Cannot deserialize an object from the message received from " + destination+" connection to "+url, e); + return; } - ... - ``` + } catch (JMSException e) { + this.errorsListener.onException(new ClientException("Error receiving message from destination " + destination, e)); + LOGGER.error("Error receiving message from destination " + destination+" connection to "+url, e); + } + } else { + this.errorsListener.onException(new ClientException("Received a message of unexpected type " + message.getClass().getName() + " for a destination " + destination)); + LOGGER.error("Received a message of unexpected type " + message.getClass().getName() + destination+" connection to "+url); + } + ... +``` - Create publishing destination and producer - ```java + +```java + ... Destination pubDestination; try { pubDestination = (Destination) jndiInitialContext.lookup("/topic/" + pubTopicName); @@ -179,7 +183,8 @@ Method executed the following actions: } catch (JMSException e) { throw new ClientException("Cannot create producer for publishing topic " + pubTopicName, e); } - ``` + ... +``` Session, producer and consumer are stored in an JMSClientSubscription object (subclass of ClientSubscription object) for future use. Created instance of ClientSubscription object is registered with JMSUniversalClient. @@ -250,4 +255,4 @@ Disconnects all opened subscriptions, closes session and connection. this.connection.stop(); this.session.close(); this.connection.close(); -``` \ No newline at end of file +``` From 5c6322ea2e4e418e47b2710239f636357a0ab8c5 Mon Sep 17 00:00:00 2001 From: Roman Smolgovsky Date: Mon, 14 Mar 2016 22:00:19 -0700 Subject: [PATCH 8/9] Fixed closing method. --- javascript/src/AmqpUniversalClient.js | 49 +++++++++++++------ javascript/src/JMSUniversalClient.js | 24 +++++---- javascript/src/JavascriptUniversalClient.js | 4 +- .../src/JavascriptUniversalClientNPM.js | 4 +- 4 files changed, 53 insertions(+), 28 deletions(-) diff --git a/javascript/src/AmqpUniversalClient.js b/javascript/src/AmqpUniversalClient.js index d8ab13f..158b8d1 100644 --- a/javascript/src/AmqpUniversalClient.js +++ b/javascript/src/AmqpUniversalClient.js @@ -32,7 +32,7 @@ var amqpClientFunction=function(logInformation){ * Provides communication services with AMQP server. Created within amqpClientFunction constructor. * @class */ - var AmqpClient = {}; + var AmqpClient = {subscriptions:[]}; var errorFunction=null; var amqpClient=null; @@ -89,7 +89,9 @@ var amqpClientFunction=function(logInformation){ clientId:null, messageIdCounter:0, user:user, + closed:null, messageReceivedFunc:messageReceivedFunc, + subscribed:false, init:function(subscribedCallback){ this.queueName="client" + Math.floor(Math.random() * 1000000); this.clientId=appId; @@ -101,6 +103,8 @@ var amqpClientFunction=function(logInformation){ logInformation("INFO", "OPEN: Consume Channel"); this.consumeChannel = amqpClient.openChannel(function(){that.consumeChannelOpenHandler(that)}); $.when(this.publishChannelOpened, this.consumeChannelOpened).done(function(){ + that.closed=$.Deferred(); + that.subscribed=true; subscribedCallback(that); }); @@ -213,31 +217,38 @@ var amqpClientFunction=function(logInformation){ this.publishChannel.publishBasic({body: body, properties: props, exchange: this.topicPub, routingKey: routingKey}); }, disconnect:function(){ - var config = { - replyCode: 0, - replyText, '', - classId: 0, - methodId: 0 - }; - this.consumeChannel.deleteQueue({queue:this.queueName, ifEmpty: false}, function(){ - this.consumeChannel.closeChannel(config, function(){ - this.publishChannel.closeChannel(config, function(){ - + if (!this.subscribed){ + this.closed.resolve(); + } + else{ + this.subscribed=false; + var config = { + replyCode: 0, + replyText: '', + classId: 0, + methodId: 0 + }; + this.consumeChannel.deleteQueue({queue:this.queueName, ifEmpty: false}, function(){ + this.consumeChannel.closeChannel(config, function(){ + this.publishChannel.closeChannel(config, function(){ + this.closed.resolve(); + }); }); }); - }); + } } }; return SubscriptionObject; } - var createConnectionObject=function(amqpClient, user){ + var createConnectionObject=function(connection, amqpClient, user){ /** * Contains infomration about established connection. * @class */ var ConnectionObject = { + connection:connection, user:user, amqpClient:amqpClient, /** @@ -251,7 +262,9 @@ var amqpClientFunction=function(logInformation){ subscribe:function(topicPub, topicSub, messageReceivedFunc, noLocal, subscribedCallbackFunction){ logInformation("INFO","CONNECTED!!!"); var subscription=createSubscriptionObject(this.amqpClient, topicPub, topicSub, noLocal, messageReceivedFunc, this.user); + var that=this; subscription.init(function(subscription){ + that.connection.subscriptions.push(subscription); subscribedCallbackFunction(subscription); }); } @@ -288,8 +301,9 @@ var amqpClientFunction=function(logInformation){ credentials: credentials }; try{ + var that=this; amqpClient.connect(options, function(){ - var connection=createConnectionObject(amqpClient,connectionInfo.username); + var connection=createConnectionObject(that, amqpClient,connectionInfo.username); connectedFunctionHandle(connection); }); } @@ -302,7 +316,12 @@ var amqpClientFunction=function(logInformation){ * Disconnects from Kaazing WebSocket AMQP Gateway */ AmqpClient.close=function(){ - amqpClient.disconnect(); + for(var i=0;iSource: AmqpUniversalClient.js * Provides communication services with AMQP server. Created within amqpClientFunction constructor. * @class */ - var AmqpClient = {}; + var AmqpClient = {subscriptions:[]}; var errorFunction=null; var amqpClient=null; @@ -117,7 +117,9 @@

Source: AmqpUniversalClient.js

clientId:null, messageIdCounter:0, user:user, + closed:null, messageReceivedFunc:messageReceivedFunc, + subscribed:false, init:function(subscribedCallback){ this.queueName="client" + Math.floor(Math.random() * 1000000); this.clientId=appId; @@ -129,6 +131,8 @@

Source: AmqpUniversalClient.js

logInformation("INFO", "OPEN: Consume Channel"); this.consumeChannel = amqpClient.openChannel(function(){that.consumeChannelOpenHandler(that)}); $.when(this.publishChannelOpened, this.consumeChannelOpened).done(function(){ + that.closed=$.Deferred(); + that.subscribed=true; subscribedCallback(that); }); @@ -239,18 +243,40 @@

Source: AmqpUniversalClient.js

props.setUserId(this.user); logInformation("sent","Sending message to "+this.topicPub+": "+ msg, "sent"); this.publishChannel.publishBasic({body: body, properties: props, exchange: this.topicPub, routingKey: routingKey}); + }, + disconnect:function(){ + if (!this.subscribed){ + this.closed.resolve(); + } + else{ + this.subscribed=false; + var config = { + replyCode: 0, + replyText: '', + classId: 0, + methodId: 0 + }; + this.consumeChannel.deleteQueue({queue:this.queueName, ifEmpty: false}, function(){ + this.consumeChannel.closeChannel(config, function(){ + this.publishChannel.closeChannel(config, function(){ + this.closed.resolve(); + }); + }); + }); + } } }; return SubscriptionObject; } - var createConnectionObject=function(amqpClient, user){ + var createConnectionObject=function(connection, amqpClient, user){ /** * Contains infomration about established connection. * @class */ var ConnectionObject = { + connection:connection, user:user, amqpClient:amqpClient, /** @@ -264,7 +290,9 @@

Source: AmqpUniversalClient.js

subscribe:function(topicPub, topicSub, messageReceivedFunc, noLocal, subscribedCallbackFunction){ logInformation("INFO","CONNECTED!!!"); var subscription=createSubscriptionObject(this.amqpClient, topicPub, topicSub, noLocal, messageReceivedFunc, this.user); + var that=this; subscription.init(function(subscription){ + that.connection.subscriptions.push(subscription); subscribedCallbackFunction(subscription); }); } @@ -301,8 +329,9 @@

Source: AmqpUniversalClient.js

credentials: credentials }; try{ + var that=this; amqpClient.connect(options, function(){ - var connection=createConnectionObject(amqpClient,connectionInfo.username); + var connection=createConnectionObject(that, amqpClient,connectionInfo.username); connectedFunctionHandle(connection); }); } @@ -314,8 +343,13 @@

Source: AmqpUniversalClient.js

/** * Disconnects from Kaazing WebSocket AMQP Gateway */ - AmqpClient.disconnect=function(){ - amqpClient.disconnect(); + AmqpClient.close=function(){ + for(var i=0;i<this.subscriptions.length;i++){ + this.subscriptions[i].disconnect(); + } + $.when.apply($,this.subscriptions).then(function() { + amqpClient.disconnect(); + }); } return AmqpClient; @@ -336,7 +370,7 @@

Home

Classes

  • diff --git a/javascript/jsdoc/JMSUniversalClient.js.html b/javascript/jsdoc/JMSUniversalClient.js.html index d9f1fd7..0280e2e 100644 --- a/javascript/jsdoc/JMSUniversalClient.js.html +++ b/javascript/jsdoc/JMSUniversalClient.js.html @@ -68,7 +68,7 @@

    Source: JMSUniversalClient.js

    noLocal:noLocal, messagesToSend:[], inSend:false, - subscribed:false, + subscribed:true, closed:$.Deferred(), sendMessageOverTheWire:function(){ var msg = this.messagesToSend.pop(); @@ -119,17 +119,16 @@

    Source: JMSUniversalClient.js

    /** * Closes the subscrpiption and releases all the resources. */ - close:function(){ - if (this.subscribed){ + disconnect:function(){ + if (!this.subscribed){ this.closed.resolve(); } else{ - this.producer.close(function(){ - this.consumer.close(function(){ - this.subscribed=false; - this.closed.resolve(); - }); - }) + this.producer.close(); + this.consumer.close(function(){ + this.subscribed=false; + this.closed.resolve(); + }); } } }; @@ -155,6 +154,13 @@

    Source: JMSUniversalClient.js

    * @param subscribedCallbackFunction {function} callback function if a format function(SubcriptionObject) to be called when SubsriptionObject is created. */ subscribe:function(topicPub, topicSub, messageReceivedFunc, noLocal, subscribedCallbackFunction){ + if (!topicPub.startsWith("/topic/")){ + topicPub="/topic/"+topicPub; + } + if (!topicSub.startsWith("/topic/")){ + topicSub="/topic/"+topicSub; + } + var pubDest = this.session.createTopic(topicPub); var producer = this.session.createProducer(pubDest); logInformation("INFO","Producer for "+topicPub+" is ready! AppID=" + appId); @@ -244,14 +250,16 @@

    Source: JMSUniversalClient.js

    /** * Disconnects from Kaazing WebSocket JMS Gateway, closes all the subscription and releases all the resources. */ - JMSClient.disconnect=function(){ + JMSClient.close=function(){ for(var i=0;i<this.subscriptions.length;i++){ - this.subscriptions[i].close(); + this.subscriptions[i].disconnect(); } $.when.apply($,this.subscriptions).then(function() { - session.close(function () { - connection.close(function () { + connection.stop(function(){ + session.close(function () { + connection.close(function () { + }); }); }); }); @@ -275,7 +283,7 @@

    Home

    Classes

    • diff --git a/javascript/jsdoc/JavascriptUniversalClient.js.html b/javascript/jsdoc/JavascriptUniversalClient.js.html index ef03ca0..d072f8a 100644 --- a/javascript/jsdoc/JavascriptUniversalClient.js.html +++ b/javascript/jsdoc/JavascriptUniversalClient.js.html @@ -113,8 +113,8 @@

      Source: JavascriptUniversalClient.js

      /** * Disconnects from Kaazing WebSocket Gateway */ - JavascriptUniversalClient.disconnect=function(){ - client.disconnect(); + JavascriptUniversalClient.close=function(){ + client.close(); } return JavascriptUniversalClient; @@ -136,7 +136,7 @@

      Home

      Classes

      • diff --git a/javascript/jsdoc/JavascriptUniversalClientNPM.js.html b/javascript/jsdoc/JavascriptUniversalClientNPM.js.html index 5364582..778cb04 100644 --- a/javascript/jsdoc/JavascriptUniversalClientNPM.js.html +++ b/javascript/jsdoc/JavascriptUniversalClientNPM.js.html @@ -116,8 +116,8 @@

        Source: JavascriptUniversalClientNPM.js

        /** * Disconnects from Kaazing WebSocket Gateway */ - JavascriptUniversalClient.disconnect=function(){ - client.disconnect(); + JavascriptUniversalClient.close=function(){ + client.close(); } return JavascriptUniversalClient; @@ -139,7 +139,7 @@

        Home

        Classes

        • diff --git a/javascript/jsdoc/UniversalClientDef-JavascriptUniversalClient.html b/javascript/jsdoc/UniversalClientDef-JavascriptUniversalClient.html index 63210d7..29b75bb 100644 --- a/javascript/jsdoc/UniversalClientDef-JavascriptUniversalClient.html +++ b/javascript/jsdoc/UniversalClientDef-JavascriptUniversalClient.html @@ -141,14 +141,14 @@

          Methods

          -

          (static) connect(connectionInfo, errorFuncHandle, connectFunctionHandle)

          +

          (static) close()

          - Connects to Kaazing WebSocket Gateway (AMQP or JMS) + Disconnects from Kaazing WebSocket Gateway
          @@ -159,99 +159,86 @@

          (static) conn -

          Parameters:
          + + + + +
          + - - - - - - + - + - + - + - - - + - - - - - + - + - + - + +
          Source:
          +
          + - - + - - - - + + + + + - - - - - - - - - - - - + - - + + +

          (static) close()

          - -
          NameTypeDescription
          connectionInfo - - -ConnectionInfo + + - - Connection info object that should contain url, username and password properties
          errorFuncHandle - - -function - - function that is used for error handling in a format of function(error)
          connectFunctionHandle - - -function - - function this is called when connection is established in a format: function(ConnectionObject).
          + + + +
          + Disconnects from Kaazing WebSocket Gateway +
          + + + + + + + @@ -287,7 +274,7 @@
          Parameters:
          Source:
          @@ -464,7 +451,7 @@
          Parameters:
          Source:
          @@ -495,14 +482,14 @@
          Parameters:
          -

          (static) disconnect()

          +

          (static) connect(connectionInfo, errorFuncHandle, connectFunctionHandle)

          - Disconnects from Kaazing WebSocket Gateway + Connects to Kaazing WebSocket Gateway (AMQP or JMS)
          @@ -513,86 +500,99 @@

          (static) d - - - - -
          - - - +
          Parameters:
          - + + + + + + - + - + - + - + + + + - + + + + - + - -
          Source:
          -
          - + - + - + + - - - - - - - - - - - - + + + + + - - + -

          (static) disconnect()

          + + + + + + - -
          - Disconnects from Kaazing WebSocket Gateway -
          - + + + + + + + +
          NameTypeDescription
          connectionInfo + + +ConnectionInfo - - + + Connection info object that should contain url, username and password properties
          errorFuncHandle + + +function + + function that is used for error handling in a format of function(error)
          connectFunctionHandle + + +function + + function this is called when connection is established in a format: function(ConnectionObject).
          @@ -628,7 +628,7 @@

          (static) d
          Source:
          @@ -1039,14 +1039,14 @@

          Methods

          -

          (static) connect(connectionInfo, errorFuncHandle, connectFunctionHandle)

          +

          (static) close()

          - Connects to Kaazing WebSocket Gateway (AMQP or JMS) + Disconnects from Kaazing WebSocket Gateway
          @@ -1057,99 +1057,86 @@

          (static) conn -

          Parameters:
          + + + + +
          + - - - - - - + - + - + - + - - - + - - - - - + - + - + - + +
          Source:
          +
          + - - + - - - - + + + + + - - - - - - - - - - - - + - - + + +

          (static) close()

          - -
          NameTypeDescription
          connectionInfo - - -ConnectionInfo + + - - Connection info object that should contain url, username and password properties
          errorFuncHandle - - -function - - function that is used for error handling in a format of function(error)
          connectFunctionHandle - - -function - - function this is called when connection is established in a format: function(ConnectionObject).
          + + + +
          + Disconnects from Kaazing WebSocket Gateway +
          + + + + + + + @@ -1185,7 +1172,7 @@
          Parameters:
          Source:
          @@ -1362,7 +1349,7 @@
          Parameters:
          Source:
          @@ -1393,14 +1380,14 @@
          Parameters:
          -

          (static) disconnect()

          +

          (static) connect(connectionInfo, errorFuncHandle, connectFunctionHandle)

          - Disconnects from Kaazing WebSocket Gateway + Connects to Kaazing WebSocket Gateway (AMQP or JMS)
          @@ -1411,86 +1398,99 @@

          (static) d - - - - -
          - - - +
          Parameters:
          - + + + + + + - + - + - + - + + + + - + + + + - + - -
          Source:
          -
          - + - + - + + - - - - - - - - - - - - + + + + + - - + -

          (static) disconnect()

          + + + + + + - -
          - Disconnects from Kaazing WebSocket Gateway -
          - + + + + + + + +
          NameTypeDescription
          connectionInfo + + +ConnectionInfo - - + + Connection info object that should contain url, username and password properties
          errorFuncHandle + + +function + + function that is used for error handling in a format of function(error)
          connectFunctionHandle + + +function + + function this is called when connection is established in a format: function(ConnectionObject).
          @@ -1526,7 +1526,7 @@

          (static) d
          Source:
          @@ -1826,7 +1826,7 @@

          Home

          Classes

          • diff --git a/javascript/jsdoc/amqpClientFunction-AmqpClient.html b/javascript/jsdoc/amqpClientFunction-AmqpClient.html index 56747df..4b09813 100644 --- a/javascript/jsdoc/amqpClientFunction-AmqpClient.html +++ b/javascript/jsdoc/amqpClientFunction-AmqpClient.html @@ -140,6 +140,88 @@

            Methods

            + +

            (static) close()

            + + + + + +
            + Disconnects from Kaazing WebSocket AMQP Gateway +
            + + + + + + + + + + + + + +
            + + + + + + + + + + + + + + + + + + + + + + + + + + +
            Source:
            +
            + + + + + + + +
            + + + + + + + + + + + + + + + + + + + +

            (static) connect(connectionInfo, errorFuncHandle, connectFunctionHandle)

            @@ -287,89 +369,7 @@
            Parameters:
            Source:
            - - - - - - - -
          - - - - - - - - - - - - - - - - - - - - - -

          (static) disconnect()

          - - - - - -
          - Disconnects from Kaazing WebSocket AMQP Gateway -
          - - - - - - - - - - - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - -
          Source:
          -
          @@ -417,7 +417,7 @@

          Home

          Classes

          • diff --git a/javascript/jsdoc/amqpClientFunction-createConnectionObject-ConnectionObject.html b/javascript/jsdoc/amqpClientFunction-createConnectionObject-ConnectionObject.html index 4b3fe34..c200556 100644 --- a/javascript/jsdoc/amqpClientFunction-createConnectionObject-ConnectionObject.html +++ b/javascript/jsdoc/amqpClientFunction-createConnectionObject-ConnectionObject.html @@ -91,7 +91,7 @@

            new C
            Source:
            @@ -332,7 +332,7 @@

            Parameters:
            Source:
            @@ -380,7 +380,7 @@

            Home

            Classes

            • diff --git a/javascript/jsdoc/amqpClientFunction-createSubscriptionObject-SubscriptionObject.html b/javascript/jsdoc/amqpClientFunction-createSubscriptionObject-SubscriptionObject.html index 661e997..b0b561c 100644 --- a/javascript/jsdoc/amqpClientFunction-createSubscriptionObject-SubscriptionObject.html +++ b/javascript/jsdoc/amqpClientFunction-createSubscriptionObject-SubscriptionObject.html @@ -235,7 +235,7 @@
              Parameters:
              Source:
              @@ -283,7 +283,7 @@

              Home

              Classes

              • diff --git a/javascript/jsdoc/global.html b/javascript/jsdoc/global.html index 99691ee..5949c3c 100644 --- a/javascript/jsdoc/global.html +++ b/javascript/jsdoc/global.html @@ -710,7 +710,7 @@

                Home

                Classes

                • diff --git a/javascript/jsdoc/index.html b/javascript/jsdoc/index.html index a2ea300..ab7fa68 100644 --- a/javascript/jsdoc/index.html +++ b/javascript/jsdoc/index.html @@ -56,7 +56,7 @@

                  Home

                  Classes

                  • diff --git a/javascript/jsdoc/jmsClientFunction-JMSClient.html b/javascript/jsdoc/jmsClientFunction-JMSClient.html index 6a7c4d7..e822e9d 100644 --- a/javascript/jsdoc/jmsClientFunction-JMSClient.html +++ b/javascript/jsdoc/jmsClientFunction-JMSClient.html @@ -140,6 +140,88 @@

                    Methods

                    + +

                    (static) close()

                    + + + + + +
                    + Disconnects from Kaazing WebSocket JMS Gateway, closes all the subscription and releases all the resources. +
                    + + + + + + + + + + + + + +
                    + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    Source:
                    +
                    + + + + + + + +
                    + + + + + + + + + + + + + + + + + + + +

                    (static) connect(connectionInfo, errorFuncHandle, connectFunctionHandle)

                    @@ -287,89 +369,7 @@
                    Parameters:
                    Source:
                    - - - - - - - -
          - - - - - - - - - - - - - - - - - - - - - -

          (static) disconnect()

          - - - - - -
          - Disconnects from Kaazing WebSocket JMS Gateway, closes all the subscription and releases all the resources. -
          - - - - - - - - - - - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - -
          Source:
          -
          @@ -417,7 +417,7 @@

          Home

          Classes

          • diff --git a/javascript/jsdoc/jmsClientFunction-createConnectionObject-ConnectionObject.html b/javascript/jsdoc/jmsClientFunction-createConnectionObject-ConnectionObject.html index 4605ab8..518f6f9 100644 --- a/javascript/jsdoc/jmsClientFunction-createConnectionObject-ConnectionObject.html +++ b/javascript/jsdoc/jmsClientFunction-createConnectionObject-ConnectionObject.html @@ -91,7 +91,7 @@

            new C
            Source:
            @@ -332,7 +332,7 @@

            Parameters:
            Source:
            @@ -380,7 +380,7 @@

            Home

            Classes

            • diff --git a/javascript/jsdoc/jmsClientFunction-createSubscriptionObject-SubscriptionObject.html b/javascript/jsdoc/jmsClientFunction-createSubscriptionObject-SubscriptionObject.html index 74cf2e2..9e708d0 100644 --- a/javascript/jsdoc/jmsClientFunction-createSubscriptionObject-SubscriptionObject.html +++ b/javascript/jsdoc/jmsClientFunction-createSubscriptionObject-SubscriptionObject.html @@ -140,7 +140,7 @@

              Methods

              -

              (static) close()

              +

              (static) disconnect()

              @@ -370,7 +370,7 @@

              Home

              Classes