You are viewing a plain text version of this content. The canonical link for it is here.
Posted to soap-user@xml.apache.org by gr...@i2image.com on 2001/02/15 22:00:32 UTC

v1.14 HOW TO: Configure addressbook, Tomcat/Catalina, SOAP

/**
 * Title:            How to configure Tomcat, SOAP and the addressbook
sample servlet.
 * Last Modified by: $Author: gleichtm $
 * Last mod:      $Date: 2001/02/15 20:56:13 $
 * Filename:      $RCSfile: TomcatSoapSetup.txt,v $
 * Copyright:        Copyright (c) 1999-2001
 * Company:          Quintiles Intelligent Imaging
 * @author           Gregg Leichtman
 * @version          $Name:  $ $Revision: 1.14 $
 * Description:      Describes the environment variables, directory
structure, commands and files needed
 *                   to setup Tomcat 4.0b1, SOAP 2.0 and the SOAP
addressbook sample servlet.
 */

I have posted this in the hopes that it will help others that have run in
to problems setting up Tomcat with SOAP. What I will describe applies to
Tomcat 4.0b1 running under NT 4.0 SP6.1 as localhost on port 8080 although
the caveats should apply to previous versions and other OS's. These notes
represent my current understanding of Tomcat configuration and a number of
very frustating days used in setting up Tomcat 4.0b1. If anything is in
error, I apologize in advance and welcome any and all corrections and
clarifications.


First, configure Tomcat as described in the SOAP docs for installation (I'm
sure you've done that successfully and that's why you're looking at this in
quiet desperation/frustration).

Next, if you are getting the following error:

org.xml.sax.SAXParseException: The markup in the document preceding the
root
element must be well-formed.
        at
org.apache.xerces.framework.XMLParser.reportError(XMLParser.java:1016)
        at
org.apache.xerces.framework.XMLDocumentScanner.reportFatalXMLError(XMLDocumentScanner.java:625)
        at
org.apache.xerces.framework.XMLDocumentScanner$XMLDeclDispatcher.dispatch(XMLDocumentScanner.java:804)
        at
org.apache.xerces.framework.XMLDocumentScanner.parseSome(XMLDocumentScanner.java:380)
        at org.apache.xerces.framework.XMLParser.parse(XMLParser.java:908)
        at
org.apache.soap.util.xml.XercesParserLiaison.read(XercesParserLiaison.java:85)
        at org.apache.soap.rpc.Call.invoke(Call.java:157)
        at
org.apache.soap.server.ServiceManagerClient.invokeMethod(ServiceManagerClient.java:110)
        at
org.apache.soap.server.ServiceManagerClient.deploy(ServiceManagerClient.java:123)
        at
org.apache.soap.server.ServiceManagerClient.main(ServiceManagerClient.java:188)

Exception in thread "main" [SOAPException: faultCode=SOAP-ENV:Protocol;
msg=java.lang.NoSuchMethodError
        at org.apache.soap.util.xml.QName.<init>(QName.java:80)
        at org.apache.soap.util.xml.QName.matches(QName.java:146)
        at org.apache.soap.Envelope.unmarshall(Envelope.java:210)
        at
org.apache.soap.server.http.RPCRouterServlet.doPost(RPCRouterServlet.java:182)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
        at
org.apache.tomcat.core.ServletWrapper.doService(ServletWrapper.java:404)
        at org.apache.tomcat.core.Handler.service(Handler.java:286)
        at
org.apache.tomcat.core.ServletWrapper.service(ServletWrapper.java:372)
        at
org.apache.tomcat.core.ContextManager.internalService(ContextManager.java:797)
        at
org.apache.tomcat.core.ContextManager.service(ContextManager.java:743)
        at
org.apache.tomcat.service.http.HttpConnectionHandler.processConnection(HttpConnectionHandler.java:210)
        at
org.apache.tomcat.service.TcpWorkerThread.runIt(PoolTcpEndpoint.java:416)
        at
org.apache.tomcat.util.ThreadPool$ControlRunnable.run(ThreadPool.java:498)
        at java.lang.Thread.run(Thread.java:484)]
        at org.apache.soap.rpc.Call.invoke(Call.java:167)
        at
org.apache.soap.server.ServiceManagerClient.invokeMethod(ServiceManagerClient.java:110)


        at
org.apache.soap.server.ServiceManagerClient.deploy(ServiceManagerClient.java:123)
        at
org.apache.soap.server.ServiceManagerClient.main(ServiceManagerClient.java:188)

