Title: OpenEdge
1OpenEdge SQL SonicMQUsing JMS with SQL
Applications
2Session Goals
- Learn how to use JMS techniques
- With a JDBC application
- With an ODBC application
- Using SQL java stored procedure
- Using SQL java row trigger
3OpenEdge SQL and SonicMQ
- JMS and SonicMQ
- OpenEdge SQL
- Integration
- Demo
- Summary and Questions
4Example Supplier and Retailer
5Messaging
- A mechanism enabling autonomous applications to
communicate - Messages are units of information composed of
- Body
- Header
- Destinations
- Priority
- Ordering
- Expiration
- Time-to-Live
- And more
6JMS
- A specification for Message-Oriented Middleware
(MOM) provider - Version 1.1
- A Java interface and semantics for
inter-application messaging - Basic functionality of JMS
- Javax.jms. package
- Enterprise Application Integration (EAI)
- http//java.sun.com/products/jms
7JMS Features
- Standard client API
- Asynchronous or synchronous guaranteed message
delivery - Transactions
- Message filtering
- Reliability levels
- Two messaging models with a common interface
8Basic JMS Terminology
Application B
Application A
JMS - Message Oriented Middleware
Connection
Session
Destination
Producer
Consumer
9JMS Two Messaging Models
Point to Point (1 to 1)
Potential Receiver
Queue
Sender
Potential Receiver
Publish and Subscribe (1 to Many)
Subscriber
Topic
Publisher
Subscriber
10Development of JMS
- Develop the JMS client application
- Develop the JMS adapter
- Develop the producers and consumers
- Develop the interaction with the JMS server
11SonicMQ
- A JMS provider
- Uses standard JMS components and terminology
- Extends the JMS specification
- Additional message types (XML, Multi-part, Large)
- Distributed transactions (JTA XAResource API)
- Security (authentication, authorization, SSL)
- Open database connectivity
- Continuous availability (Fault tolerant client
connection)
http//www.sonicsoftware.com
12Install SonicMQ
- Download the product from http//www.sonicsoftware
.com - Typical installation components
- A domain manager container
- The Sonic management console (SMC)
- The client runtime
- The default PSE pro database
- JRE ( Windows only )
13Configuring and Managing SonicMQ
- Sonic Management Console (SMC)
- Create a new container hosting a broker
- View existing queues
- Create a new queue
- Monitor broker notification
14Start the SonicMQ Domain
Start ?Programs ?Sonic Software ?SonicMQ ?SonicMQ
Container1
Domain
Container1
Broker1
Queue
Topic
Directory Service
Agent Manager
15SonicMQ API and Archives
- Packages
- Javax.jms (standard JMS)
- Progress.message.jclient (Sonic extensions)
- Progress.message.jclient.channel
- Progress.message.jclient.xa
- Archives
- Under sonicmq-install-dir\lib\.jar
16OpenEdge SQL and SonicMQ
- JMS and SonicMQ
- OpenEdge SQL
- Integration
- Demo
- Summary and Questions
17OpenEdge SQL
- SQL standard database open access via JDBC and
ODBC - DataDirect JDBC driver
- Core JDBC 2.0 and extensions
- DataDirect ODBC driver
- Core ODBC 3.0
- Server integration with Java
- Java Stored procedure and row trigger
18OpenEdge SQL client-server architecture
Windows App
Java App
ODBC driver
JDBC driver
OE SQL Server
JVM
Database Storage Manager
OpenEdge SQL Database
Java sp/trigger
19Install OpenEdge SQL
- SQL server
- Choose the database component
- _sqlsrv2
- Multithreaded and reusable
- DataDirect JDBC and ODBC drivers
- Choose SQL Client access
- Java classes
- DLL or shared libraries
20JDBC application program initialization
- Environment
- CLASSPATH
- Shared library path
- Include the package
- Import java.sql.
- Load the driver
- Class.forName(com.progress.sql.jdbc.JdbcProgressD
river) - Get the connection
- DriverManager.getConnection()
- jdbcjdbcprogressThost-nameport
database-name - Turn on the JDBC tracing
- DriverManager.setLogStream(PrintStream log)
21Basic JDBC API
Driver Manager
ltInterfacegt Driver
ltInterfacegt Connection
ltInterfacegt Statement
ltInterfacegt ResultSet
ltInterfacegt PreparedStatement
ltInterfacegt DatabaseMetaData
ltInterfacegt ResultSetMetaData
ltInterfacegt CallableStatement
22ODBC application program initialization
- Setting the Shared library path
- Creating a DSN
- Data Source (ODBC) on Windows
- ODBC.INI file on Unix
- Allocate An Environment Handle
- SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE,En
vHandle) - Allocate A Connection Handle
- SQLAllocHandle(SQL_HANDLE_DBC, EnvHandle,
ConHandle) - Connect with the DSN
- SQLConnect(ConHandle,)
23ODBC APIs
- The various ODBC functions can be broken down
into seven distinct groups - Connections
- Cursors
- Executing SQL statements
- Receiving results
- Cancelling an operation
- Error handling
- Transaction control
24Java Stored Procedures
- Java snippets
- All standard JAVA features
- OpenEdge SQL-supplied JAVA classes
- Integration between SQL and JAVA
- Enhances application
- Flexibility, Performance, Portability and
reusability - Extend SQL capabilities of databases
- Receive or send IN/OUT/INOUT parameters
- Handle exceptions
- Allow any SQL statement to access database
- Return result set
- Call other procedures
- Use predefined and external JAVA classes
25Java Stored Procedures (Cont.)
- Transaction
- Same as and part of the calling application
- COMMIT or ROLLBACK statement not allowed
- Security
- Creation
- RESOURCE or DBA privilege
- Drop and Grant
- DBA or the owner
- Execution
- DBA, owner or user who is granted with the
EXECUTE - Only owners privileges checked for procedure
objects (tables, columns and etc) during
execution
26Working with Java Stored Procedures
- Configuring
- JDK, JRE and sql_env script
- Using SQL statements
- CREATE PROCEDURE
- DROP PROCEDURE
- CALL
- Viewing
- SYSPROGRESS.SYSPROCEDURES
- SYSPROGRESS.SYSPROCTEXT
- Exporting
- SQLSCHEMA -P
27Accessing Stored Procedures from Applications
- Embed the call escape sequence
- CALL proc_name ( parameter , ... )
- JDBC CallableStatement
- ODBC SQLPrepare or SQLExecDirect
try CallableStatement statement int Part_num
318 statement conn.prepareCall("call
order_parts(?)") statement.setInt(1,
Part_num) statement.execute()
SQLUINTEGER Part_num SQLINTEGER Part_numInd
0 SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT,SQL
_C_SLONG, SQL_INTEGER,0, 0, Part_num, 0,
Part_numInd) Part_num 318 SQLExecDirect(hstmt,
" call order_parts(?) ", SQL_NTS)
28Java row triggers
- A special type of stored procedure
- To maintain database integrity
- Automatically invoked (fired) by certain SQL
operations - OLDROW and NEWROW object
- getValue(), setValue()
- CREATE/DROP TRIGGER SQL statements
- SYSPROGRESS.SYSTRIGGER
29OpenEdge SQL JAVA classes
setParam
makeNull
execute
rowCount
SQLIStatement
SQLPStatement
execute
Open
close
fetch
wasNull
getValue
Found
getParam
SQLCursor
log
err
DhSQLResultSet
set
makeNull
insert
DhSQLException
getDiagnostics
30OpenEdge SQL and SonicMQ
- JMS and SonicMQ
- OpenEdge SQL
- Integration
- Demo
- Summary and Questions
31SonicMQ Messaging
OpenEdgeApplication
EIS
Java/J2EE Application
JMS
Customer Adapter
JMS
Message Broker ( SonicMQ
)
Customer Adapter
JMS
Connection
OpenEdge Database
Legacy Application
Session
Producer or Consumer
32Solutions
- Developing the JMS enabled client applications
- JDBC JMS
- Developing the JMS adapter
- JAVA class
- Java stored procedure
- Developing the JMS producer with the database
Java row triggers
33Writing a JMS Adapter
- Set the CLASSPATH
- Choose the messaging model
- PTP
- PUB/SUB
- Identify the role
- Producer
- Consumer
- Prepare message types
34Include SonicMQ jars
- CLASSPATH needs to include
- sonic_Client.jar
- mfcontext.jar
- gnu-regexp-1.0.6.jar
- jaxp.jar
- xercesImpl.jar
- xmlParserAPIs.jar
35PTP - Basic Steps
- Initialization
- - Connect to a SonicMQ Broker
- - Create a Session
- - Create or lookup queues
- Create a Message Producer/Consumer
- Prepare Messages
- Send/Receive Message
- Close Message Producer/Consumer
36Pub\Sub - Basic Steps
- Initialization
- - Connect to a SonicMQ broker
- - Create a Session
- - Create or lookup Topics
- Create a message publisher
- Subscribe to Topic
- Publish message to Topic
- Consume message from a Topic
- Close Message Producer/Consumer
37Writing a JMS Adapter Initialization
String broker "localhost2506"//default sonic
broker String username "wang" //default user
name String password "password"//default user
password // Create a SonicMQ connection. Try
javax.jms.ConnectionFactory factory
factory (new progress.message.jclient.Conne
ctionFactory (broker))
javax.jms.Connect connect connect
factory.createConnection (username, password)
javax.jms.Session session
session connect.createSession(false,javax.jms.Se
ssion.AUTO_ACKNOWLEDGE) catch
(javax.jms.JMSException jmse)
jmse.printStackTrace() System.exit(1)
ConectionFactory
Creates
Connection
Creates
Session
38Creating a Producer
createQueue( String queueName )
Queue
createTopic( String topicName )
Topic
session
MessageProducer
createProducer( Queue queue ) createProducer(
Topic topic )
javax.jms.Queue senderQueue session.createQueue(
sQueue) javax.jms.MessageProducer sender
session.createProducer(senderQueue) Sender.send
(msg,javax.jms.DeliveryMode.PERSISTENT,javax.jms.M
essage.DEFAULT_PRIORITY,MESSAGE_LIFESPAN) . Sende
r.close()
39Creating a Consumer
createQueue( String queueName )
Queue
createTopic( String topicName )
Topic
session
MessageConsumer
createConsumer( Queue queue ) createConsumer (
Topic topic )
javax.jms.Queue receiveQueue session.createQueue
(rQueue) javax.jms.MessageConsumer receiver
session.createConsumer(receiveQueue) Receiver.se
tMessageListener (listener) Connect.start() . r
eceiver.close()
40Message Types
Message type Message body
TextMessage A Java String
ObjectMessage A serializable Java object
MapMessage Name/value pairs, where names are Java strings and values are java primitive types
StreamMessage A sequential stream of primitives
BytesMessage An uninterrupted stream of bytes
XMLMessage A Java String formatted as a tagged XML document
MultipartMessage Zero or more parts each part can be a JMS message or arbitrary data
41Select a Message Type
- Major factors
- Company message format requirements
- Message volume and size
- Proportion of keys to data
- Consumers need
- Suggestions
- XML for inter-application communications
- Text for simple test with no interpretation
- Map for random access to data via keys
- Stream for sequential access to data
- Object for producer and consumer have access to
the same java class representing message - Byte for binary format message contents
42Working on Messages
- Producing messages
- javax.jms.Session.createmessage type()
- javax.jms.MessageProducer.send()
- Consuming messages
- Javax.jms.MessageListener.onMessage()
- Javax.jms.MessageConsumer.receive()
javax.jms.MapMessage mmsg session.createMapMessa
ge() Progress.message.jclient.XMLMessage xmsg
((progress.message.jclient.Session)
session).createXMLMessage()
public void onMessage( javax.jms.Message
aMessage) javax.jms.TextMessage textMessage
(javax.jms.TextMessage) aMessage String string
textMessage.getText()
43Use Case 1 - Producer
JDBC App
ODBC App
JMS adapter
Receiving App
SonicMQ Broker
Receiving App
JMS adapter (java sp)
44Example JMS producer adapter
javax.jms.MapMessage msgsession.createMapMessage(
) msg.setInt( "ID", iid.intValue()) msg.setStrin
g( "INAME", iname) msg.setString( "IPRICE",
iprice) producer.send( msg,javax.jms.DeliveryMode
.PERSISTENT, javax.jms.Message.DEFAULT_PRIORITY,1
800000)
progress.message.jclient.XMLMessage msg
((progress.message.jclient.Session)session).creat
eXMLMessage() msg.setText(xmlString) producer.se
nd( msg,javax.jms.DeliveryMode.PERSISTENT, javax.
jms.Message.DEFAULT_PRIORITY,1800000)
if ( producer ! null ) producer.close() if (
session ! null ) session.close() if (
connect ! null ) connect.close()
public class JMSProducerAdapter private
javax.jms.Connection connect null private
javax.jms.Session session null javax.jms.Queue
queue null javax.jms.Topic topic
null javax.jms.MessageProducer producer
null public JMSProducerAdapter(String broker,
String username, String password) public void
createPTPProducer(String queueName) public
void createPSProducer(String topicName)
public void sendMapMsg (Integer iid, String
iname,String iprice) .. public void sendXMLMsg
( String xmlString ) public void close ()
45Example JDBC Producer application
jmsProducer new JMSProducerAdapter(DEFAULT_BROK
ER_NAME,DEFAULT_USERNAME,DEFAULT_PASSWORD) jmsPro
ducer.createPTPProducer(DEFAULT_QUEUE) while
(rs.next()) id rs.getInt(1)
generateXMLText(id, iname, iprice)
jmsProducer.sendXMLMsg ( xmlmsg.toString()
) rs.close()
StringBuffer xmlmsg new StringBuffer()
xmlmsg.append ("lt?xml version\"1.0\"?gt\n") xmlms
g.append ("ltmessagegt\n") xmlmsg.append ("
ltItemIDgt" iid "lt/ItemIDgt\n") xmlmsg.append
(" ltItemNamegt" iname "lt/ItemNamegt\n") xmlmsg
.append (" ltItemPricegt" iprice
"lt/ItemPricegt\n") xmlmsg.append ("lt/messagegt\n")
public class jdbctest_producer private static
Connection connectionnull private static
Statement stmtnull private static
CallableStatement callStmtnull private static
JMSProducerAdapter jmsProducernull public
jdbctest_producer(String dbconnectstring,String
username,String password) private void
connect(String dbconnectstring,String
username,String password) public void
closeConnection() public ResultSet
retrieveData(String query) throws
Exception public void send_message (ResultSet
rs) throws Exception public void
generateXMLText (int iid, String iname,
java.math.BigDecimal iprice) public static
void main(String args)
46ExampleODBC Producer application
stSQLExecDirect(CallStmtHandle, (SQLCHAR)"
call JMSProducerAdapter(?,?,?) ", SQL_NTS)
SQLRETURN ODBC_ClassSelectRecords(SQLCHAR
SQLStmt,char Tname) st SQLExecDirect
(StmtHandle, SQLStmt, SQL_NTS) st
SQLBindCol (StmtHandle, 1, SQL_C_LONG,
(SQLPOINTER) ID, sizeof(long) , cbID) st
SQLBindCol (StmtHandle, 2, SQL_C_CHAR,
(SQLPOINTER) Name, sizeof(Name), NULL) st
SQLBindCol (StmtHandle, 3, SQL_C_CHAR,
(SQLPOINTER) Price, sizeof(Price), cbID)
while (st ! SQL_NO_DATA) st
SQLFetch(StmtHandle) if (st !
SQL_NO_DATA) SendMessage(ID,Name,Price,Tname)
SQLRETURN ODBC_ClassSendMessage(long
iid, SQLCHAR iname, SQLCHAR iprice,char
Tname) stSQLBindParameter
(CallStmtHandle, 1, SQL_PARAM_INPUT,SQL_C_LONG,
SQL_INTEGER,0, 0, iid, 4, cbID)
stSQLBindParameter (CallStmtHandle, 2,
SQL_PARAM_INPUT,SQL_C_CHAR, SQL_CHAR,30, 0,
iname, 30, NULL) stSQLBindParameter
(CallStmtHandle, 3, SQL_PARAM_INPUT,SQL_C_CHAR,
SQL_CHAR,10, 0, iprice, 10, NULL)
stSQLExecDirect(CallStmtHandle, (SQLCHAR)"
call JMSProducerAdapter(?,?,?) ", SQL_NTS)
47Example Java Stored Procedure JMS producer
adapter
CREATE PROCEDURE JMSProducerAdapter( IN id
INTEGER, IN iname VARCHAR(30),IN iprice
VARCHAR(10) ) IMPORT import java.sql. BEGIN
JMSProducerAdapter jmsProducernull String
DEFAULT_BROKER_NAME "localhost2506"
String DEFAULT_USERNAME "wang" String
DEFAULT_PASSWORD "password" String
DEFAULT_QUEUE "SampleQ1" // Invoking the
JMS adapter Java object jmsProducer new
JMSProducerAdapter (DEFAULT_BROKER_NAME,
DEFAULT_USERNAME,DEFAULT_PASSWORD)
jmsProducer.createPTPProducer(DEFAULT_QUEUE)
jmsProducer.sendMapMsg (id, iname, iprice)
jmsProducer.close() END
jmsProducer new JMSProducerAdapter
( DEFAULT_BROKER_NAME, DEFAULT_USERNAME,
DEFAULT_PASSWORD)
jmsProducer.createPTPProducer(DEFAULT_QUEUE)
jmsProducer.sendMapMsg (id, iname, iprice)
jmsProducer.close()
48Use Case 2 - Consumer
JDBC App
ODBC App
JMS Adapter
Sending App
SonicMQ Broker
JMS Adapter (java sp)
Sending App
49Example JMS consumer adapter
if (aMessage instanceof
javax.jms.MapMessage)
javax.jms.MapMessage mapMessage
(javax.jms.MapMessage) aMessage int id
mapMessage.getInt("ID") String name
mapMessage.getString("INAME") String price
(String)mapMessage.getObject("IPRICE") jdbcobj.n
ewItem(id,name,price)
public class JMSConsumerAdapter implements
javax.jms.MessageListener private
javax.jms.Connection connect null private
javax.jms.Session session null private
javax.jms.Queue queue null private
javax.jms.Topic topic null private
javax.jms.MessageConsumer consumer
null jdbctest_consumer jdbcobj null // The
JDBC application object public Integer ids
new Integer20 public String names new
String20 public String prices new
String20 public int msgCnt 0 public
JMSConsumerAdapter(String broker, String
username, String password) public void
createPTPConsumer(String queueName) public
void createPSConsumer(String topicName) private
void printDocNodes( org.w3c.dom.Node node, int
indentSpaces ) public void onMessage(
javax.jms.Message aMessage) public void close
() public static void main(String
args)
if (aMessage instanceof progress.message.jcli
ent.XMLMessage) progress.message.jclie
nt.XMLMessage xmlMessage (progress.message.jcl
ient.XMLMessage) aMessage
org.w3c.dom.Document doc xmlMessage.getDocument(
) org.w3c.dom.NodeList nodes null
nodes doc.getElementsByTagName("ItemID")
String id (nodes.getLength() gt 0) ?
nodes.item(0).getFirstChild().getNodeValue()
"unknown"
queue session.createQueue
(queueName) consumer
session.createConsumer(queue)
consumer.setMessageListener(this)
connect.start()
50Example JDBC consumer application
public class Jdbctest_Consumer implements
javax.jms.MessageListener public void
onMessage( javax.jms.Message aMessage)
// Cast the message as a text message.
javax.jms.TextMessage textMessage
(javax.jms.TextMessage) aMessage
// Passing the message receive_message
textMessage.getText()
insertRecord(receive_message)
updateRecord(receive_message) public
void insertRecord(String msgText) Public void
updateRecord(String msgText)
51Example Java Stored Procedure JMS consumer
adapter
CREATE PROCEDURE JMSConsumerAdapter(IN sleeptime
Integer) RESULT ( id INTEGER, name VARCHAR(30),
price VARCHAR(10)) IMPORT import java.sql.
BEGIN // Create the JMS adapter java object
JMSConsumerAdapter jmsConsumer new
JMSConsumerAdapter(DEFAULT_BROKER_NAME,DEFAULT
_USERNAME,DEFAULT_PASSWORD,true) // PTP model
with queue jmsConsumer.createPTPConsumer(DEFAUL
T_QUEUE) // Sleep to get more messages
java.lang.Thread.sleep(sleeptime.longValue())
// Translate the JMS message into the result
set for (int i0 ilt jmsConsumer.msgCnt i)
SQLResultSet.set(1, jmsConsumer.idsi) SQLRe
sultSet.set(2, jmsConsumer.namesi) SQLResultSe
t.set(3, jmsConsumer.pricesi) SQLResultSet.ins
ert() // Close jmsConsumer.close()
END
jmsConsumer new JMSConsumerAdapter (
DEFAULT_BROKER_NAME, DEFAULT_USERNAME,
DEFAULT_PASSWORD,true) jmsConsumer.createPTPCons
umer(DEFAULT_QUEUE)
52Example ODBC Consumer
stSQLBindParameter (CallStmtHandle, 1,
SQL_PARAM_INPUT,SQL_C_LONG, SQL_INTEGER,0, 0,
sleeptime, 4, cbID) stSQLExecDirect(CallStmtHa
ndle, (SQLCHAR)" call JMSConsumerAdapter(?)
", SQL_NTS)
SQLRETURN ODBC_ClassProcessMessage()
SQLRETURN st SQLINTEGER cbID 0 long
sleeptime 600 long ID 0 SQLCHAR Name
30 SQLCHAR Price10 stSQLBindParameter
(CallStmtHandle,1,SQL_PARAM_INPUT,SQL_C_LONG,SQL_
INTEGER,0,0,sleeptime,4,cbID)
stSQLExecDirect(CallStmtHandle, (SQLCHAR)"
call JMSConsumerAdapter(?) ", SQL_NTS) if
(st SQL_SUCCESS) st SQLBindCol
(CallStmtHandle, 1, SQL_C_LONG, (SQLPOINTER) ID,
sizeof(long) , cbID) st SQLBindCol
(CallStmtHandle, 2, SQL_C_CHAR, (SQLPOINTER)
Name, sizeof(Name), NULL) st SQLBindCol
(CallStmtHandle, 3, SQL_C_CHAR, (SQLPOINTER)
Price, sizeof(Price), cbID) while (st !
SQL_NO_DATA) st SQLFetch(CallStmtHand
le) if (st ! SQL_NO_DATA)
return PASS
st SQLBindCol (CallStmtHandle, 1, SQL_C_LONG,
(SQLPOINTER) ID, sizeof(long) , cbID) st
SQLFetch(CallStmtHandle)
53Use Case 3 Database Trigger
Receiving App
SonicMQ Broker
JMS adapter (java sp)
JMS adapter
Receiving App
Java trigger
54Example Insert Trigger
JMSProducerAdapter jmsProducer new
JMSProducerAdapter ( DEFAULT_BROKER_NAME,
DEFAULT_USERNAME, DEFAULT_PASSWORD) jmsProducer.
createPTPProducer(DEFAULT_QUEUE) jmsProducer.send
MapMsg (id, iname, iprice.toString()) jmsProducer
.close()
create trigger tb1_insert_trig1 after insert on
tb1 REFERENCING NEWROW for each
row IMPORT import java.sql. BEGIN // Get
the new record from the NEWROW object Integer
id (Integer)NEWROW.getValue (1,INTEGER)
String iname (String)NEWROW.getValue
(2,VARCHAR) java.math.BigDecimal iprice
(java.math.BigDecimal)NEWROW.getValue
(3,NUMERIC) // Create the JMS adapter java
object JMSProducerAdapter jmsProducer new
JMSProducerAdapter(DEFAULT_BROKER_NAME,DEFAULT_US
ERNAME,DEFAULT_PASSWORD) // PTP model with
queue jmsProducer.createPTPProducer(DEFAULT_QU
EUE) // Send the data
jmsProducer.sendMapMsg (id, iname,
iprice.toString()) // Close
jmsProducer.close() END
55OpenEdge SQL and SonicMQ
- JMS and SonicMQ
- OpenEdge SQL
- Integration
- Demo
- Summary and Questions
56Demo Supplier and Retailer
57Demo Supplier and Retailer
- Supplier database update for
- Products price changes
- New arrival products
- Receiving orders from Retailer
- Supplier databases Java trigger
- Fired up and calling the JMS Adapter to send the
updated information - Retailers application
- Receiving Suppliers products updates
- Sending orders to Supplier
58OpenEdge SQL and SonicMQ
- JMS and SonicMQ
- OpenEdge SQL
- Integration
- Demo
- Summary and Questions
59In Summary You can do it now !
OpenEdge SQL DB
- SQL programmers are able to use JMS/SonicMQ to
communicate their JDBC or ODBC applications - Java stored procedures are a great OpenEdge SQL
feature to take advantage of JMS - It is easy to develop
JDBC
J2EE
.NET
SonicMQ Broker
Any
ODBC
Any
OpenEdge SQL DB
60Questions?
- JMS and SonicMQ
- OpenEdge SQL
- Integration
- Demo
- Summary and Questions