Progress Fuse Adapter Documentation

OpenEdge Adapter for Fuse Message Broker

Overview

The OpenEdge Adapter for Fuse Message Broker enables connections from an
OpenEdge™ ABL application to Fuse™ Message Broker or Apache ActiveMQ (or
other messaging solution as described below). It consists of a number of ABL
classes that should be referenced in an ABL application that needs to exchange
messages with the outside world using one of the supported world class
messaging solutions.

This adapter takes care of message manipulation and communication over the
network with the message broker. There is no need to install or load external
libraries; it is a pure ABL solution.

Features

The product is usable, but development has not stopped. The initial
developers are still extending the list of features. The following aspects of
the JMS standard are feasible with the STOMP protocol, but not (fully)
supported yet.

Requirements

Installing and configuring the required products is not described here.
Please refer to the appropriate product documentation.

More information

Addtional documentation for the OpenEdge Adapter for Fuse Message Broker:

External documentation:

Alternative product:


API for the Progress Adapter for Fuse Message Broker

OpenEdge Adapter for Fuse Message Broker API

The API supported by the adapter is a subset of the JMS API. Full
documentation of all details is available online. The
diagrams below only describe the part of the API that is implemented by the
OpenEdge Adapter for Fuse Message Broker.
Notes:

foundationclassfoundationclass
connectionclassconnectionclass
sessionclasssessionclass
producerclassproducerclass
consumerclassconsumerclass


Change log for the Progress Adapter for Fuse

Changelog


MIT Progress Adapter for Fuse

Copyright (c) 2009 Flusso B.V.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


Progress Fuse Adapter Project

Progress Fuse Adapter
Written in OO ABL and supports the stomp protocol.
Code comments in Dutch

