How to Run and Debug EJBs using jBoss 2.2.2 inside of Visual Age for Java version 3.5 (patch 2)

Author: Craig Doremus <cdoremus@vianow.com> Alex Lee <chiewkwooi@hotmail.com>

Importing jBoss into Visual Age for Java (VAJ) allows you to develop and debug EJBs using the latest Enterprise Java Beans standard (version 1.1 and Message Driven EJBs). The Enterprise version of Visual Age has built-in EJB debugging, but that edition of the IDE only supports version 1.0 of the EJB spec. Currently, Visual Age only supports JDK 1.2.2.

We created a jBoss Test Environment by manually importing jBoss source into Visual Age for Java. This import also involved a few code hacks to remove JDK 1.3 code, to change the paths to configuration files and some modification of paths inside of configuration files.

Our jBoss import does not include an integrated Jakarta-Tomcat servlet engine. IBM provides a Test Environment for Tomcat version 3.1 on their web site here, that allows debugging of JSP and servlets inside of VAJ. Both Tomcat and jBoss can be run inside of VAJ to provide the ability to debug EJBs called by servlets.

Requirements

  • Visual Age for Java Professional or Enterprise Edition Version 3.5 with patch 2 installed. Version 3.5.3 has recently been released, but there are some RMI bugs in it so we can't recommend using it at this time.

  • JBoss-2.2.2.zip downloaded (NOT the one with integrated Tomcat) Download it here

