使用Apache Axis部署 Web服务时的常见问题及其解决方法

2003 年 11 月
本文详细介绍了在Linux环境下以Apache Axis+ Resin作为Web服务平台部署Web服务时的常见问题及解决方法。衷心希望本文对Web服务的开发人员或对Web服务感兴趣的读者能起到一定的帮助作用。

1 引言
随着Web服务技术的发展和成熟,其方便性和易用性已逐渐被人们所接受,越来越多的合作伙伴之间开始利用Web服务来实现合作方之间的数据接口。使用Apache Axis和Linux平台是一种低成本的Web服务解决方案,但Apache Axis文档的FAQ对开发者来说内容还不够丰富,本文作者将自己使用Axis时遇到的问题和解决方法整理成文,奉献给Web服务的开发人员和对此感兴趣的读者朋友,旨在帮助大家节约一些宝贵的时间。有关Web服务的基础知识,读者可以阅读参考文献中推荐的文档。作者未在文中介绍Apache和Resin的安装方法,读者可以参考相关网站的说明文档。

作者使用的软件环境如下。

操作系统:Red Hat Linux 7.2

Web服务器: Apache 1.3.27

应用服务器:Resin 2.1.8 ( http://www.caucho.com/ )

SOAP服务器:Apache Axis 1.1

XML解析器:Xerces 2.5.0,Xalan 2.5.1

JDK版本:JDK 1.4.1

2 使用Axis时的常见问题及其解决方法

2.1 Axis运行需要哪些jar文件

对Axis解包后,将axis-1_1/webapps/axis/WEB-INF/lib/目录下的jar文件复制到/usr/local/apache/htdocs/WEB-INF/lib目录下(Web应用程序的目录)。应包括以下jar文件。


axis-ant.jar
axis.jar
commons-discovery.jar
commons-logging.jar
jaxrpc.jar
log4j-1.2.8.jar
name.txt
saaj.jar
wsdl4j.jar

如果需要使用axis提供的测试页面,还要将axis-1_1/webapps/axis/目录下的文件复制到/usr/local/apache/htdocs/axis/目录下。应包括以下文件。


EchoHeaders.jws
fingerprint.jsp
happyaxis.jsp
index.html

2.2 应该使用哪一种XML解析器

XML解析器选用不当,经常会导致使用Apache Axis时出现一些莫名其妙的问题。

由于Apache Axis 并未对Resin内置的xml解析器进行过测试,因此推荐读者使用已通过测试的Xerces xml解析器。可以从 http://xml.apache.org/xalan-j/index.html 处下载Xalan的Java版XSLT处理器,其中包含了Xerces的Java版XML解析器,不需要再单独下载xml解析器。

Xalan 2.5.1解包后,将bin/目录下的xercesImpl.jar、xml-apis.jar和xalan.jar复制到resin安装目录的lib/目录下,例如/usr/local/resin/lib。

编辑/etc/目录下的profile文件,找到设置CLASSPATH环境变量的位置,在其后加入下面的内容(B shell)。


XMLPARSER=$RESIN_HOME/lib/xalan.jar:$RESIN_HOME/lib/xercesImpl.jar:$RESIN_HOME/lib/xml-apis.jar
export CLASSPATH=$XMLPARSER:$CLASSPATH

2.2.1 注意事项
如果CLASSPATH中包含其它的XML解析器设置,应将其从CLASSPATH环境变量的设置中去掉,以免发生冲突。

2.3 如何在Resin中使用Xerces的XML解析器

通过修改resin.conf将resin的XmlParser置换为Xerces的XmlParser。在resin.conf对应的Web应用程序配置中加入以下设置。


<system-property javax.xml.transform.TransformerFactory="org.apache.xalan.processor.TransformerFactoryImpl"/>
<system-property javax.xml.parsers.DocumentBuilderFactory="org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"/>
<system-property javax.xml.parsers.SAXParserFactory="org.apache.xerces.jaxp.SAXParserFactoryImpl"/>
<system-property org.xml.sax.driver="org.apache.xerces.parsers.SAXParser"/>

配置完成后重新启动Resin。

2.4 如何排除XML解析器出现的异常

2.4.1 问题描述

使用http://test.com/axis查看已部署的服务时出现Axis内部错,显示有关WSDD配置的异常信息。如果把WEB-INF目录下的server-config.wsdd删除,再查看就正常了,但只能看到AdminService和Version两个系统缺省的服务,后来部署的服务都看不到了。

2.4.2 原因分析

Axis会在WEB应用程序的WEB-INF/目录下自动生成一个名字为server-config.wsdd的xml文件,其中记录了已部署的WEB服务。每部署一个新的WEB服务时,Axis都会将新服务的描述信息加入到server-config.wsdd中。

故障站点使用的XmlParser是resin内置的XmlParser,Axis并未对其对进行过兼容性测试,查看WEB服务信息时需要从server-config.wsdd(这是一个xml文件)取得已部署的WEB服务描述信息,当server-config.wsdd的内容较复杂时,resin内置的XmlParser因某种原因出现异常,导致Axis内部错误。Server-config.wsdd中记录的Web服务描述信息较少时不会出现异常。

2.4.3 解决方法

修改resin.conf,将resin的XmlParser置换为Xerces的XmlParser。置换方法参见2.3节。

2.4.4 小结

如果Axis报告的错误中有关于xml解析器的错误,建议读者参照本小节描述的方法更换应用服务器的xml解析器,将会有助于问题的解决。

2.5 如何将Axis集成到Resin或其它应用服务器

Axis是以Servlet的方式运行的,而Resin的作用相当于Servlets容器(Container),因此只要配置得当,就可以使Axis在Resin环境中运行,这一点也适用于Resin以外的其它应用服务器。在Resin中配置Axis的方法如下。

将axis-1_1/webapps/axis/WEB-INF/web.xml中的Servlet配置项复制到resin.conf中对应的Web应用程序配置中。通常应包括以下内容。


	<!-- Axis Web-Service Configuration Start -->
		<servlet>
		  <servlet-name>AxisServlet</servlet-name>
		  <display-name>Apache-Axis Servlet</display-name>
		  <servlet-class>
		      org.apache.axis.transport.http.AxisServlet
		  </servlet-class>
		</servlet>

		<servlet>
		  <servlet-name>AdminServlet</servlet-name>
		  <display-name>Axis Admin Servlet</display-name>
		  <servlet-class>
		      org.apache.axis.transport.http.AdminServlet
		  </servlet-class>
		  <load-on-startup>100</load-on-startup>
		</servlet>

		<servlet>
		  <servlet-name>SOAPMonitorService</servlet-name>
		  <display-name>SOAPMonitorService</display-name>
		  <servlet-class>
		      org.apache.axis.monitor.SOAPMonitorService
		  </servlet-class>
		  <init-param>
		    <param-name>SOAPMonitorPort</param-name>
		    <param-value>5001</param-value>
		  </init-param>
		  <load-on-startup>100</load-on-startup>
		</servlet>

		<servlet-mapping>
		  <servlet-name>AxisServlet</servlet-name>
		  <url-pattern>/axis/servlet/AxisServlet</url-pattern>
		</servlet-mapping>

		<servlet-mapping>
		  <servlet-name>AxisServlet</servlet-name>
		  <url-pattern>*.jws</url-pattern>
		</servlet-mapping>

		<servlet-mapping>
		  <servlet-name>AxisServlet</servlet-name>
		  <url-pattern>/services/*</url-pattern>
		</servlet-mapping>

		<servlet-mapping>
		  <servlet-name>SOAPMonitorService</servlet-name>
		  <url-pattern>/SOAPMonitor</url-pattern>
		</servlet-mapping>

		<!-- uncomment this if you want the admin servlet -->
	<!--	
		 <servlet-mapping>
		   <servlet-name>AdminServlet</servlet-name>
		   <url-pattern>/axis/servlet/AdminServlet</url-pattern>
		 </servlet-mapping>
	-->	
		<!-- currently the W3C havent settled on a media type for WSDL;
		  http://www.w3.org/TR/2003/WD-wsdl12-20030303/#ietf-draft
		  for now we go with the basic 'it's XML' response -->
		<mime-mapping>
		  <extension>wsdl</extension>
		   <mime-type>text/xml</mime-type>
		</mime-mapping>

		<mime-mapping>
		  <extension>xsd</extension>
		  <mime-type>text/xml</mime-type>
		</mime-mapping>

	  <!-- Axis Web-Service Configuration End -->	

2.6 Axis提供了哪些开发工具

Apache Axis提供了WSDL2Java和Java2WSDL两个开发工具。

WSDL2Java利用已知的WSDL文件生成服务端和客户端代码。该WSDL文件可以是由合作伙伴提供的,也可以是利用Java2WSDL生成的。Java2WSDL根据已有的Java类文件生成WSDL文件,Java类文件可以是接口类文件,并不需要实现细节。

此外Axis还提供了SoapMonitorApplet和TCPMon工具,可用于监测Web服务。

2.7 如何生成Web服务的服务端和客户端代码

2.7.1 生成或取得WSDL文件

Java2WSDL是Axis提供的利用Java类文件得到WSDL文件的工具。类文件可以使用接口文件编译生成,例如下面的接口文件SoftwarePrice.java。


package samples.userguide.example6;
/**
 * Interface describing a web service to set and get software prices.
 **/
public interface SoftwarePrice {
    public void setWidgetPrice(String softWareName, String price);
    public String getWidgetPrice(String softWareName);

编译SoftwarePrice.java。


javac SoftwarePrice.java

将SoftwarePrice.class复制到正确的package路径下。

执行下面的命令:


java org.apache.axis.wsdl.Java2WSDL -o sp.wsdl  -l"http://test.com:80/services/SoftwarePrice" -n "urn:SoftwarePrice" 
	-p"samples.userguide.example6" "urn:Example6" samples.userguide.example6.SoftwarePrice

各参数的含义如下。


-o:指定输出的WSDL文件的文件名。
-l:指定服务的位置。
-n:WSDL文件的目标名字空间。
-p:指定从package到名字空间的映射,这里可以有多个映射。

最后面的类文件包含了Web服务的接口。

该命令执行后,将生成sp.wsdl文件。

如果按CLASSPATH的设置找不到指定的类文件,Axis将报告异常,如下所示。


java.lang.ClassNotFoundException: samples.userguide.example6.SoftwarePrice
        at java.net.URLClassLoader$1.run(URLClassLoader.java:198)
        at java.security.AccessController.doPrivileged(Native Method)
		……

如果出现上面的问题,请检查是否已将有关类文件复制到正确的位置或CLASSPATH设置是否正确。

生成WSDL文件以后,就可以利用Axis提供的WSDL2Java工具生成Web服务的服务端代码和客户端代码了。

2.7.1.1 注意事项

WSDL文件也可以由合作伙伴提供。这种情况下合作伙伴往往是Web服务的提供者或标准接口的制定者,开发者只要按照既定的WSDL文件生成客户端或服务端代码就可以了。

2.7.2 生成客户端或服务端代码

WSDL2Java工具用于从WSDL文件生成客户端存根(stub)代码,服务端框架(skeleton)代码以及WSDL中的数据类型文件(生成与之对应的Java代码)。开发人员只需向框架代码中补充相关的业务逻辑代码即可得到完整的Web服务代码,因此该工具极大地减轻了开发人员的编码负担。WSDL2Java的使用举例如下。


java org.apache.axis.wsdl.WSDL2Java --server-side --skeletonDeploy true MyService.wsdl

执行上述命令后将生成下列文件。

No.文件用途
1.deploy.wsddMyService服务的部署描述文件
2.MyService.javaMyService服务的接口文件
3.MyServiceService.java获得MyService服务的接口文件
4.MyServiceServiceLocator.java实现MyServiceService接口
5.MyServiceSoapBindingImpl.java实现MyService接口,应向其中补充业务逻辑
6.MyServiceSoapBindingSkeleton.javaMyService服务的服务端框架代码,实现MyService, org.apache.axis.wsdl.Skeleton接口
7.MyServiceSoapBindingStub.javaMyService服务的客户端存根代码,实现MyService接口
8.undeploy.wsdd注销MyService服务的部署描述文件

2.7.3 编写Web服务客户端代码

Web服务的客户端程序完成对Web服务的调用,其程序结构如下。


import com.chinavnet.zx.service.v1_0.*;// WSDL2Java生成的package的名字空间;
public class TestClient {
    public static void main (String[] args) throws Exception
{
		com.chinavnet.zx.service.v1_0.SPInterfaceForVNetLocator locator = new  SPInterfaceForVNetLocator();//获得一个locator对象
		locator.setMaintainSession(true);
		com.chinavnet.zx.service.v1_0.SPInterfaceForVNetSoap service = locator.getSPInterfaceForVNetSoap();//获得服务对象
		com.chinavnet.zx.service.v1_0.DetailLedgerFeedbackResult feedbackRes = null;
		//初始化Web服务中定义的数据类型
        try {
		feedbackRes =  service.generalLedgerFeedback();//调用Web服务的方法并取得返回值
			System.out.println("FeedbackResult :");
			if(feedbackRes != null)
			{
				System.out.println("SPID: " +feedbackRes.getSPID());
				System.out.println("errorDesc: " +feedbackRes.getErrorDescription());
				System.out.println("result: " +feedbackRes.getResult());
			}else
			{
				System.out.println("feedbackRes is null!");
			}
        } catch (java.rmi.RemoteException re) {
 //           throw new junit.framework.AssertionFailedError("Remote Exception caught: " + re );
 		  re.printStackTrace();
        }
}//End of main()
}//End of TestClient class

测试客户端程序是非常简单的,将客户端程序编译后,执行"java TestClient"即可。

2.8 如何编写服务端代码

向MyServiceSoapBindingImpl.java添加相关的业务逻辑代码后,将WSDL2Java生成的源程序编译,打包成jar文件,复制到/usr/local/apache/htdocs/WEB-INF/lib/目录下。

2.9 如何发布Web服务

有了deploy.wsdd文件并准备好类文件后,就可以发布MyService服务了。Axis在安装后自动发布了AdminService,利用它可以发布新的Web服务。方法如下。


java org.apache.axis.client.AdminClient -lhttp://localhost:80/services/AdminService deploy.wsdd
上面的命令执行后,有如下提示。
Processing file deploy.wsdd
<Admin>Done processing</Admin>

2.10 执行WSDL2Java时报告" 类型被引用但未定义"

2.10.1 问题描述

执行WSDL2Java时报告下面的异常:


java.io.IOException: Type {http://schemas.xmlsoap.org/wsdl/} ArrayOfFailedRecord is referenced but not defined.

2.10.2 原因分析

出现上述情况可能的原因有:

类型未定义就被引用。

使用了错误的名字空间。

WSDL文件中存在输入错误。

2.10.3 解决方法

经过仔细检查发现wsdl文件中的


<s:element minOccurs="0" maxOccurs="1" name="FailedRecords" type="s0:ArrayOfFailedRecord" />

的type=" s0:ArrayOfFailedRecord"中的s0:前面有一个空格,将空格删除后问题解决了。

2.10.4 小结

WSDL文件中出现的编辑错误有可能导致执行WSDL2Java时出现"类型被引用但未定义"错误。

2.11 server-config.wsdd的作用是什么

server-config.wsdd记录了axis已发布的Web服务的描述信息。

2.12 发布Web服务时报告"Exception:: (404)Not Found"

2.12.1 问题描述


执行java org.apache.axis.client.AdminClient -lhttp://localhost:80/services/AdminService deploy.wsdd命令发布WEB服务时报告如下内容。
Processing file deploy.wsdd
Exception:: (404)Not Found

Apache的access_log显示如下。


127.0.0.1 - - [17/Sep/2003:15:56:33 +0800] "POST /services/AdminService HTTP/1.0" 404 293

2.12.2 原因分析

出现这个问题的比较简单的原因可能是端口不对,或URL路径不对(例如路径中多写了目录),Axis的SoapMonitor服务按指定的端口或URL找不到AdminService,需要检查正确的端口号和URL路径。

比较深层次的原因就复杂得多了。

本文作者遇到的是下面的情况。

AdminService是一个已发布的WEB服务。

AdminClient使用soap协议同AdminService通信,需要按指定的端口和URL定位AdminService,而原来使用的resin.conf中,有两个web-app配置项,配置A的摘要如下所示。


<host id=' '>
      <app-dir>/usr/local/apache/htdocs/</app-dir>

配置B的摘要如下所示。


<host id='test.com'>
      <app-dir>/usr/local/apache/htdocs/esales/</app-dir>

Axis的有关配置在配置B中。

Httpd.conf中的DocumentRoot是/usr/local/apache/htdocs/。

使用java org.apache.axis.client.AdminClient -lhttp://localhost:80/services/AdminService deploy.wsdd发布WEB服务时,需要按http协议解析url: //localhost:80/services/AdminService。由于htdocs/目录下并没有services/目录(services是Axis在resin.conf中的servlet-mapping),因此应用服务器按resin.conf中的配置去定位AdminService ,因为url的主机名为localhost,因此resin不会到<host id='test.com'>(配置B)中去定位url,而是到配置A中去定位,在配置A中并没有Axis的配置,找不到与AdminService相关的url,因此报告了前面描述的异常情况。

2.12.3 解决方法

知道了原因后,按如下方法就可以解决了。

将配置B中全部关于Axis的配置移到配置A中,注意相应地要改变/etc/profile中的CLASSPATH变量的值。

保存resin.conf后,重新登录服务器(使新的CLASSPATH生效),重新启动resin。再次发布WEB服务。


java org.apache.axis.client.AdminClient -lhttp://localhost:80/services/AdminService deploy.wsdd

屏幕显示如下。


Processing file deploy.wsdd
<Admin>Done processing</Admin>

WEB服务终于发布成功了。

在发布成功的情况下apache的access_log中会看到如下的log:


tail -f access_log|grep vice  
127.0.0.1 - - [17/Sep/2003:16:05:00 +0800] "POST /services/AdminService HTTP/1.0" 200 296 "-" "Axis/1.1"

2.12.4 小结

本小节描述的问题可能是读者遇到的出现最多的异常,但原因并不是唯一的。遇到该问题时,建议读者冷静分析出现问题的可能原因,多实验几种解决方法,最终一定可以成功!

2.13 如何监测SOAP请求和响应流

2.13.1 引言

发布了Web服务以后,如何观察请求和响应数据呢?记录运行日志是一种传统且有效的方法,但对于调试程序来讲还不够方便和直观。值得欣慰的是,Axis为我们提供了在客户端观察SOAP请求和响应流数据的工具SoapMonitor,经过适当配置后,可以实时地观察到Web服务的SOAP请求和响应数据。SoapMonitor是一个Java Applet程序,通过浏览器下载到客户端运行。下面就介绍SoapMonitor的配置和使用方法。

2.13.2 准备SOAPMonitor 小应用程序

在Axis 1.1中,没有为我们编译SOAPMonitor.java程序,但我们可以在axis-1_1/webapps/axis/目录下找到名字为SOAPMonitorApplet.java的源程序文件,自己进行编译。该程序编译后,会生成如下的类文件:


SOAPMonitorApplet.class
SOAPMonitorApplet$ServiceFilterPanel.class
SOAPMonitorApplet$SOAPMonitorData.class
SOAPMonitorApplet$SOAPMonitorFilter.class
SOAPMonitorApplet$SOAPMonitorPage.class
SOAPMonitorApplet$SOAPMonitorTableModel.class
SOAPMonitorApplet$SOAPMonitorTextArea.class

读者需要把上述类文件复制到自己的Web应用程序目录下,本例中是/usr/local/apache/htdocs/目录。

在浏览器地址样中输入SOAPMonitor的地址,例如 http://test.com/SOAPMonitor ,浏览器会提示用户正在下载Applet程序,下载完毕后,读者可以在浏览器窗口中看到如图4-1所示的用户界面。如果上述类文件的位置不正确,浏览器会报告"找不到类"的错误。此时应检查是否已将上述类文件复制到正确的目录下。

图 2-1 SOAPMonitor的界面

2.13.3 发布SOAPMonitor服务

图2-1所示的SOAPMonitor界面出现后,并不意味着就可以观察到Web服务的SOAP请求流与响应流了,首先需要发布SOAPMonitorService。该Web服务是由Axis提供的,但需要由用户自己进行发布,方法如下。

获得SOAPMonitor服务的WSDD文件deploy.wsdd,内容如下(也可到 http://www.sosnoski.com/presents/java-xml/axis/axis-monitor.html 复制该文件):


<deployment xmlns="http://xml.apache.org/axis/wsdd/" 
    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> 
  
  <handler name="soapmonitor" 
      type="java:org.apache.axis.handlers.SOAPMonitorHandler"> 
    <parameter name="wsdlURL" 
      value="/axis/SOAPMonitorService-impl.wsdl"/> 
    <parameter name="namespace" 
      value="http://tempuri.org/wsdl/2001/12/SOAPMonitorService-impl.wsdl"/> 
    <parameter name="serviceName" value="SOAPMonitorService"/> 
    <parameter name="portName" value="Demo"/> 
  </handler> 
  
  <service name="SOAPMonitorService" provider="java:RPC"> 
    <parameter name="allowedMethods" value="publishMessage"/> 
    <parameter name="className" 
      value="org.apache.axis.monitor.SOAPMonitorService"/> 
    <parameter name="scope" value="Application"/> 
  </service> 
</deployment>

发布SOAPMonitor服务:


java org.apache.axis.client.AdminClient -lhttp://localhost:80/services/AdminService deploy.wsdd

2.13.4 修改deploy.wsdd

发布SOAPMonitor服务后,还要对被监测的Web服务进行配置。方法是先注销该Web服务,然后修改该服务对应的WSDD文件,在其中增加请求流和响应流的配置,否则是观测不到SOAP请求和响应流的。

注销Web服务的方法如下。

进入该Web服务的undeploy.wsdd文件所在的目录,执行


Java org.apache.axis.client.AdminClient -lhttp://localhost:80/services/AdminService undeploy.wsdd

修改WSDD文件的方法如下。

以Axis提供的MyService为例,对MyService的WSDD文件做如下修改。

修改前:


... 
 <service name="MyService" provider="java:RPC"> 
  <parameter name="className" value="samples.userguide.example3.MyService"/> 
  <parameter name="allowedMethods" value="*"/> 
  ... 

修改后: (有下划线的行是新加入的内容)


... 
 <service name="MyService" provider="java:RPC"> 
    <requestFlow> 
        <handler type="soapmonitor"/> 
    </requestFlow> 
    <responseFlow> 
        <handler type="soapmonitor"/> 
    </responseFlow> 
  <parameter name="className" value="samples.userguide.example3.MyService"/> 
  <parameter name="allowedMethods" value="*"/> 
  ... 

修改WSDD文件后,重新发布MyService服务:


java org.apache.axis.client.AdminClient -lhttp://localhost:80/services/AdminService deploy.wsdd

2.13.5 启动SOAPMonitor小应用程序

按2.13.2节介绍的方法启动SOAPMonitor小应用程序。

使用客户端程序测试MyService服务:


#  java samples.userguide.example3.Client -lhttp://vnet.sohu.com/services/MyService "test"
结果为:You typed : test

注意,一定要先启动SOAPMonitor小应用程序,后调用Web服务才能观察到SOAP请求和响应流。

2.13.6 观察SOAP请求和响应流

这时在SoapMonitorApplet的窗口中可以观察到SOAP和请求和响应消息,如图2-2所示。

图2-2 MyService的Soap请求和响应流

2.14 使用客户端程序测试Web服务时报告"Exception:: (404)Not Found"

2.14.1 问题描述

WEB服务接口编写完成并发布后,客户端测试程序收不到WEB服务的返回结果,Apache或Resin的log中也看不到访问记录。但测试程序返回结果为0(成功),在没有部署该WEB服务的情况下,也是这个结果,因此怀疑调用的是WSDL文件的提供者自己测试用的WEB服务接口,可能与另一方提供的WSDL文件有关。

2.14.2 原因分析

合作伙伴调用WEB服务就能够成功,从WEB服务主机自己的客户端调用就接收不到数据,估计与合作伙伴提供的WSDL文件有关,该WSDL文件影响了WSDL2Java生成的客户端stub代码。检查stub代码,发现其soapAction都指向了合作伙伴的测试地址。

2.14.3 解决方法

修改stub代码中的soapAction,改为sp(Service Provider)自己的WEB服务URL。重新编译程序并发布Web服务,问题解决。

_call.setSOAPActionURI("sp自己的Web服务地址");

2.14.4 小结

本小节描述的问题出现于Web服务提供方按合作伙伴统一提供的WSDL文件生成客户端代码的情况。遇到这类问题,读者可直接检查WSDL2Java自动生成的代码的有关部分。

在WSDL文件中可以看到与下列内容相似的设置。


<wsdl:service name="SPInterfaceForVNet">
 <wsdl:port binding="impl:SPInterfaceSoapSoapBinding" name="SPInterfaceForVNetSoap">
  <wsdlsoap:address location="http://test.com/services/SPInterfaceSoap" /> 
  </wsdl:port>
  </wsdl:service>

其中 即为已发布的WEB服务的URL,供客户端调用。

2.15 如何列出已发布的Web服务

使用下面的命令:


java org.apache.axis.client.AdminClient -lhttp://localhost:80/services/  list

实际上该命令的输出就是server-config.wsdd文件的内容。

2.16 发布Web服务时报告"调用目标异常"

2.16.1 问题描述

在部署WEB服务时报告:java.lang.reflect.InvocationTargetException异常。

2.16.2 原因分析

在WSDL文件中自定义的名字空间与Axis的services名字空间冲突。

2.16.3 解决方法

修改WSDL文件,将services改为别的名字。

2.17 WSDL文件中的targetNamespace的作用是什么

TargetNamespace指明目标名字空间,用于验证xml文档。

在WSDL文件中,<definitions>中的targetNamespace与<types>中的targetNamespace应保持一致。

2.18 Web服务部署成功但检测不到

2.19 客户端程序找不到可用的Web服务

2.19.1 问题描述


执行 
java org.apache.axis.client.AdminClient -lhttp://localhost:80/services/AdminService deploy.wsdd

时显示<Admin>Done processing</Admin>,却检查不到新的服务,在WEB-INF/目录下的server-config.wsdd文件中也看不到相应的配置项。

2.19.2 原因分析

新的WEB服务的类文件没有重新编译并复制到正确的位置。

2.19.3 解决方法

WEB服务的类文件可以打包为jar文件。在CLASSPATH环境变量中正确设置jar文件的路径。例如:


jar cvf  SPInterfaceSoap.jar com/zx/service/v1_0/*.class

将SPInterfaceSoap.jar复制到WEB-INF/lib/目录下,重新发布WEB服务。

2.20 如何排除原因不明的错误

有时,在对WEB服务执行客户端测试时会出现慕名其妙的错误。为保证环境是正确的,可以按下面的步骤排除原因不明的错误。

1. Undeploy被测试的服务


java org.apache.axis.client.AdminClient -lhttp://localhost:80/services/AdminService undeploy.wsdd

2. 重新启动resin: /usr/local/resin/bin/httpd.sh restart(如果是其它的应用服务器,请按相应的方法重新启动)

3. 重新发布WEB服务

4. 进行测试

3 小结
目前有很多可以使用的应用服务器和Web服务平台软件,本文仅以Apache Axis和Resin为例介绍了在部署Web服务的过程中可能遇到的问题及其解决方法,其中并未讨论Web服务的安全性问题。对于如何高效地开发和部署Web服务以及如何确保Web服务的安全性,还希望对此感兴趣的读者共同参与讨论,对于文中存在的错误和不足之处也希望读者朋友们能够不吝批评指正。

参考资料

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于 Apache Axis2,我们可以将上述类中的方法对外提供为 web 服务,并生成 WSDL 文件,同也可以利用 Axis2 客户端代码调用该服务。 首先,我们需要在项目中引入 Axis2 的相关依赖包,并进行配置和部署。 1. 引入依赖包 首先,在项目的 pom.xml 文件中添加相关依赖: ```xml <dependency> <groupId>org.apache.axis2</groupId> <artifactId>axis2</artifactId> <version>1.7.9</version> </dependency> ``` 2. 配置和部署 在项目的配置文件中,我们需要配置 Axis2 的相关信息,如 web.xml 文件中添加以下内容: ```xml <servlet> <servlet-name>AxisServlet</servlet-name> <display-name>Apache-Axis2</display-name> <servlet-class>org.apache.axis2.transport.http.AxisServlet</servlet-class> <init-param> <param-name>axis2.repository.path</param-name> <param-value>/WEB-INF/axis2.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>AxisServlet</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> ``` 在项目的根目录下,创建文件夹 WEB-INF,再在 WEB-INF 目录下创建文件 axis2.xml,文件内容如下: ```xml <axisconfig name="AxisJava2.0"> <handler name="SimpleFileUploadHandler" class="org.apache.axis2.handlers.SimpleFileUploadHandler"/> <deployer extension=".aar" directory="axis2services"/> </axisconfig> ``` 然后,在项目中新建一个类来实现我们的 web 服务: ```java package com.example; public class ExampleService { public String sayHello(String name) { return "Hello, " + name + "!"; } } ``` 在该类中,我们提供了一个名为 sayHello 的方法,用于返回一个字符串。 接下来,我们可以使用 Axis2 的工具类来生成 WSDL 文件,即我们的服务描述文件。 ```java package com.example; import org.apache.axis2.description.AxisService; import org.apache.axis2.description.Parameter; import org.apache.axis2.description.WSDL2Constants; import org.apache.axis2.engine.AxisConfiguration; import org.apache.axis2.transport.http.AxisServlet; import org.apache.axis2.wsdl.WSDLConstants; import org.apache.axis2.wsdl.WSDLUtil; import org.apache.axis2.wsdl.WSDLConstants.WSDL20_2004_Constants; import org.apache.woden.WSDLFactory; import org.apache.woden.WSDLWriter; import javax.servlet.ServletContext; import javax.wsdl.WSDLException; import javax.wsdl.xml.WSDLLocator; import javax.wsdl.xml.WSDLWriter; import java.io.OutputStream; import java.util.Iterator; public class WsdlGenerator { private AxisServlet axisServlet; public WsdlGenerator(AxisServlet axisServlet) { this.axisServlet = axisServlet; } public void generateWsdlFile(OutputStream outputStream, String serviceName) throws WSDLException { AxisConfiguration axisConfiguration = axisServlet.getConfigurationContext().getAxisConfiguration(); AxisService axisService = axisConfiguration.getService(serviceName); WSDLWriter wsdlWriter = WSDLFactory.newInstance().newWSDLWriter(); wsdlWriter.writeWSDL(new WSDL2Constants.WSDL(, new WSDLLocator() { @Override public String getBaseURI() { return null; } @Override public String getLatestImportURI() { return null; } @Override public java.io.Reader getBaseReader() { return null; } @Override public java.io.Reader getImportReader(String parentLocation, String importLocation) { return null; } @Override public javax.wsdl.xml.WSDLLocator getBaseLocator() { return null; } })); The generated WSDL file can then be returned to the caller by writing it to the OutputStream. 提供的参数 outputStream 是用于写入 WSDL 文件的输出流,serviceName 是指定的服务名称。 使用 Axis2 客户端调用我们的服务,可以使用以下代码: ```java package com.example.client; import org.apache.axis2.client.ServiceClient; import org.apache.axis2.transport.http.HTTPConstants; import org.apache.axis2.transport.http.HttpTransportProperties; public class ClientExample { public static void main(String[] args) throws Exception { ServiceClient serviceClient = new ServiceClient(); HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator(); auth.setUsername("username"); auth.setPassword("password"); serviceClient.getOptions().setProperty(HTTPConstants.AUTHENTICATE, auth); serviceClient.getOptions().setTo(targetEPR); serviceClient.sendReceive(operation); } } ``` 在该代码中,我们首先创建一个 ServiceClient 对象,然后设置用户名和密码,接着设置服务的目标地址,最后发送请求。 使用以上步骤,我们可以基于 Apache Axis2 将上述类的方法对外提供为 web 服务,生成 WSDL 文件,并可以使用 Axis2 客户端代码来调用该服务

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值