9.11.1 使用XFire测试SOAP处理程序(2)
在服务器控制台, PhotoAppSoapAuthenticationHandler为每个Web服务调用打印到控制台的各个引入的SOAP消息,以及每当Web服务操作执行时打印的各个Hibernate SQL语句。
..... [INFO]... Executing PhotoAppSoapAuthenticationHandler <?xml version="1.0" encoding="UTF-8" standalone="no"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soap:Header> <PixCredentials> <userid>webaffiliate1</userid> <password>password1</password> </PixCredentials> </soap:Header> <soap:Body> <persistAffiliate xmlns="http://service.pix.beginspring.wrox.com"> <!-- Commented out. --> </persistAffiliate> </soap:Body> </soap:Envelope> Hibernate: select albums0_.user_userName as user7_1_, albums0_.id as id1_, albums0_.id as id2_0_, albums0_.user_userName as user7_2_0_, albums0_.name as name2_0_, albums0_.description as descript4_2_0_, albums0_.creationDate as creation5_2_0_, albums0_.labels as labels2_0_, albums0_.DTYPE as DTYPE2_0_ from Album albums0_ where albums0_.user_userName=? .....
工作原理
为了测试SOAPClientAuthenticationHandler,这里对前面讨论的AffiliateManagement WebServiceTest代码做了一些修改。下面的代码程序清单显示了做出的改动:
//Imports
public class AffiliateManagementWebServiceTest {
// Remains same , commented out for simplicity
public static void main(String[] args) {
// Load the Spring Configuration.
ClassPathXmlApplicationContext context = new
ClassPathXmlApplicationContext(
configLocations);
serviceClient = (AffiliateManagementService) context
.getBean("affiliateWebServiceClient");
//For SOAP Client Authentication Handler
//Set username and password on handler
clientHandler = (SOAPClientAuthenticationHandler)
context.getBean("affiliateSoapAuthenticationHandler");
clientHandler.setUsername("webaffiliate1");
//Encyrpt the password in real world.
clientHandler.setPassword("password1");
//Execute Test methods.
testAffiliateCreation();
// remaining methods
testInvalidHandlerCredentials();
}
// remaining test methods commented一旦Spring容器加载了webservice-client.xml,将从Spring上下文中获取SOAPClientAuthenticationHandler bean引用,并设置用户ID和密码证书。下面的代码程序清单显示了SOAPClientAuthenticationHandler:
package com.wrox.beginspring.pix.webservice;
import org.codehaus.xfire.MessageContext;
import org.codehaus.xfire.handler.AbstractHandler;
import org.jdom.Element;
public class SOAPClientAuthenticationHandler extends AbstractHandler {
private String username = null;
private String password = null;
public SOAPClientAuthenticationHandler() {
}
public SOAPClientAuthenticationHandler(String username, String password) {
this.username = username;
this.password = password;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void invoke(MessageContext context) throws Exception {
Element el = context.getOutMessage().getOrCreateHeader();
Element auth = new Element("PixCredentials");
Element username_el = new Element("userid");
username_el.addContent(username);
Element password_el = new Element("password");
password_el.addContent(password);
auth.addContent(username_el);
auth.addContent(password_el);
el.addContent(auth);
}
}SOAPClientAuthenticationHandler的invoke()方法接收包含有客户端SOAP请求的MessageContext。MessageContext提供一些方法,通过这些方法可以从SOAP请求中接收SOAP消息头和SOAP消息主体。在invoke()方法内,使用context.getOutMessage().getHeader()方法从消息上下文获取SOAP消息头;之后设置SOAP消息头中的用户ID和密码,并打印发送到位于控制台的Web服务的SOAP消息。在服务器上,会看到PhotoAppSoapAuthenticatonHandler在打印类似的SOAP消息。
接下来执行AffiliateManagementWebServiceTest中的测试方法。testInvalidHandlerCredentials (稍后将介绍)通过把SOAP消息头中的用户名设为无效来测试逆向条件。在PhotoAppSoapAuthenticationHandler代码中提供了一个哑元实现,当用户名包含无效值时这个哑元实现会抛出一个身份验证异常。
//This will throw an exception as user name with invalid is rejected by server soap
//handler PhotoAppSoapAuthenticationHandler
public static void testInvalidHandlerCredentials() {
try {
if (clientHandler.isDebug()) {
clientHandler.setUsername("invalid");
// Encyrpt the password in real world.
clientHandler.setPassword("password1");
serviceClient.removeAffiliateWithUser(affiliate1.getUserName(),
testUser1.getUserName());
System.out.println("removeAffiliateWithUser executed for - > "
+ affiliate1.getUserName());
}
} catch (Exception e) {
if (e instanceof XFireRuntimeException) {
e.printStackTrace();
} else {
throw new RuntimeException(e);
}
}
}如果查看服务器日志,那么会发现如果PhotoAppSoapAuthenticationHandler抛出异常,那么Web服务操作不会执行。会看到运行Web服务客户端的控制台打印出下面的"身份验证失败"异常:
org.codehaus.xfire.XFireRuntimeException: Could not invoke service.. Nested exception is org.codehaus.xfire.fault.XFireFault: Authentication Failed org.codehaus.xfire.fault.XFireFault: Authentication Failed
在服务器端,会看到PhotoAppSoapAuthenticationHandler打印的身份验证异常:
Executing PhotoAppSoapAuthenticationHandler INFO [org.codehaus.xfire.handler.DefaultFaultHandler] Fault occurred!org.codehaus.xfire.fault.XFireFault: Authentication Failed at com.wrox.beginspring.pix.soaphandler.PhotoAppSoapAuthenticationHandler.invoke(Photo AppSoapAuthenticationHandler.java:39)
本章介绍了Web服务的概念、Web服务的开发方法,以及Web服务技术如何提供与系统交互的标准方法。
讲述了XFire(一个轻量级的Java SOAP架构)以及它如何通过使用Spring配置帮助把POJO提供为Web服务。还介绍了使用XFire进行Spring配置使得以声明的方式创建Web服务客户端变得简单,从而不需要再使用Web服务客户端创建工具编写或生成大块代码。
使用Spring和XFire确实简化了Web服务的开发:Spring托管的bean可以被轻松地作为Web服务提供,同时这些bean还可以利用依赖注入和Spring提供的多种AOP功能。