Documentation

  • Using the adapter
  • API details
  • Change log

  • Using the Progress Adapter for Fuse Message Broker

    Using the OpenEdge Adapter for Fuse Message Broker

    Getting started

    Prerequisites

    Defining the connection with the broker

    In JMS you need 2 objects to collect the connection parameters with the
    message broker: a ConnectionFactory that knows where to connect,
    and a Connection object that knows how to authenticate for a
    session (next step). In this example we assume that the broker is running on
    the develement machine and the STOMP listener uses the default port number.

    factory = NEW nl.flusso.stomp.ConnectionFactory('localhost':U, 61613).
    connection = factory:createConnection('username':U, 'password':U).

    If your broker does not require authentication, you can supply the unknown
    value for both user name and password:

    connection = factory:createConnection(?, ?).

    Starting a session and cleaning up

    A JMS session encapsulates all communication with the broker (using an ABL
    SOCKET object). After using the session object for exchanging messages with the
    broker, we need to release operating system resources and tell the broker we do
    not want to receive any more data. The broker uses this notification to clean
    up resources allocated for us.

    jmsSession = connection:createSession(FALSE, {&CLIENT_ACKNOWLEDGE}).
    /* Exchange messages with the broker, see below. */
    FINALLY:
      jmsSession:close().
    END FINALLY.

    In the example above we indicate that we do not want to group sent messages
    using explicit transactions, but we do want to acknowledge the successful
    receipt and processing of messages that the broker sent to us. If we would
    choose automatic acknowledgement, messages for us are considered done when they
    are sent by the STOMP subsystem of the broker, before we even know that there
    are bytes on their way over the network channel.

    Preparing for message exchange

    A JMS Destination is an abstract concept that denotes the place
    where we sent messages to or receive messages from. It could be either a
    Queue or a Topic. We send messages to a
    Destination using a MessageProducer and receive from
    a Destination using a MessageConsumer.

    destination = jmsSession:createQueue('SampleQ1':U).
    producer = jmsSession:createProducer(destination).

    or

    destination = jmsSession:createQueue('SampleQ1':U).
    consumer = jmsSession:createConsumer(destination).

    Sending messages

    After all the preparations above we are ready to create a message and send
    it.

    messageToSend = jmsSession:createTextMessage('Hello world':U).
    producer:send(messageToSend).

    Full example, now including all declarations:

    USING javax.jms.*.
    ROUTINE-LEVEL ON ERROR UNDO, THROW.
    {javax/jms/Session.i}
    
    DEFINE VARIABLE factory       AS ConnectionFactory NO-UNDO.
    DEFINE VARIABLE connection    AS Connection        NO-UNDO.
    DEFINE VARIABLE jmsSession    AS Session           NO-UNDO.
    DEFINE VARIABLE destination   AS Queue             NO-UNDO.
    DEFINE VARIABLE producer      AS MessageProducer   NO-UNDO.
    DEFINE VARIABLE messageToSend AS TextMessage       NO-UNDO.
    
    factory = NEW nl.flusso.stomp.ConnectionFactory('localhost':U, 61613).
    connection = factory:createConnection('username':U, 'password':U).
    jmsSession = connection:createSession(FALSE, {&CLIENT_ACKNOWLEDGE}).
    destination = jmsSession:createQueue('SampleQ1':U).
    producer = jmsSession:createProducer(destination).
    
    messageToSend = jmsSession:createTextMessage('Hello world':U).
    producer:send(messageToSend).
    
    FINALLY:
      jmsSession:close().
    END FINALLY.

    Receiving messages

    Receiving a message is somewhat more complicated than sending one, because
    we need to find out what kind of message we received before we can process it.
    In ABL we do that by trying to cast the message to a type that we can handle.
    In the example below we ignore messages of other types, and in particular we do
    not acknowledge the receipt of those messages. That way those messages will
    remain available for other clients to process.

    USING javax.jms.*.
    ROUTINE-LEVEL ON ERROR UNDO, THROW.
    {javax/jms/Session.i}
    
    DEFINE VARIABLE factory        AS ConnectionFactory NO-UNDO.
    DEFINE VARIABLE connection     AS Connection        NO-UNDO.
    DEFINE VARIABLE jmsSession     AS Session           NO-UNDO.
    DEFINE VARIABLE destination    AS Queue             NO-UNDO.
    DEFINE VARIABLE consumer       AS MessageConsumer   NO-UNDO.
    DEFINE VARIABLE genericMessage AS Message           NO-UNDO.
    DEFINE VARIABLE textMessage    AS TextMessage       NO-UNDO.
    DEFINE VARIABLE textBody       AS LONGCHAR          NO-UNDO.
    DEFINE VARIABLE textLength     AS INTEGER           NO-UNDO.
    
    factory = NEW nl.flusso.stomp.ConnectionFactory('localhost':U, 61613).
    connection = factory:createConnection('username':U, 'password':U).
    jmsSession = connection:createSession(FALSE, {&CLIENT_ACKNOWLEDGE}).
    destination = jmsSession:createQueue('SampleQ1':U).
    consumer = jmsSession:createConsumer(destination).
    
    genericMessage = consumer:receive().
    textMessage = CAST(genericMessage, TextMessage) NO-ERROR.
    IF NOT ERROR-STATUS:ERROR THEN
    DO:
      textBody = textMessage:text.
      textLength = LENGTH(textBody).
      MESSAGE (IF textLength < 100 THEN STRING(textBody) ELSE 'long message') VIEW-AS ALERT-BOX.
      textMessage:acknowledge().
    END.
    
    FINALLY:
      jmsSession:close().
    END FINALLY.

    Hints

    Use interfaces

    In the examples above all class-based object variables are defined as having
    an ABL interface type. That is is a recommended practice for general OO
    programming, but in particular when using the OpenEdge Adapter for Fuse Message
    Broker. Developers reserve the right to change all implementation classes in
    package nl.flusso.stomp, except ConnectionFactory. All operations
    after obtaining a ConnectionFactory instance can be accomplished
    using only interface type variables and parameters.

    More examples

    The stompTests directory in the source distribution contains our general
    test cases. They show some more possible usage scenarios.

    Note that those tests (and the adapter implementation itself) tend to delete
    all objects explicitly, instead of relying on the 10.2 garbage collector. That
    is not because we think it is better or we prefer to do unnecessary work, but
    it is part of the preparation for a planned backport to 10.1C.

    Full documentation

    The OpenEdge Adapter for Fuse Message Broker implements a pure subset of the
    standard JMS API. The part that is implemented, should follow the specification
    faithfully. There are no intended extensions of the specification (except as
    workarounds for OpenEdge™ limitations, see below).

    In a separate document we describe what part of the
    JMS API is currently supported. All details of the API are described in the
    standard JMS 1.1 documentation (available online) and in
    several works available at your favorite book seller.

    Java API to ABL translation rules

    The following rules were applied for translating the JMS API specification
    to ABL definitions.