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功能。