Accessing JMS from VB

Java/J2EE COM Interoperability Products Page

This example demonstrates how to access a JMS topic from VB. J-Integra® for COM is a Java interoperability component that bridges Java and JMS. It provides bi-directional access of Java objects and COM components. It includes:

The JMS Provider can be running on any platform, such as Solaris, UNIX, Linux, etc.

This example assumes the reader has working knowledge of Java, JMS, VB and hands-on experience with J-Integra®
(specifically accessing Java objects from COM).

This is not an introductory example. If you have not used J-Integra® before, please take a look at the basic step-by-step
COM accessing Java examples first.

This example uses Suns' J2EESDK1.3, and is based on  Sun's Java Message Service tutorial. (Section 4.3 - Simple Publish/Subscribe). Make sure Sun's example runs successfully before attempting to use a VB client. It is very difficult to troubleshoot the system when the JMS part is not working properly in the first place.

The steps involved

To access JMS in  DCOM mode, we need a bridging class that registers a JVM with J-Integra® runtime,
and handles Java object instantiation.

Since we need to implement a Java interface, we must use Early Binding and generate the Java proxies and the Type Library.

  1. Set up the project folders.

  2. Create and compile a Bridging Class.

  3. Generate and compile the Java proxies for the JMS classes.

  4. Compile and register the COM Type Library (.tlb)  for those JMS classes.

  5. Register the JVM on the Windows Machine.

  6. Create a Visual Basic Client application, and the Message Listener COM object.

  7. Run the system.

  8. Optionally, run the Java Bridging Class on a non-Windows machine. 

  9. Troubleshooting.

Set up the Project Folders

  1. Create a folder and name it JMStoVB.

  2. In this folder, create folders named Javax and VBClient.

Create a Bridging JVM

  1. In the JMStoVB folder, create a Java class named COMtoJMSEarly.

  2. Cut and paste the code below (note the JVM name: "JMSEarly"):

    import com.linar.jintegra.*; 
     
    public class COMtoJMSEarly{ 
     
    public static void main(String[] args)  { 
       
    try
           
    // Generate a log just in case it all goes wrong 
            com.linar.jintegra.Log.logImmediately(
    3, "jintegra.log"); 
           
    // com.linar.jintegra.AuthInfo.setDefault(
           //                   "NT DOMAIN"
    , "NT USER NAME", "NT PASSWORD"); 

     
           
    // Register the JVM name with the J-Integra® runtime 
            com.linar.jintegra.Jvm.register(
    "JMSEarly"); 
     
           
    // Wait around for a while. When the process exits the objects 
           
    // here will no longer be accessible from COM. 
           
    while(true) { 
             
    // do nothing. 
              Thread.sleep(
    10000); 
            } 
        } 
    catch (Exception e) { 
          System.out.println(e.getMessage()); 
          e.printStackTrace(); 
        } 
      } 

Generate and Compile the Proxies

  1. From the command line, open the JMStoVB/Javax directory and run the java2com tool.

  2. Click "Add...", locate j2ee.jar and click Ok.

  3. From the j2ee.jar folder, select the following classes:
    javax.naming.InitialContext 
    javax.jms.TopicConnectionFactory 
    javax.jms.Topic 
    javax.jms.TopicConnection 
    javax.jms.TopicSession
    javax.jms.TopicSubscriber 
    javax.jms.Message 
    javax.jms.MessageListener

  4. Select Save Settings from the File menu

  5. If you need to regenerate the Type Library and the proxies, java2com will remember the settings,
    and will reuse the Type Library ID, the Class IDs, and the Interface IDs.

Compile and Register the Type Library

  1. From the command line, type:
    midl Javax.idl
    regtlb Javax.tlb JMSEarly

    Note that we specify JSMEarly as the JVM name.

Register the JVM on a Windows Machine

  1. Run the regjvm tool.

  2. Click New JVM and specify JMSEarly as the JVM name. Set the Port to 4010 (can be any available port).

  3. Click Save JVM.