Manually importing jBoss 2.2.2 source code into Visual Age

  1. Unzip JBoss-2.2.2.zip into a temporary directory.

  2. Create a jBoss project in VAJ. If jBoss 2.0 is already installed, version it and delete all files and related projects before proceeding with the jBoss 2.2.2 install.

  3. Import source, jar and class files into VAJ from the temporary directory including:

    1. All jBoss source (src subdirectory).

      Source of org.jnp.server (both *.class and *.java files) from the vaj-jnpserver222.jar archive found in the files area on the documentation page on www.jboss.org.

      Source of org.jbossmq.* from the vaj-jbossmq222.jar archive found in the files area on the documentation page on www.jboss.org.

      org.jboss.security.SecurityAssociation source from CVS (version 1.5, which can be found here)

      org.jboss.naming.NamingService from CVS (version 1.9, which can be found here)

    2. In lib or lib/ext directory import the class files:

      	All files from minerva-1_0b3.jar
      	All files from jbosssx.jar
      	All files from jbosscx-0.2.jar except org.jboss.resource.RARDepolyer.class, org.jboss.resource.RARDepolyer$1.class and org.jboss.resource.RARDepolyer$DeploymentInfo.class.
      org.jboss.resource.RARDepolyer should be imported as source from CVS (ver 1.3) so to change tmp.properties reference (see below)
      	All files in ejxejb.jar
      	All files in ejxeditor.jar
      	All files in awt.jar
      	All files for openjms-client-patched-0.5.1.jar
      	All files from openjms-pool.jar
      	All files from openjms-rmi-patched-0.5.1.jar
      		For organization purposes you might want to put the following class into separate projects:
      	All files in jms.jar -- Java Messaging Service (into separate JMS project)
      	All files in  jaas.jar -- Java's Security API (into JAAS project)
      	All files in jmxri.jar -- Java Management Extension API (into JMX project)
      	All files in crimson.jar (into Apache Crimson project)
      	All files from xml.jar and jaxp.jar
             jdbc2_0-stdext.jar -- JDBC 2.0 Extensions
      	ejb.jar -- EJB 1.1 interfaces 
      	javax.ejb.MessageDrivenBean and javax.ejb.MessageDrivenContext from ejb2.0.jar 
            jndi.jar -- if not already in VAJ
      NOTE: HSQL and InstantDB can be finicky and freeze upon startup of jBoss. Do not install these if they are not needed. PostgreSQL or Oracle are preferred alternatives.
            hsql.jar -- optional HSQL database.  
            jpl-util-0_5b.jar
            jta-spec1_0_1.jar -- (javax.transaction package will be updated elsewhere)
            mail.jar -- JavaMail API
            activation.jar -- Java Activation Frameworks
      	connector.jar -- Java Connector Architecture
              
  4. Directories to be added to VAJ's <vaj.home>/ide/project_resources/jboss directory from jBoss zip archive:

            bin
            client
            conf/default
            db -- for InstantDB and Hypersonic
            deploy -- EJB autodeploy directory
            lib (with ext subdir) -- all the jars
            log
            tmp
    
  5. Change the references to configuration files in the source code:

    • jboss.conf:

      In org.jboss.Main.Main() add conf/default in line:

      URL mletConf = mlet.getResource("conf/default/jboss.conf")

    • jboss.jcml:

      In org.jboss.configuration.ConfigurationService.loadConfiguration() add conf/default in line:

      InputStream conf = Thread.currentThread().getContextClassLoader().getResourceAsStream "conf/default/jboss.jcml");

      In org.jboss.configuration.ConfigurationService.loadConfiguration() add conf/default in line:

      conf = Thread.currentThread().getContextClassLoader().getResourceAsStream("conf/default/jboss.jcml");

    • jndi.properties

      org.jboss.naming.NamingService.initService() add conf/default in line:

      System.getProperties().load(Thread.currentThread().getContextClassLoader().getResourceAsStream("conf/default/jndi.properties"));

      org.jboss.Main.Main() add conf/default in line:

      URL jndiLocation = this.getClass().getResource("conf/default/jndi.properties");

    • tmp.properties

      org.jboss.deployment.J2eeDeployer.initService() add /tmp in line:

      URL tmpDirUrl = getClass().getResource("/tmp/tmp.properties");

      org.jboss.resource.RARDeployer.initService() add /tmp in line:

      URL tmpPropURL = getClass().getResource("/tmp/tmp.properties");

    • db.properties

      org.jboss.ejb.plugins.StatefulSessionFilePersistenceManager.init() add db/ in line:

      File databaseDir = new File(getClass().getResource("db/db.properties").getFile()).getParentFile();

      org.jboss.jdbc.HypersonicDatabase.startService() add /db/ in line:

      URL dbLocator = getClass().getResource("/db/db.properties");

    • standardjaws.xml

      org.jboss.ejb.plugins.jaws.metadata.JawsXmlFileLoader.load() add conf/default in line:

      URL stdJawsUrl = classLoader.getResource("conf/default/standardjaws.xml");

    • standardjboss.xml

      org.jboss.metadata.XmlFileLoader.load() add conf/default in line:

      URL defaultJbossUrl = Thread.currentThread().getContextClassLoader().getResource("conf/default/standardjboss.xml");

    • jnp.properties

      org.jnp.server.Main.Main() add conf/default in line:

      System.getProperties().load(getClass().getClassLoader().getResourceAsStream("conf/default/jnp.properties"));

    • log.properties

      org.jboss.logging.FileLogging.openLogFile() add /log in line:

      URL properties = getClass().getResource("/log/log.properties");

    • jboss-auto.jcml

      org.jboss.configuration.ConfigurationService.loadConfiguration() add conf/default in line:

      conf = Thread.currentThread().getContextClassLoader().getResourceAsStream("conf/default/jboss-auto.jcml");

      org.jboss.configuration.ConfigurationService.saveConfiguration() add conf/default in line:

      URL confFile = Thread.currentThread().getContextClassLoader().getResource("conf/default/jboss-auto.jcml");

    • mail.properties

      org.jboss.mail.MailService.startService() add conf/default in line:

      if (properties == null) {properties = "conf/default/mail.properties";}

      in jboss.jcml (in VAJ's <vaj.home>/ide/project_resources/jboss/conf/default directory) add conf/default in mail.properties line:

      <attribute name="ConfigurationFile">conf/default/mail.properties</attribute>

    • jbossmq.properties

      org.jbossmq.Log.getLevel() add conf/default in line:

      InputStream in = Thread.currentThread().getContextClassLoader().getResource("conf/default/jbossmq.properties").openStream();

    • jbossmq.xml

      org.jbossmq.server.JMSServer.saveConfig() add conf/default in line:

      String file = getClass().getClassLoader().getResource("conf/default/jbossmq.xml").getFile();

      org.jbossmq.server.StartServer.run() add conf/default in line:

      InputStream in = getClass().getClassLoader().getResource("conf/default/jbossmq.xml").openStream();

      org.jbossmq.persistence.PersistenceManager.PersistenceManager() add conf/default in line:

      URL configFile = getClass().getClassLoader().getResource("conf/default/jbossmq.xml");

  6. Properties to change in org.jboss.Main (right click on class and bring up Properties dialog) (NOTE -- please adjust the path to point to your Visual Age install directory):

    1. Program tab:

      1. Command line argument:

      conf/default

      2. Properties: (as listed)

      jboss.home="e:/Program Files/Ibm/VisualAge for Java/ide/project_resources/jboss" Note that this command line should be quoted if there are spaces in the command line (like Program Files).

    2. Classpath tab:

      1. Project Path: Add any other projects that jBoss needs if classes it contains are not in the jBoss project.

      2. Extra Directories Path:

      1. Add the following jar files from the <jboss.home>/lib or <jboss.home>/lib/etx directory : lib\ext\dynaserver.jar;lib\ext\ejxjaws.jar;lib\ext\ejxjboss.jar;lib\ext\exolabcore-0.1.jar;lib\ext\gnu-regexp-1.0.8.jar;lib\ext\jboss.jar;lib\ext\jbossmq.jar;lib\ext\jetty-service.jar;lib\ext\jmxtools.jar;lib\ext\jnpserver.jar;lib\ext\tomcat-service.jar;lib\jboss-jaas.jar

      2. Add the following directories: "./conf/default;./db;./deploy;./log"

  7. For org.jboss.jmx.connector.rmi.RMIConnectorImpl, org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker, org.jbossmq.distributed.server.ConnectionReceiverRMIImpl and org.jbossmq.distributed.server.DistributedJMSServerRMIImpl, manually generate RMI stub/skeleton using VAJ's built-in RMI tool (Right click on the class and select Tools --> Generate RMI/JDK 1.2 --> stubs/skeleton). You might need to temporarily move java.transaction.* into the jboss project for the rmic compiler to function without errors for JRMPContainerInvoker or directly import the RMI stub from the binary jboss.jar (org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker_Stub.class).

  8. In jboss.conf (in <jboss.home>/conf/default directory):

    • Change all references from ../../ in file to ./ using search and replace

    • Change references from ../xml.jar to ./xml.jar

  9. In jboss.jcml (in <jboss.home>/conf/default directory) change ../deploy to ./deploy in this tag:

    				
      <mbean code="org.jboss.ejb.AutoDeployer" name="EJB:service=AutoDeployer">
        <attribute name="Deployer">J2EE:service=J2eeDeployer</attribute>
        <attribute name="URLs">./deploy</attribute>
      </mbean>
    	

    a. Change single reference from ../conf/default/instantdb.properties to ./conf/default/instantdb.properties

  10. In instantdb.properties (in <jboss.home>/conf/default directory) change all references from ../../ to ./.

  11. In org.jboss.util.Shutdown.preRegister(), comment out this shutdown hook code:

    	  /* Modified by Craig since addShutdownHook is implemented in JDK 1.3
    	  try
    	  {
    		  
    		 Runtime.getRuntime().addShutdownHook(new Thread()
    		 {
    			public void run()
    			{
    			   System.out.println("Shutting down");
    			   
    			   // Make sure all services are down properly
    			   shutdownServices();
    			   
    			   System.out.println("Shutdown complete");
    			}
    		 });
    		 log.log("Shutdown hook added");
    		 */
    	  //} catch (Throwable e)
    	  //{
    		 log.error("Could not add shutdown hook");
    	  //}
    		
    			
  12. Removing InstantDB from VAJ (do this if it freezes VAJ during startup).

    This can be done by remove all references to InstantDB in the <jboss.home>/conf/default/jboss.jcml file.

Running and debugging EJBs inside of Visual Age

  1. Create META-INF subdirectory in the deploy directory of <jboss.home>.

    a. Add ejb-jar.xml and both jboss.xml and jaws.xml (if needed) to the directory.

  2. Run org.jboss.Main using VAJ run command to start jBoss.

  3. Make sure any projects that contain EJBs that you are developing are in the classpath of org.jboss.Main.

  4. If running EJBs from servlets/JSPs, make sure that jBoss's project is in Tomcat's classpath (the com.ibm.ivj.tomcat.TomcatRunner class). If you are calling EJBs from a client class with a main() method, make sure the jBoss project is in its classpath in addition to all jars from the <jboss.home>/client directory.

  5. To debug, set breakpoints inside of EJB bean class.

  6. To allow changes to EJBs to take effect in VAJ, either restart jBoss or touch one of the XML files in the <jboss.home>/deploy/META-INF directory.