then most likely you are running SOAP 2.1. I have NOT been successful in
using SOAP 2.1 with the addressbook example (If anyone has, I would
appreciate hearing about it). My earlier posts about success in using SOAP
2.1 were in error (that's what I get when I swap jar files back and forth
50 times). I have received this error when I used both Xerces 1.2.3 and
Xerces 1.3.0 and actually swapped the SOAP 2.1 jar file into the WEB-INF
lib directory and tried to deploy the addressbook services after stopping
the server, discarding the command shell I was working within (this is
important, I have had problems because of this), discarding the work
directory, restarting the server and issuing the deploy services command
(from the SOAP 2.1 addressbook\testit.cmd file):

java org.apache.soap.server.ServiceManagerClient
http://localhost:8080/soap/servlet/rpcrouter deploy
FULL_PATH\DeploymentDescriptor.xml (this is all on one line)

where FULL_PATH is the path to the DeploymentDescriptor.xml file inside the
...\samples\addressbook directory. Stopping the server, swapping to a SOAP
2.0 jar, restarting the server and then issuing the deployment command
again succeeds. Therefore, I conclude that SOAP 2.1 MAY have a problem in
setting up the DeploymentDescriptor.xml file for SAX parsing. So, beware of
mixing SOAP 2.0 and 2.1 pieces together.

I have also found that if you are inside the ...\samples\addressbook
directory, it is not necessary to issue the full path to the descriptor
file. If you issue this command outside the ...\samples\addressbook
directory without specifying the full path to the descriptor file, I have
found that you will receive the following error:

SOME_PATH_OUTSIDE_addressbook>java
org.apache.soap.server.ServiceManagerClient http:
//localhost:8080/soap/servlet/rpcrouter deploy DeploymentDescriptor.xml

Exception in thread "main" java.io.FileNotFoundException:
DeploymentDescriptor.xml (The system cannot find the file specified)
        at java.io.FileInputStream.open(Native Method)
        at java.io.FileInputStream.<init>(FileInputStream.java:64)
        at java.io.FileReader.<init>(FileReader.java:38)
        at
org.apache.soap.server.ServiceManagerClient.main(ServiceManagerClient.java:185)

Note that the SOAP documentation clearly states that "Apache-SOAP requires
Apache Xerces (Java) version 1.1.2 or higher." Make sure you are using a
current version of the Xerces parser (currently at 1.3.0). Also, note (as
many many individuals have already pointed out) that the xerces jar file
needs to be declared first in you environment classpath. This is because
"these versions support the DOM level 2 candidate recommendation which
provides namespace support. If you have any other XML parsers (or other JAR
files which may have the org.w3c.dom.* interfaces), then it is very
important that you place the JAR file xerces.jar from Xerces at the front
of your classpath. Apache-SOAP will not work otherwise."

Also, William Brogden points out that "even if Xerces.jar is first on your
classpath, Java will find
an earlier generation parser if it is in the JDK/jre/lib/ext directory."

Note that Tomcat (alias Catalina in Tomcat 4.x) creates a "work" directory
under the CATALINA_HOME (TOMCAT_HOME for older versions) directory defined
by the environment variable CATALINA_HOME or by the JVM directive
-Dcatalina.home=%CATALINA_HOME% (which appears to override the environment
variable) (see catalina.bat in bin directory). This work directory caches
compiled JSP scripts across runs of the server. If you look inside this
directory (after having run SOAP and it fails in certain interim states,
but not when it runs successfully), you potentially will see the java
source code files that are dynamically created from the jsp scripts "list",
"deploy" and "undeploy" and that these source code files are dynamically
compiled into class files that are then dynamically loaded by the server.
(Interestingly the dynamically created SOAP Java source files indicate that
they are in package admin, yet they are stored one directory above the
admin directory and the admin directory remains empty when things are
running "correctly.") Therefore, if you change your setup, especially when
you are having problems getting the server and SOAP to work together, it is
absolutely critical that the server be stopped, the work directory be
thrown away in the trash and the server be restarted. I spent days trying
to fix a configuration problem that I probably had fixed days earlier,
because I failed to discard the work directory.

Tomcat has its own internal class loaders (see
tomcat-4.0-b1\jakarta-tomcat-4.0-b1-src\catalina\docs\dev\classloaders.html
in the distribution for a complete description of the class loaders). This
appears to cause no end of confusion for new users. This means that it has
its own internal classpaths that are independent of the classpath provided
through the shell environment variable CLASSPATH or as an argument to the
JVM using -cp or -classpath. Because of this Tomcat loads unjar'd classes
and jar'd classes from two primary locations (see the URL above for
others). Tomcat can load unjar'd classes from a directory called "classes"
that must be located directly under the Tomcat home directory and it can
load jar'd classes (i.e. ones in a jar file) from a directory called "lib"
that must also be located directly under the Tomcat home directory. In
addition to these two locations, Tomcat will load unjar'd and jar'd class
files from directories named "classes" and "lib" respectively when these
directories are placed in your webapps application directory under WEB-INF.
For example, using the SOAP application, you would place its classes and
jar files in directories classes and lib as follows:

