从Apache CXF访问WCF Web服务(MTOM和WS-Security)

从Apache CXF访问WCF Web服务(MTOM和WS-Security),wcf,interop,cxf,ws-security,mtom,Wcf,Interop,Cxf,Ws Security,Mtom,我已经为这个问题挣扎了相当长的一段时间,尽管环顾了世界各地,但仍然无法解决它 场景详细信息(代码、配置和其他内容在末尾发布): WCF Web服务(.NET 4),公开了两个端点:一个是不安全的,另一个是使用消息安全性和用户名身份验证(使用成员资格基础设施)进行安全的——没有传输安全性 两个端点都使用MTOM编码;WSDL引用的所有分类都用MessageContract属性标记,成员用MessageBodyMember属性标记 WCF绑定上的配置将“establishSecurityContex

我已经为这个问题挣扎了相当长的一段时间,尽管环顾了世界各地,但仍然无法解决它

场景详细信息(代码、配置和其他内容在末尾发布):

  • WCF Web服务(.NET 4),公开了两个端点:一个是不安全的,另一个是使用消息安全性和用户名身份验证(使用成员资格基础设施)进行安全的——没有传输安全性
  • 两个端点都使用MTOM编码;WSDL引用的所有分类都用MessageContract属性标记,成员用MessageBodyMember属性标记
  • WCF绑定上的配置将“establishSecurityContext”和“negotiateServiceCredential”设置为false
  • WCF服务受自签名证书保护,用于加密
  • 正在尝试使用Apache CXF 2.5.1从Java客户端访问。我已将证书设置为可从类路径访问的密钥库
  • 结果是:

  • 从.NET客户端访问Web服务工作正常
  • 从apachecxf访问不安全的端点在使用和不使用MTOM编码的情况下都可以正常工作
  • 从ApacheCXF访问受保护的端点(没有MTOM)可以正常工作。CXF跟踪表明加密/解密过程正常进行
  • 一旦在WCF中激活MTOM,问题就出现了。我们能够确定,在WCF端,消息的接收、处理和响应的生成/加密正常进行
  • 在CXF中接收消息的过程中,问题才会发生。在我们看来,CXF在尝试解密消息之前没有正确地反序列化MTOM附件;因此,解密逻辑发现消息在响应中仍然有一个要解密的元素,但发现一个要解密的空元素并失败。我们尝试添加一个接收阶段拦截器来初始化附件,但没有成功(尝试在多部分响应中找到边界标记失败)
  • 使用Fiddler,我们发现响应形式良好,并引用了附件
  • 代码/CONFIG/STUFF:

    Web.Config(为清晰起见缩短):

    
    
    Java客户机代码(为清晰起见省略部分):

    private static void secureTest(){
    试一试{
    logger.debug(“安全测试启动.安装服务”);
    //服务实例化
    TestService=新的TestService();
    ITestService端口=service.getTestServiceSecure();
    //请求创建
    BasicRequest请求=objectFactory.createBasicRequest();
    request.setStringData(“字符串数据”);
    setIntegerData(“整数数据”);
    //设置日志记录
    设置拦截器(端口);
    //设置安全性和绑定
    设置绑定(端口);
    //服务电话
    调试(“正在尝试服务调用”);
    BasicResponse响应=port.simpleOperation(请求);
    调试(“调用成功!!!”;
    logger.debug(String.format)(“响应数据:str:%1$s;int:%2$s”,
    response.getStringData(),response.getIntegerData());
    }捕获(例外e){
    logger.error(“服务调用期间的错误”,e);
    }
    }
    专用静态侦听器(ITestService端口){
    Client proxy=JaxWsClientProxy.getClient(端口);
    proxy.getInInterceptors().add(新的LogginInterceptor());
    proxy.getOutiterCeptors().add(新的LoggingOutiterCeptor());
    }
    专用静态无效设置绑定(ITestService端口){
    javax.xml.ws.BindingProvider bp=(javax.xml.ws.BindingProvider)端口;
    SOAPBinding=(SOAPBinding)bp.getBinding();
    binding.setMTOMEnabled(true);
    Map context=bp.getRequestContext();
    context.put(“ws-security.username”、“systemadmin”);
    context.put(“ws-security.password”Pass@word1");
    context.put(“ws-security.encryption.properties”,
    “clientKeystore.properties”);
    put(“ws-security.encryption.username”、“serviceKey”);
    }
    
    错误跟踪(仅限解密阶段):

    [main]调试org.apache.ws.security.components.crypto.CryptoFactory-使用加密引擎[class org.apache.ws.security.components.crypto.Merlin]
    [main]DEBUG org.apache.ws.security.util.Loader-尝试使用sun.misc.Launcher查找[clientKeystore.jks]$AppClassLoader@2a340e类加载器。
    [main]DEBUG org.apache.ws.security.components.crypto.Merlin-已加载jks类型的KeyStore clientKeystore.jks
    [main]DEBUG org.apache.ws.security.processor.Timestamp处理器-找到时间戳列表元素
    [main]DEBUG org.apache.ws.security.message.token.Timestamp-当前时间:2012-02-07T22:52:22.852Z
    [main]DEBUG org.apache.ws.security.message.token.Timestamp-创建的时间戳:2012-02-07T22:52:22.641Z
    [main]DEBUG org.apache.ws.security.message.token.Timestamp-时间戳过期:2012-02-07T22:57:22.641Z
    [main]DEBUG org.apache.ws.security.message.token.Timestamp-时间戳验证:一切正常
    [main]DEBUG org.apache.ws.security.message.token.DerivedKeyToken-DerivedKeyToken:已创建:元素构造函数
    [main]DEBUG org.apache.ws.security.message.token.DerivedKeyToken-DerivedKeyToken:已创建:元素构造函数
    [main]DEBUG org.apache.ws.security.processor.ReferenceListProcessor-找到引用列表元素
    [main]DEBUG org.apache.ws.security.processor.ReferenceListProcessor-找到数据引用:_3
    [main]DEBUG org.apache.ws.security.processor.X509Util-Sym Enc Algo:http://www.w3.org/2001/04/xmlenc#aes256-cbc
    [main]DEBUG org.apache.xml.security.encryption.XMLC
    
      <system.serviceModel>
        <!-- Services -->
        <services>
          <service name="TestServices.Services.TestService" behaviorConfiguration="TestService.Basic">
            <!-- Plain (unsecured) endpoint -->
            <endpoint address="" binding="wsHttpBinding" bindingConfiguration="TestService.Basic" name="TestService.Basic"
                      contract="TestServices.Interfaces.ITestService" bindingNamespace="http://searchtechnologies.com/cpa/wcfinterop"/>
            <!-- Secure endpoint -->
            <endpoint address="/secure" binding="wsHttpBinding" bindingConfiguration="TestService.Secure" name="TestService.Secure"
                      contract="TestServices.Interfaces.ITestService" bindingNamespace="http://searchtechnologies.com/cpa/wcfinterop"/>
          </service>
        </services>
        <!-- Bindings -->
        <bindings>
          <wsHttpBinding>
            <binding name="TestService.Basic" messageEncoding="Mtom">
              <security mode="None">
                <message clientCredentialType="None"/>
                <transport clientCredentialType="None"/>
              </security>
            </binding>
            <binding name="TestService.Secure" messageEncoding="Mtom">
              <security mode="Message">
                <message clientCredentialType="UserName" establishSecurityContext="false" negotiateServiceCredential="false"/>
                <transport clientCredentialType="None"/>
              </security>
            </binding>
          </wsHttpBinding>
        </bindings>
        <!-- Behaviors -->
        <behaviors>
          <serviceBehaviors>
            <behavior name="TestService.Basic">
              <serviceMetadata httpGetEnabled="true"/>
              <serviceDebug includeExceptionDetailInFaults="true"/>
              <serviceCredentials>
                <serviceCertificate storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName" findValue="equiros-PC2.search.local"/>
                <userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="SqlProvider"/>
              </serviceCredentials>
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
      private static void secureTest() {
        try {
          logger.debug("Secure test starting. Instatiating service");
          // service instantiation
          TestService service = new TestService();
          ITestService port = service.getTestServiceSecure();
          // request creation
          BasicRequest request = objectFactory.createBasicRequest();
          request.setStringData("String data");
          request.setIntegerData("Integer data");
          // setup logging
          setupInterceptors(port);
          // setup security & binding
          setupBinding(port);
          // service call
          logger.debug("Attempting service call");
          BasicResponse response = port.simpleOperation(request);
          logger.debug("Call success!!!");
          logger.debug(String.format("Response data: str: %1$s; int: %2$s",
              response.getStringData(), response.getIntegerData()));
        } catch (Exception e) {
          logger.error("Error during service invocation", e);
        }
      }
    
      private static void setupInterceptors(ITestService port) {
        Client proxy = JaxWsClientProxy.getClient(port);
        proxy.getInInterceptors().add(new LoggingInInterceptor());
        proxy.getOutInterceptors().add(new LoggingOutInterceptor());
      }
    
      private static void setupBinding(ITestService port) {
        javax.xml.ws.BindingProvider bp = (javax.xml.ws.BindingProvider) port;
        SOAPBinding binding = (SOAPBinding) bp.getBinding();
        binding.setMTOMEnabled(true);
        Map<String, Object> context = bp.getRequestContext();
        context.put("ws-security.username", "systemadmin");
        context.put("ws-security.password", "Pass@word1");
        context.put("ws-security.encryption.properties",
            "clientKeystore.properties");
        context.put("ws-security.encryption.username", "serviceKey");
      }
    
    [main] DEBUG org.apache.ws.security.components.crypto.CryptoFactory  - Using Crypto Engine [class org.apache.ws.security.components.crypto.Merlin]
    [main] DEBUG org.apache.ws.security.util.Loader  - Trying to find [clientKeystore.jks] using sun.misc.Launcher$AppClassLoader@2a340e class loader.
    [main] DEBUG org.apache.ws.security.components.crypto.Merlin  - The KeyStore clientKeystore.jks of type jks has been loaded
    [main] DEBUG org.apache.ws.security.processor.TimestampProcessor  - Found Timestamp list element
    [main] DEBUG org.apache.ws.security.message.token.Timestamp  - Current time: 2012-02-07T22:52:22.852Z
    [main] DEBUG org.apache.ws.security.message.token.Timestamp  - Timestamp created: 2012-02-07T22:52:22.641Z
    [main] DEBUG org.apache.ws.security.message.token.Timestamp  - Timestamp expires: 2012-02-07T22:57:22.641Z
    [main] DEBUG org.apache.ws.security.message.token.Timestamp  - Validation of Timestamp: Everything is ok
    [main] DEBUG org.apache.ws.security.message.token.DerivedKeyToken  - DerivedKeyToken: created : element constructor
    [main] DEBUG org.apache.ws.security.message.token.DerivedKeyToken  - DerivedKeyToken: created : element constructor
    [main] DEBUG org.apache.ws.security.processor.ReferenceListProcessor  - Found reference list element
    [main] DEBUG org.apache.ws.security.processor.ReferenceListProcessor  - Found data reference: _3
    [main] DEBUG org.apache.ws.security.processor.X509Util  - Sym Enc Algo: http://www.w3.org/2001/04/xmlenc#aes256-cbc
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Getting XMLCipher with transformation
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Constructing XMLCipher...
    [main] DEBUG org.apache.xml.security.algorithms.JCEMapper  - Request for URI http://www.w3.org/2001/04/xmlenc#aes256-cbc
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - cipher._algorithm = AES/CBC/ISO10126Padding
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Initializing XMLCipher...
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - opmode = DECRYPT_MODE
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Processing source element...
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Decrypting element...
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Decrypting to ByteArray...
    [main] DEBUG org.apache.xml.security.utils.ElementProxy  - setElement("KeyInfo", "null")
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Encrypted octets:
    x1eLqhngbuRTq2XJIkcTdzyu1UFb4eV0kwno04/w4yW0HiY6RyYa7OHqniV63aaxgZPxm0NOK2ZUgjggtkM0O9myJ6ZJOFxCLmqREjQMD+mFW+WuTSEZ5cgc3SFule3MmryqoStNLsmzM8t5yaT3drF1ctT7DJQnV6W858WwpD+Dw+WYmO0RaUlgsfbTnWiBvCZ8yyCzvgmZTMGr8y9LXnwaw+FsspReuMpcIOsqU9LE5u5uW5ZJglgn5cv/8XWikD3TwNzqL+7qAVN8R6WnXgUmb1DuX5lx4cyxlwcLnkfOQKbGrwGvKJUY47ohAgKH
    [main] DEBUG org.apache.xml.security.algorithms.JCEMapper  - Request for URI http://www.w3.org/2001/04/xmlenc#aes256-cbc
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - JCE Algorithm = AES/CBC/ISO10126Padding
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Decrypted octets:
    <BasicResponse xmlns="http://searchtechnologies.com/cpa/wcfinterop/data"><DateTimeData>0001-01-02T00:00:00</DateTimeData><IntegerData>Integer data</IntegerData><StringData>String data</StringData></BasicResponse>
    [main] DEBUG org.apache.ws.security.processor.ReferenceListProcessor  - Found data reference: _6
    [main] DEBUG org.apache.ws.security.processor.X509Util  - Sym Enc Algo: http://www.w3.org/2001/04/xmlenc#aes256-cbc
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Getting XMLCipher with transformation
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Constructing XMLCipher...
    [main] DEBUG org.apache.xml.security.algorithms.JCEMapper  - Request for URI http://www.w3.org/2001/04/xmlenc#aes256-cbc
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - cipher._algorithm = AES/CBC/ISO10126Padding
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Initializing XMLCipher...
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - opmode = DECRYPT_MODE
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Processing source element...
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Decrypting element...
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Decrypting to ByteArray...
    [main] DEBUG org.apache.xml.security.utils.ElementProxy  - setElement("KeyInfo", "null")
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - Encrypted octets:
    
    [main] DEBUG org.apache.xml.security.algorithms.JCEMapper  - Request for URI http://www.w3.org/2001/04/xmlenc#aes256-cbc
    [main] DEBUG org.apache.xml.security.encryption.XMLCipher  - JCE Algorithm = AES/CBC/ISO10126Padding
    Feb 07, 2012 4:52:22 PM org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor handleMessage
    WARNING: 
    org.apache.ws.security.WSSecurityException: The signature or decryption was invalid
        at org.apache.ws.security.processor.ReferenceListProcessor.decryptEncryptedData(ReferenceListProcessor.java:298)
        at org.apache.ws.security.processor.ReferenceListProcessor.decryptDataRefEmbedded(ReferenceListProcessor.java:159)
        at org.apache.ws.security.processor.ReferenceListProcessor.handleReferenceList(ReferenceListProcessor.java:93)
        at org.apache.ws.security.processor.ReferenceListProcessor.handleToken(ReferenceListProcessor.java:60)
        at org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:396)
        at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:249)
        at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:85)
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
        at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:799)
        at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1627)
        at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1494)
        at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1402)
        at org.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:47)
        at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:195)
        at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
        at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:649)
        at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
        at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:533)
        at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:463)
        at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:366)
        at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:319)
        at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:88)
        at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)
        at $Proxy33.simpleOperation(Unknown Source)
        at com.searchtechnologies.wcfinterop.TestServiceClient.secureTest(TestServiceClient.java:74)
        at com.searchtechnologies.wcfinterop.TestServiceClient.main(TestServiceClient.java:32)
    Caused by: java.lang.ArrayIndexOutOfBoundsException
        at java.lang.System.arraycopy(Native Method)
        at org.apache.xml.security.encryption.XMLCipher.decryptToByteArray(Unknown Source)
        at org.apache.xml.security.encryption.XMLCipher.decryptElement(Unknown Source)
        at org.apache.xml.security.encryption.XMLCipher.doFinal(Unknown Source)
        at org.apache.ws.security.processor.ReferenceListProcessor.decryptEncryptedData(ReferenceListProcessor.java:296)
        ... 26 more
    
    Feb 07, 2012 4:52:22 PM org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging
    WARNING: Interceptor for {http://searchtechnologies.com/cpa/wcfinterop}TestService#{http://searchtechnologies.com/cpa/wcfinterop}SimpleOperation has thrown exception, unwinding now
    org.apache.cxf.binding.soap.SoapFault: The signature or decryption was invalid
        at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.createSoapFault(WSS4JInInterceptor.java:643)
        at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:308)
        at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:85)
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
        at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:799)
        at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1627)
        at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1494)
        at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1402)
        at org.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:47)
        at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:195)
        at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
        at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:649)
        at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
        at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:533)
        at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:463)
        at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:366)
        at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:319)
        at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:88)
        at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)
        at $Proxy33.simpleOperation(Unknown Source)
        at com.searchtechnologies.wcfinterop.TestServiceClient.secureTest(TestServiceClient.java:74)
        at com.searchtechnologies.wcfinterop.TestServiceClient.main(TestServiceClient.java:32)
    Caused by: org.apache.ws.security.WSSecurityException: The signature or decryption was invalid
        at org.apache.ws.security.processor.ReferenceListProcessor.decryptEncryptedData(ReferenceListProcessor.java:298)
        at org.apache.ws.security.processor.ReferenceListProcessor.decryptDataRefEmbedded(ReferenceListProcessor.java:159)
        at org.apache.ws.security.processor.ReferenceListProcessor.handleReferenceList(ReferenceListProcessor.java:93)
        at org.apache.ws.security.processor.ReferenceListProcessor.handleToken(ReferenceListProcessor.java:60)
        at org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:396)
        at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:249)
        ... 21 more
    Caused by: java.lang.ArrayIndexOutOfBoundsException
        at java.lang.System.arraycopy(Native Method)
        at org.apache.xml.security.encryption.XMLCipher.decryptToByteArray(Unknown Source)
        at org.apache.xml.security.encryption.XMLCipher.decryptElement(Unknown Source)
        at org.apache.xml.security.encryption.XMLCipher.doFinal(Unknown Source)
        at org.apache.ws.security.processor.ReferenceListProcessor.decryptEncryptedData(ReferenceListProcessor.java:296)
        ... 26 more
    
    [main] ERROR com.searchtechnologies.wcfinterop.TestServiceClient  - Error during service invocation
    java.lang.NullPointerException
        at com.sun.xml.internal.messaging.saaj.soap.impl.ElementImpl.addTextNode(ElementImpl.java:439)
        at com.sun.xml.internal.messaging.saaj.soap.ver1_2.Fault1_2Impl.setFaultRole(Fault1_2Impl.java:323)
        at com.sun.xml.internal.messaging.saaj.soap.ver1_2.Fault1_2Impl.setFaultActor(Fault1_2Impl.java:559)
        at org.apache.cxf.jaxws.JaxWsClientProxy.createSoapFault(JaxWsClientProxy.java:219)
        at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:152)
        at $Proxy33.simpleOperation(Unknown Source)
        at com.searchtechnologies.wcfinterop.TestServiceClient.secureTest(TestServiceClient.java:74)
        at com.searchtechnologies.wcfinterop.TestServiceClient.main(TestServiceClient.java:32)