Create a VB Client Application and the Message Listener COM Object

  1. In the JMStoVB/VBClient folder, create an ActiveX EXE project—a standard EXE will  not work in this case, as we need to export a COM object.

  2. Click Project/References, and select the Javax type library.

  3. The project should have  a Class Module, a Form, and a Module:

  4. Create the TextMessageHandler Class, and make it implement Javax.JavaxJmsMessageListener interface:

    The code for the TextMessageHandler:

    Option Explicit
    Option Base 0
    
    Implements Javax.JavaxJmsMessageListener
    
    Private Sub Class_Initialize()
        MsgBox "JMS Text Message Listener Initialized."
    End Sub
    
    Private Sub JavaxJmsMessageListener_onMessage(ByVal p1 As Javax.JavaxJmsMessage)
        Dim message As Javax.JavaxJmsTextMessage
        Set message = p1
        MsgBox message.GetText
    End Sub

  5. Create the Form1  Form:

  6. The code for the Form:
    (Note that the code follows the equivalent Java JMS subscriber code very closely)

    Option Explicit
    
    Dim InitialContext                   As Javax.JavaxNamingInitialContext 
    Dim TopicConnectionFactory As Javax.JavaxJmsTopicConnectionFactory
    Dim Topic                              As Javax.JavaxJmsTopic
    Dim TopicConnection             As Javax.JavaxJmsTopicConnection
    Dim TopicSession                   As Javax.JavaxJmsTopicSession
    Dim TopicSubscriber              As Javax.JavaxJmsTopicSubscriber
    Dim TopicListener                  As TextMessageHandler
    
    Private Sub Command1_Click() 
        Set InitialContext = New Javax.JavaxNamingInitialContext ' Create Java Naming Context
       
       ' Look up the connection factory
        Set TopicConnectionFactory = InitialContext.lookup("TopicConnectionFactory")  
        Set Topic = InitialContext.lookup("MyTopic") ' Look up the Topic "MyTopic"
      
        'Create topic  connection
        Set TopicConnection = TopicConnectionFactory.createTopicConnection2
        Set TopicSession = TopicConnection.createTopicSession(False, 0) 'Create topic session
        Set TopicSubscriber = TopicSession.createSubscriber2(Topic) ' Create topic subscriber
        Set TopicListener = New TextMessageHandler ' Create the Message Handler
        Call TopicSubscriber.setMessageListener(TopicListener) ' Set the message Handler
        TopicConnection.start ' Connect to the topic.
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        TopicConnection.Close ' Close the connection, and release the resources.
        Set TopicListener = Nothing 
    End Sub

  7. Create the Main Module:
    The code:

    Sub Main()
        Dim frm As New Form1
        Load frm 
        frm.Show
    End Sub

  8. Click Project/Properties, and select Sub Main as the Startup Object.

  9. Build the project.

Run the System

  1. Prepare a startup script (runJVM.bat) for the Bridging Class, and  start the Bridging Class.
    If you are running from a non-Windows machine, use the equivalent shell script.

    set JAVA_HOME=c:\jdk1.3.1_01
    set J2EE_HOME=C:\j2sdkee1.3
    
    set classpath=.;%classpath%
    set classpath=c:\JMStoVB\Javax;%classpath%
    set classpath=%J2EE_HOME%\lib\j2ee.jar;%classpath%
    set classpath=%J2EE_HOME%\lib\locale;%classpath%
    set classpath=c:\jintegra\lib\jintegra.jar;c:\jintegra\lib;%classpath%
    set path=
    set path=%J2EE_HOME%\bin
    set path=%JAVA_HOME%\bin;%path%
    
    java -Djms.properties=%J2EE_HOME%\config\jms_client.properties -DJINTEGRA_DCOM_PORT=4010 COMtoJMSEarly
    
    pause

  2. We put the following on the classpath (the directory names on your machine may be different):

    1. The directories JMStoVB, and "JMStoVB/Javax

    2. The jintegra.jar

    3. The J-Integra® license directory (jintegra/lib)

    4. The J2EE classes: j2ee.jar, and \lib\locale

  3. Run the Bridging Class with the JINTEGRA_DCOM_PORT set to 4010, the JVM port number.

  4. Make sure that the Topic (MyTopic), has been created. (This is done in Sun's JMS tutorial.)

  5. Start the J2EE server: From the command line, type
    j2ee -verbose

  6. Start the VB Client,  and click Start Listening to subscribe to the Topic and start listening for messages.

  7. Start the Topic Publisher, as specified in the JMS tutorial and observe the callbacks.

  8. The output of the Bridging Class in shown in the following screen shot.

Optionally, run the Bridging Class from a Remote, Non-Windows Machine

  1. Specify the machines' propert network name to the regvjm tool instead of localhost

  2. Uncomment the com..linar.jintegra.AuthInfo.setDefault("NT DOMAIN", "NT USER NAME", "NT PASSWORD"); 
    line in the bridging class, and recompile it. (The Credentials in "setDefault" are the valid credentials for a machine running the VB client).

  3. Make sure that the TextMessageHandler object is configured to allow DCOM access (see Configuring DCOM for Remote Access).

  4. Make sure that the Authentication property of the object is set to Connect.

Troubleshooting

  1. VB client raises Runtime Error 5 or java.lang.ClassNotFoundException

    These errors indicate  that the Java classes you are trying to instantiate from VB (the JMS classes) could not be located and/or instantiated. You may not have placed them on the Classpath, or you have a typo in Class's name in  the VB code
    Please see the Common Errors section of the Knowledge Base for additional causes of this error.

    2. VB Client raises an error similar to the one below:

    Make sure that the proxies (IID... files)  have been compiled and placed on the Classpath.

    3. The VB Client can add the Message Listener object successfully, but no callbacks are coming. The VB client does not raise any errors.

    There may be a problem with authentication. Check the Java console and the J-Integra® log (callbacks.log) for occurrences of the AutomationException: 0x80070005 - General access denied error and the AutomationException: 0x5 - Access is denied error. Make sure that the CallbackObject has been configured to allow DCOM access, and the credentials supplied in AuthInfo.setDefault(..) are valid. Make sure that the CallbackObject's Authentication level is set to Connect in DCOMCNFG. Consult the Configuring DCOM for Remote Access section of the documentation on resolving this error.

    4. The VB Client raises and error: Can't find SerialContextProvider

    Make sure that the J2EE server is running.

    Check the Bridging Class console for errors.