YOUR_TOMCAT_HOME\webapps\soap\WEB-INF\classes

and/or

YOUR_TOMCAT_HOME\webapps\soap\WEB-INF\lib

Note that when you place your unjar'd classes in either "classes"
directory, you must maintain the package hierarchy of the classes. For
example, if you place a compiled class myclass.class into "classes" under
WEB-INF that has a package of a.b.c, you must create a directory structure
of:

YOUR_TOMCAT_HOME\webapps\soap\WEB-INF\classes\a\b\c\myclass.class

The class loader document indicates that any class or jar files placed in
the respective "classes" and/or "lib" directories directly under the Tomcat
home become available to all web applications. It also states that Tomcat
creates a separate class loader for each web application (i.e. different
applications will not see classes from other applications) when the
"classes" and "lib" directories are placed under the application's WEB_INF
directory.

Make sure the soap.jar file is in your environment classpath just after
xerces.jar. The soap.jar file should also be located in either of the lib
directories described above. I placed it under ...\soap\WEB-INF\lib, since
it is specific to the soap application.

Make sure that you have Sun's Java Mail mailapi.jar (the other mail jars
are unneeded) and the JavaBeans Activation Framework activation.jar files
in your environment classpath. Both are needed for SOAP.

In order to run the SOAP samples, you should copy the samples directory (as
you received it from the distribution) to:

YOUR_TOMCAT_HOME\webapps\soap\WEB-INF\classes

You must also make sure that this directory is in your environment
classpath. This will allow you to run the address book SOAP remote clients
in testit (described below) or independently as described in the
addressbook README file. If you fail to put this directory in your
classpath, you will see errors of the type:

Getting info for "Mr Good"
Exception in thread "main" java.lang.NoClassDefFoundError:
samples/addressbook/GetAddress

In the catalina.bat file in the bin directory under YOUR_TOMCAT_HOME change
the following lines to include your environment's classpath as follows:

FROM:

rem ----- Set Up The Runtime Classpath
----------------------------------------set

CP=%CATALINA_HOME%\bin\bootstrap.jar;%JAVA_HOME%\lib\tools.jar
set CLASSPATH=%CP%
echo Using CLASSPATH: %CLASSPATH%

TO:

rem ----- Set Up The Runtime Classpath
----------------------------------------set

CP=%CATALINA_HOME%\bin\bootstrap.jar;%JAVA_HOME%\lib\tools.jar
set CLASSPATH=%CLASSPATH%;%CP%
echo Using CLASSPATH: %CLASSPATH%

Bring up a DOS command prompt and go to the CATALINA_HOME\bin directory and
startup the server with:

startup

and you should see a command prompt window come up with (for Tomcat 4.0b1
of course):

Starting service Tomcat-Standalone
Apache Tomcat/4.0-b1
Starting service Tomcat-Apache
Apache Tomcat/4.0-b1

In the SOAP 2.1 (but not SOAP 2.0) distribution there is an NT command file
called testit.cmd. Copy testit.cmd from the SOAP 2.1 directory to the
addressbook directory where you put the SOAP 2.0 samples at:

YOUR_TOMCAT_HOME\webapps\soap\WEB-INF\classes\samples\addressbook

and run testit or alternatively run a SOAP client manually using the
command described in the addressbook README as an example.

The testit command should walk through all the addressbook SOAP clients and
exercise them.

This attempts to deploy the addressbook services using the XML descriptor
file and the deploy.jsp Java server page (in ...\soap\admin). This is far
easier and much less error prone than attempting to deploy the address book
services using the web page that can be obtained at URL:

http://localhost:8080/soap/admin/index.html

Note that the SOAP rpcrouter can be checked for proper functioning by going
to URL:

http://localhost:8080/soap/servlet/rpcrouter

where you will see:

SOAP RPC Router
Sorry, I don't speak via HTTP GET- you have to use HTTP POST to talk to me.

when it is working properly.

Both the SOAP admin clients and visitation of the rpcrouter can be found
at:

http://localhost:8080/soap

If you succeed, you should see:

SOAP Service Manager: Unable to read 'DeployedServices.ds': assuming fresh
start
>>(Wed Feb 14 09:54:55 EST 2001) Processing SOAP request...

