Using JMS from Visual Basic |
This example demonstrates how to access Java Message Service (JMS) from a Visual Basic application.
This example was developed using Windows 2000, JDK1.3.1, J2EESDK1.3 Beta and Visual Basic 6.0. It should also work with Windows NT4.0.
Install J-Integra®.
Install the latest JDK.
Install J2EESDK1.3 Beta (follow the link called "Java 2 SDK, Enterprise Edition, version 1.3 beta").
Install Visual Basic.
You will also need Microsoft's IDL compiler (midl.exe) to compile your COM IDL. Midl.exe is part of the Visual C++ installation. Visual C++ also includes the command vcvars32.bat which will set up the environment variables required to run midl.exe.
Part I - Late Binding - which demonstrates how to use JMS from VB without having to generate proxies. This part also demonstrates a technique for invoking overloaded methods in a java class from VB.
Part II - Early Binding - which demonstrates the same functionality as the late binding part but by using proxies generated by com2java.
You should not need to be familiar with Visual Basic to complete this example, but any experience is an advantage.
After working through the examples presented here you will see how easy it
is to integrate Visual Basic and JMS. Or indeed any COM client, not just Visual
Basic.
Now any Visual Basic client can post messages to a JMS queue. This is becoming
increasingly important as message queues are more tightly integrated with J2EE.
More Visual Basic clients will need to interact with EJBs via JMS.
Although not presented here, it is also possible
for any COM client to function as a receiver. To provide the service of taking
messages from the queue and processing them.
An example of this would be a COM server hosted in MTS which completes some
transaction processing on a Microsoft platform. It could process transactions
posted to the JMS from a variety of other platforms.
By using late binding you do not need to generate proxies for the Java classes you wish to access. J-Integra® provides to Visual Basic an IDispatch interface which is used to create objects, invoke methods and set properties.
Usually this is the quickest way to test/experiment with accessing a Java class from a COM client. However it does have the drawback of performance overhead and you also lose Visual Basic's auto completion features (where it prompts you with method/member names).
The steps involved
This example assumes that you have installed
the JDK under C:\JDK1.3.1
the J2EESDK under C:\J2SDKEE1.3
We will be creating this example in C:\pure\JMSExample\LateBinding. Please create this directory.
Set your PATH environment variable to include the JDK and J-Integra® bin directories, and update your CLASSPATH environment to include the J-Integra® runtime. As you also need to configure your environment for the J2EESDK you may find it convenient to create a batch file in the j2eesdk bin directory and execute that. This is what I did:
Note that the setenv.bat file which is called at the end of mysetenv.bat is part of the J2EESDK and is located in that bin directory.
In the c:\pure\JMSExample\LateBinding directory create a file called COMtoJMS.java and place the following code there:
// This is the bridge. The VB client talks to this // process via DCOM, and this process talks to JMS. // If you have a Java server process you could add this // initialization there. import javax.naming.*; import com.linar.jintegra.*; public class COMtoJMS { ?FONT COLOR="#000080">public static void main(String[] args) throws Exception { ?FONT COLOR="#000080">try { ?FONT COLOR="#808080">// Generate a log just in case it all goes wrong ?FONT COLOR="#000000">com.linar.jintegra.Log.logImmediately(3, "jintegra.log"); ?FONT COLOR="#808080">// Register the JVM name with the J-Integra® runtime ?FONT COLOR="#000000">Jvm.register("JMS"); ?FONT COLOR="#808080">// Wait around for a while. When the process exits the objects ?FONT COLOR="#808080">// here will no longer be accessible from COM. ?FONT COLOR="#000080">while (true) { ?FONT COLOR="#808080">// do nothing. ?FONT COLOR="#000000">Thread.sleep(10000); ?FONT COLOR="#000000"> } ?FONT COLOR="#000000"> } ?FONT COLOR="#000080">catch (Exception e){ ?FONT COLOR="#000000">System.out.println(e.getMessage()); ?FONT COLOR="#000000">e.printStackTrace(); ?FONT COLOR="#000000"> } ?FONT COLOR="#000000"> } } |
Also create a file called MyWrappers.java and place the following code there:
// This class provides wrappers to enable calling overloaded // member functions from Visual Basic. import javax.naming.*; import javax.jms.*; public class MyWrappers { ?FONT COLOR="#000080">public void QueueSender_send( ?FONT COLOR="#000000">QueueSender cQueueSender, ?FONT COLOR="#000000">Message cMessage) ?FONT COLOR="#000080">throws javax.jms.JMSException { ?FONT COLOR="#808080">// print out something so we know the method was invoked. ?FONT COLOR="#000000">System.out.println("+QueueSender_send."); ?FONT COLOR="#000000">cQueueSender.send(cMessage); ?FONT COLOR="#000000">System.out.println("-QueueSender_send."); ?FONT COLOR="#000000"> } ?FONT COLOR="#000080">public Object InitialContext_lookup( ?FONT COLOR="#000000">javax.naming.InitialContext cContext, ?FONT COLOR="#000000">String cClassName) ?FONT COLOR="#000080">throws NamingException { ?FONT COLOR="#808080">// print out something so we know the method was invoked. ?FONT COLOR="#000000">System.out.println("+InitialContext_lookup."); ?FONT COLOR="#000000">Object obj = cContext.lookup(cClassName); ?FONT COLOR="#000000">System.out.println("-InitialContext_lookup."); ?FONT COLOR="#000080">return obj; ?FONT COLOR="#000000"> } } |
Why? The javax.jms.QueueSender and the javax.naming.InitialContext classes have overloaded methods which take the same number of parameters. So for example, when you call QueueSender.send from Visual Basic, J-Integra® is unable to determine which send method you wish to call. (Note: if the methods took different numbers of parameters there would not be a problem).
This wrapper class simply takes the required parameters and calls the appropriate send method. There are two wrapper methods, one for QueueSender.send and one for InitialContext.lookup.
Compile the bridge and the wrapper class.
Register the JVM. Note that 4000 is an arbitrarily chosen port number which was not in use on my machine. If you wish, you can check for available port numbers by using the netstat -a command which displays all the ports currently in use.
Start the JVM. Note that we pass the JMS tutorial command line options to java. This is to ensure that the JMS classes are available to the JVM.
The J-Integra® DCOM engine is now listening on port 4000 for incoming DCOM calls.
In another console configure the J2EE environment (see above) and start the J2EE server as per JMS tutorial.
Check that the MyQueue queue still exists with the command j2eeadmin -listJmsDestination.
In another console configure the J2EE environment (see above).
Start the SimpleQueueReceiver program as per JMS tutorial.
Start Visual BASIC, create a 'Standard EXE' project, put a button on a form, and double-click on the button to edit its action code. Change the code to the following:
Private Sub Command1_Click() Dim objInitialContext As Object ? Get the Initial Context which will allow us to create objects Set objInitialContext = GetObject("JMS:javax.naming.InitialContext") ? ? This is my wrapper class Dim objMyWrappers As Object Set objMyWrappers = GetObject("JMS:MyWrappers") ? Dim objQueueConnectionFactory As Object Set objQueueConnectionFactory = objMyWrappers.InitialContext_lookup(objInitialContext, "QueueConnectionFactory") ? Dim objQueue As Object ? MyQueue is the name of the queue created in the JMS tutorial Set objQueue = objMyWrappers.InitialContext_lookup(objInitialContext, "MyQueue") ? ? Dim objQueueConnection As Object Set objQueueConnection = objQueueConnectionFactory.createQueueConnection() ? Dim objQueueSession As Object ? note that the second parameter to createQueueSession should be ? Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE or Session.DUPS_OK_ACKNOWLEDGE ? and I pass zero here on the assumption that they are defined 0, 1 and 2. Set objQueueSession = objQueueConnection.createQueueSession(False, 0) ? Dim objQueueSender As Object Set objQueueSender = objQueueSession.createSender(objQueue) ? Dim objMessage As Object Set objMessage = objQueueSession.createTextMessage() objMessage.SetText ("Hello from Visual Basic") ? ? Again I use my wrapper to call the overloaded member Call objMyWrappers.QueueSender_send(objQueueSender, objMessage) MsgBox "Message sent." End Sub |
Note that the above code is simply a translation of the SimpleQueueSender.java sample in JMS tutorial.
Now run the Visual Basic application. You should see the following:
And the SimpleQueueReceive output...
The only cleanup required here is to unregister the
JVM with regjvmcmd /unregister COMtoJMS.
This is an optional step, skipping this will not affect J-Integra® or the remaining
examples.
¡¡
When you use the java2com tool to generate a type library you are using EarlyBinding. When working in Visual Basic the editor has information about the java classes you are going to access. The auto completion feature of Visual Basic will prompt you with object and method names and parameters.
The most important reason for using early binding is to take advantage of the run-time advantages. There is a performance gain because the J-Integra® runtime has less work to do in calling a method, .
The steps involved
This is identical to the LateBinding example above, so please follow those instructions once again in a new console window.
In the c:\pure\JMSExample\EarlyBinding directory, create a new directory called JMSEarly. This is where we will instruct java2com to place it's output files.
When you hit the Generate button java2com will generate an IDL specification for
the java class specified (javac.jms.QueueConnectionFactory and javax.naming.InitialContext)
and all classes that these class reference. I chose the javax.jms.QueueConnectionFactory class
because it is used in the sample code shipped with the JMS tutorial. It
just happens to pull in all the classes that I need. If it did not pull
them all in I would simply have listed all the classes (separated by spaces)
in the dialog.
As well as the IDL file, java2com generates some java source code in the JMSEarly directory. This source is required by the J-Integra® runtime to locate the appropriate classes in java. You must compile these classes as follows.
Now you must compile the IDL to generate a type library and then register this library. See pre-requisites for more information on midl.
Note that regtlb is a J-Integra® tool and that the last parameter is the
JVM name JMSEarly as will be used
when registering the COMtoJMSEarly bridge.
To finish this step, cd to the parent directory and add the JMSEarly directory to the classpath.
The second command here "set CLASSPATH" is not required, I did
that so you could see what my classpath was.
In the c:\pure\JMSExample\EarlyBinding directory create a file called COMtoJMSEarly.java and place the following code there (the only difference between this version and the Late Binding version above is the class name and the name of the JVM that is registered, these differences have been highlighted in bold ):
// This is the bridge. The VB client talks to this // process via DCOM, and this process talks to JMS. // If you have a Java server process you could add this // initialization there. import javax.naming.*; import com.linar.jintegra.*; public class COMtoJMSEarly { ?FONT COLOR="#000080">public static void main(String[] args) throws Exception ?FONT COLOR="#000000">{ ?FONT COLOR="#000080">try { ?FONT COLOR="#808080">// Generate a log just in case it all goes wrong ?FONT COLOR="#000000">com.linar.jintegra.Log.logImmediately(3, "jintegra.log"); ?FONT COLOR="#808080">// Register the JVM name with the J-Integra® runtime ?FONT COLOR="#000000">Jvm.register("JMSEarly"); ?FONT COLOR="#808080">// Wait around for a while. When the process exits the objects ?FONT COLOR="#808080">// here will no longer be accessible from COM. ?FONT COLOR="#000080">while (true) { ?FONT COLOR="#808080">// do nothing. ?FONT COLOR="#000000">Thread.sleep(10000); ?FONT COLOR="#000000"> } ?FONT COLOR="#000000"> } ?FONT COLOR="#000080">catch (Exception e) { ?FONT COLOR="#000000">System.out.println(e.getMessage()); ?FONT COLOR="#000000">e.printStackTrace(); ?FONT COLOR="#000000"> } ?FONT COLOR="#000000"> } } |
Compile the bridge.
Register the JVM. Note that 4010 is an arbitrarily chosen port number which was not in use on my machine. If you wish, you can check for available port numbers by using the netstat -a command which displays all the ports currently in use.
Start the JVM. Note that we pass the JMS tutorial command line options to java. This is to ensure that the JMS classes are available to the JVM.
The J-Integra® DCOM engine is now listening on port 4010 for incoming DCOM
calls.
In another console configure the J2EE environment (see above) and start the J2EE server as per JMS tutorial.
Check that the MyQueue queue still exists with the command j2eeadmin -listJmsDestination.
In another console configure the J2EE environment (see above).
Start the SimpleQueueReceiver program as per JMS tutorial.
Start Visual BASIC, create a 'Standard EXE" project.
Now place a button on the default form, and double-click on the button to edit its action code. Change the action code to the following:
Private Sub Command1_Click() Dim objInitialContext As JMSEarly.JavaxNamingInitialContext Set objInitialContext = New JMSEarly.JavaxNamingInitialContext ? Dim objQueueConnectionFactory As JMSEarly.JavaxJmsQueueConnectionFactory Set objQueueConnectionFactory = objInitialContext.lookup("QueueConnectionFactory") ? Dim objQueue As JMSEarly.JavaxJmsQueue Set objQueue = objInitialContext.lookup("MyQueue") ? ? Note that javax.jms.QueueConnection has two createQueueConnection methods ? Here we call the method that takes no parameters Dim objQueueConnection As JMSEarly.JavaxJmsQueueConnection Set objQueueConnection = objQueueConnectionFactory.createQueueConnection2() ? ? Note the second parameter to createQueueSession Dim objQueueSession As JMSEarly.JavaxJmsQueueSession Set objQueueSession = objQueueConnection.createQueueSession(False, JMSEarly.JavaxJmsSession_AUTO_ACKNOWLEDGE) ? ? Dim objQueueSender As JMSEarly.JavaxJmsQueueSender Set objQueueSender = objQueueSession.createSender(objQueue) ? ? Note that there are two createTextMessage methods. We use the parameterless one. Dim objMessage As JMSEarly.JavaxJmsMessage Set objMessage = objQueueSession.createTextMessage2 objMessage.SetText ("Hello from Early Bound Visual Basic") ? Call objQueueSender.send4(objMessage) ? MsgBox "Message sent using Early Binding." End Sub |
Note that the above code is simply a translation
of the SimpleQueueSender.java sample in JMS tutorial.
¡¡
Now run the Visual Basic application. You should see the following:
And the SimpleQueueReceive output...
You do not have to do this cleanup, it is optional.
The only item you need to be concerned about is the JMSEarly type library. It
is good practice to do the following cleanup before deleting the type library:
cd c:\pure\JMSExample\EarlyBinding\JMSEarly
You may also unregister the JVM with regjvmcmd /unregister JMSEarly.
The previous examples placed a string in the queue which is a good proof of concept but a little limiting. It is more likely that you will want to pass structured information to the queue, for example instructions to deposit money to an account. You could format that string to contain this information, which the SimpleQueueReceiver could extract. For example, you could pass an XML document to the queue. The SimpleQueueReceiver would then access the elements of the document using an XML parser.
Another option is to place Java objects in the queue. This has the advantage that the built in Java serialization code takes care of creating an object based on the data in the queue. You can then interact directly with the object as if you had created it locally yourself.
In this example a Visual Basic client will create an instance of an class that I have defined called LogEvent. A LogEvent object represents an event that occurred which we wish to log. So it includes properties such as a timestamp, a description and severity (e.g. Info, Error, Warning). The ObjectQueueReceiver class will read messages from the "ObjectQueue" and output the LogEvent.toString() message on the console.
The steps involved
This is identical to the LateBinding example above, so please follow those instructions once again in a new console window.
Create the c:\pure\JMSExample\ObjectQueue directory and then create a file called LogEvent.java containing the following code:
import java.io.*; import java.util.Date; public class LogEvent implements Serializable { ?FONT COLOR="#808080">// Severities could include for example Warning, Info, Error, etc. ?FONT COLOR="#000080">public int m_nEventSeverity; ?FONT COLOR="#808080">// When the event occurred ?FONT COLOR="#000080">public Date m_cTimeStamp; ?FONT COLOR="#808080">// a text message describing the event ?FONT COLOR="#000080">public String m_cEventDescription; ?FONT COLOR="#808080">// The object must have a default constructor to be accessible from VB ?FONT COLOR="#000080">public LogEvent() { ?FONT COLOR="#000000"> } ?FONT COLOR="#808080">// parameterized constructor initializing all fields ?FONT COLOR="#000080">public LogEvent(int nEventSeverity, Date cTimeStamp, String cEventDescription) { ?FONT COLOR="#000000">m_nEventSeverity = nEventSeverity; ?FONT COLOR="#000000">m_cTimeStamp = cTimeStamp; ?FONT COLOR="#000000">m_cEventDescription = cEventDescription; ?FONT COLOR="#000000"> } ?FONT COLOR="#808080">// returns a string representation of the event ?FONT COLOR="#000080">public String toString() { ?FONT COLOR="#000080">return "[ Timestamp: " + m_cTimeStamp + " Severity: " + m_nEventSeverity + " Description: " + m_cEventDescription + "]"; ?FONT COLOR="#000000"> } } |
Compile this with the command javac LogEvent.java.
Copy the SimpleQueueReceiver.java class from the JMS tutorial to this directory (c:\pure\JMSExample\ObjectQueue) and rename it ObjectQueueReceiver.java. Edit the file to make it look like the following (note that the changes are marked in red font):
/* * * Copyright 2001 Sun Microsystems, Inc. All Rights Reserved. * * This software is the proprietary information of Sun * Microsystems, Inc. Use is subject to license terms. * */ /** * The SimpleQueueReceiver class consists only of a main method, * which fetches one or more messages from a queue using * synchronous message delivery. Run this program in conjunction * with SimpleQueueSender. Specify a queue name on the command * line when you run the program. */ import javax.jms.*; import javax.naming.*; public class ObjectQueueReceiver { ?FONT COLOR="#808080">/** * Main method. * * @param args the queue used by the example */ ?FONT COLOR="#000080">public static void main(String[] args) { ?FONT COLOR="#000000">String ?FONT COLOR="#000000">queueName = null; ?FONT COLOR="#000000">Context jndiContext = null; ?FONT COLOR="#000000">QueueConnectionFactory ?FONT COLOR="#000000">queueConnectionFactory = null; ?FONT COLOR="#000000">QueueConnection queueConnection = null; ?FONT COLOR="#000000">QueueSession ?FONT COLOR="#000000">queueSession = null; ?FONT COLOR="#000000">Queue queue = null; ?FONT COLOR="#000000">QueueReceiver queueReceiver = null; ?FONT COLOR="#000000">TextMessage message = null; ?FONT COLOR="#808080">/* * Read queue name from command line and display it. */ ?FONT COLOR="#000080">if (args.length != 1) { ?FONT COLOR="#000000">System.out.println("Usage: java ObjectQueueReceiver " + ?FONT COLOR="#008000">""); ?FONT COLOR="#000000">System.exit(1); ?FONT COLOR="#000000"> } ?FONT COLOR="#000000">queueName = new String(args[0]); ?FONT COLOR="#000000">System.out.println("Queue name is " + queueName); ?FONT COLOR="#808080">/* * Create a JNDI InitialContext object if none exists yet. */ ?FONT COLOR="#000080">try { ?FONT COLOR="#000000">jndiContext = new InitialContext(); ?FONT COLOR="#000000"> } catch (NamingException e) { ?FONT COLOR="#000000">System.out.println("Could not create JNDI " + ?FONT COLOR="#008000">"context: " + e.toString()); ?FONT COLOR="#000000">System.exit(1); ?FONT COLOR="#000000"> } ?FONT COLOR="#808080">/* * Look up connection factory and queue. If either does * not exist, exit. */ ?FONT COLOR="#000080">try { ?FONT COLOR="#000000">queueConnectionFactory = (QueueConnectionFactory) ?FONT COLOR="#000000">jndiContext.lookup("QueueConnectionFactory"); ?FONT COLOR="#000000">queue = (Queue) jndiContext.lookup(queueName); ?FONT COLOR="#000000"> } catch (NamingException e) { ?FONT COLOR="#000000">System.out.println("JNDI lookup failed: " ?FONT COLOR="#000000">+e.toString()); ?FONT COLOR="#000000">System.exit(1); ?FONT COLOR="#000000"> } ?FONT COLOR="#808080">/* * Create connection. * Create session from connection; false means session is * not transacted. * Create receiver, then start message delivery. * Receive all text messages from queue until * a non-text message is received indicating end of * message stream. * Close connection. */ ?FONT COLOR="#000080">try { ?FONT COLOR="#000000">queueConnection = queueConnectionFactory.createQueueConnection(); ?FONT COLOR="#000000">queueSession = queueConnection.createQueueSession(false, ?FONT COLOR="#000000">Session.AUTO_ACKNOWLEDGE); ?FONT COLOR="#000000">queueReceiver = queueSession.createReceiver(queue); ?FONT COLOR="#000000">queueConnection.start(); ?FONT COLOR="#000080">while (true) { ?FONT COLOR="#000000">Message m = queueReceiver.receive(1); ?FONT COLOR="#000080">if (m != null) { ?FONT COLOR="#000080">if (m instanceof TextMessage) { ?FONT COLOR="#000000">message = (TextMessage) m; ?FONT COLOR="#000000">System.out.println("Reading message: " + message.getText()); ?FONT COLOR="#000000"> } ?FONT COLOR="#000080">else if (m instanceof ObjectMessage) { ?I>// cast to an ObjectMessage so we can extract the object ObjectMessage cObjectMessage = (ObjectMessage) m; Object cObject = cObjectMessage.getObject(); ?I>// make sure we got the correct type of object ?B>if (cObject instanceof LogEvent) { LogEvent cLogEvent = (LogEvent) cObject; System.out.print("Reading message: received LogEvent object,"); ?I>// invoke the toString method on the object System.out.println(" LogEvent.toString():" + cLogEvent.toString()); ? } ?B>else { System.out.println("Reading message: ignoring unexpected object of type " + cObject.getClass()); ? } ? } ?B>else { ?B>break; ? } ?FONT COLOR="#000000"> } ?FONT COLOR="#000000"> } ?FONT COLOR="#000000"> } catch (JMSException e) { ?FONT COLOR="#000000">System.out.println("Exception occurred: " + ?FONT COLOR="#000000">e.toString()); ?FONT COLOR="#000000"> } finally { ?FONT COLOR="#000080">if (queueConnection != null) { ?FONT COLOR="#000080">try { ?FONT COLOR="#000000">queueConnection.close(); ?FONT COLOR="#000000"> } catch (JMSException e) { } ?FONT COLOR="#000000"> } ?FONT COLOR="#000000"> } ?FONT COLOR="#000000"> } } |
Compile this with the command javac ObjectQueueReceiver.java.
Create a new subdirectory called c:\pure\JMSExample\ObjectQueue\JMSObject. This is where we will direct the output of the java2com tool.
When you hit the Generate button, an IDL specification for the classes will be generated. Also generated are the java classes that the J-Integra® runtime requires to expose the Java classes as COM objects.
You have created and registered the type library. Now you need to add the JMSObject directory to your CLASSPATH in this console window because this is where you will run the COMtoJMSObject bridge.
The second call to "set CLASSPATH" is not required, I did
that so you could see what my classpath was.
Copy the COMtoJMSEarly.java file from the Early Binding example to a file called COMtoJMSObject.java. Change the code as follows (changes are marked on bold font):
// This is the bridge. The VB client talks to this // process via DCOM, and this process talks to JMS. // If you have a Java server process you could add this // initialization there. import javax.naming.*; import com.linar.jintegra.*; public class COMtoJMSObject { ?FONT COLOR="#000080">public static void main(String[] args) throws Exception { ?FONT COLOR="#000080">try { ?FONT COLOR="#808080">// Generate a log just in case it all goes wrong ?FONT COLOR="#000000">com.linar.jintegra.Log.logImmediately(3, "jintegra.log"); ?FONT COLOR="#808080">// Register the JVM name with the J-Integra® runtime ?FONT COLOR="#000000">Jvm.register("JMSObject"); ?FONT COLOR="#808080">// Wait around for a while. When the process exits the objects ?FONT COLOR="#808080">// here will no longer be accessible from COM. ?FONT COLOR="#000080">while (true) { ?FONT COLOR="#808080">// do nothing. ?FONT COLOR="#000000">Thread.sleep(10000); ?FONT COLOR="#000000"> } ?FONT COLOR="#000000"> } ?FONT COLOR="#000080">catch (Exception e) { ?FONT COLOR="#000000">System.out.println(e.getMessage()); ?FONT COLOR="#000000">e.printStackTrace(); ?FONT COLOR="#000000"> } ?FONT COLOR="#000000"> } } |
Compile this with the command javac COMtoJMSObject.java.
In another console configure the J2EE environment (see above) and start the J2EE server as per JMS tutorial.
In the same console that you created the queue in, change directory to c:\pure\JMSExample\ObjectQueue and run the ObjectQueueReceiver as shown here:
Note that the last parameter is the queue name.
Start Visual BASIC, create a 'Standard EXE" project.
¡¡
Now put a button on the default form, and double-click on the button to edit its action code. Change the action code to the following:
Private Sub Command1_Click() Dim objInitialContext As JMSObject.JavaxNamingInitialContext Set objInitialContext = New JMSObject.JavaxNamingInitialContext ? Dim objQueueConnectionFactory As JMSObject.JavaxJmsQueueConnectionFactory Set objQueueConnectionFactory = objInitialContext.lookup("QueueConnectionFactory") ? Dim objQueue As JMSObject.JavaxJmsQueue Set objQueue = objInitialContext.lookup("ObjectQueue") ? ? Note that javax.jms.QueueConnection has two createQueueConnection methods ? Here we call the method that takes no parameters Dim objQueueConnection As JMSObject.JavaxJmsQueueConnection Set objQueueConnection = objQueueConnectionFactory.createQueueConnection2() ? ? Note the second parameter to createQueueSession Dim objQueueSession As JMSObject.JavaxJmsQueueSession Set objQueueSession = objQueueConnection.createQueueSession(False, JMSObject.JavaxJmsSession_AUTO_ACKNOWLEDGE) ? ? Dim objQueueSender As JMSObject.JavaxJmsQueueSender Set objQueueSender = objQueueSession.createSender(objQueue) ? Dim objEvent As JMSObject.LogEvent Set objEvent = New JMSObject.LogEvent objEvent.m_cTimeStamp = Now ? the current time objEvent.m_nEventSeverity = 7 objEvent.m_cEventDescription = "Whatever you like, from VB" ? MsgBox "Sending event " + objEvent ? Note that there are two createObjectMessage methods. We use the parameterless one. Dim objMessage As JMSObject.JavaxJmsObjectMessage Set objMessage = objQueueSession.createObjectMessage2 Call objMessage.setObject(objEvent) ? Call objQueueSender.send4(objMessage) ? MsgBox "Event logged." End Sub |
Now run the Visual Basic application. You should see the following:
And the ObjectQueueReceive output...
The only item you need to be concerned about is the JMSObject type library. It is good practice to do the following cleanup before deleting the type library:
cd c:\pure\JMSExample\ObjectQueue\JMSObject
You may also unregister the JVM with regjvmcmd /unregister JMSObject.