in the DOS command shell window where the server is sending its output.
This creates a DeployedServices.ds file in the bin directory where you
started the server.

You can then see your deployed services by issuing:

java org.apache.soap.server.ServiceManagerClient
http://localhost:8080/soap/servlet/rpcrouter list

which yields:

Deployed Services:
        urn:AddressFetcher

This is exactly the same as clicking on the List button on the SOAP admin
page.

Note that if you see a SAX parse error, then you have at least succeeded in
getting the server to execute the Java Server Page deploy.jsp located in
YOUR_TOMCAT_HOME\webapps\soap\admin. This means that the server has
successfully created the java source code for the JSP, compiled it and run
it. If you instead attempt to list from the web admin facility by clicking
on the list button, then a Java source file will be generated along with a
class file that looks like:

_0002fadmin_0002flist_0002ejsplist_jsp_0.java

and

_0002fadmin_0002flist_0002ejsplist_jsp_0.class

in the directory:

YOUR_TOMCAT_HOME\work\localhost\soap

Interestingly, an admin directory is created, but the _0002fadmin....class
file is placed above it in the directory hierarchy even though examination
of the source code indicates that the source is defined in package admin.

If you do get the services to depoly then the addressbook example should
work and you should be able run testit. Successfully running testit yields:

This test assumes a server URL of
http://localhost:8080/soap/server/rpcrouter
Deploying the addressbook service...
.
Verify that its there
Deployed Services:
        urn:AddressFetcher
.
Getting info for "Mr Good"

123 Main Street
Anytown, NY 12345
(123) 456-7890
.
Adding "John Doe"
John Doe has been added.
.
Query "Mr Doe" to make sure it was added

123 Main Street
AnyTown, SS 12345
(800) 555-1212
.
Adding an XML file of listings
Added 2 listings.
.
Get everyone!
<AddressBook>
  <Listing>
    <Name>John Doe</Name>
    <Address>
      <StreetNum>123</StreetNum>
      <StreetName>Main Street</StreetName>
      <City>AnyTown</City>
      <State>SS</State>
      <Zip>12345</Zip>
      <PhoneNumber>
        <AreaCode>800</AreaCode>
        <Exchange>555</Exchange>
        <Number>1212</Number>
      </PhoneNumber>
    </Address>
  </Listing>
  <Listing>
    <Name>Bob Q. Public</Name>
    <Address>
      <StreetNum>456</StreetNum>
      <StreetName>North Whatever</StreetName>
      <City>Notown</City>
      <State>ME</State>
      <Zip>12424</Zip>
      <PhoneNumber>
        <AreaCode>987</AreaCode>
        <Exchange>444</Exchange>
        <Number>5566</Number>
      </PhoneNumber>
    </Address>
  </Listing>
  <Listing>
    <Name>Dave Davis</Name>
    <Address>
      <StreetNum>919</StreetNum>
      <StreetName>Baker Lane</StreetName>
      <City>Sunnytown</City>
      <State>UT</State>
      <Zip>43434</Zip>
      <PhoneNumber>
        <AreaCode>789</AreaCode>
        <Exchange>654</Exchange>
        <Number>3210</Number>
      </PhoneNumber>
    </Address>
  </Listing>
  <Listing>
    <Name>John B. Good</Name>
    <Address>
      <StreetNum>123</StreetNum>
      <StreetName>Main Street</StreetName>
      <City>Anytown</City>
      <State>NY</State>
      <Zip>12345</Zip>
      <PhoneNumber>
        <AreaCode>123</AreaCode>
        <Exchange>456</Exchange>
        <Number>7890</Number>
      </PhoneNumber>
    </Address>
  </Listing>
  <Listing>
    <Name>Mary Smith</Name>
    <Address>
      <StreetNum>888</StreetNum>
      <StreetName>Broadway</StreetName>
      <City>Somewhere</City>
      <State>FL</State>
      <Zip>87654</Zip>
      <PhoneNumber>
        <AreaCode>222</AreaCode>
        <Exchange>333</Exchange>
        <Number>4444</Number>
      </PhoneNumber>
    </Address>
  </Listing>
</AddressBook>
.
Undeploy it now
.
Verify that its gone
Deployed Services:
As you can see, almost all problems stem from not setting up the classpaths
properly and not throwing away the work directory.

I have successfully run Tomcat 4.0b1 with SOAP 2.0 but NOT with SOAP 2.1
and with Xerces 1.2.3 and Xerces 1.3.0.

---
Gregg Leichtman, Ph.D.
Senior Software Engineer
Quintiles Intelligent Imaging