通过客户端存根访问WSDL时Java InaccessibleWSDLException
我正在尝试为Exchange Web服务编写自定义
Java客户端.
我已经使用wsimport工具生成了客户端存根,如EWS的Services.wsdl文件中的 here所述.现在我编写了使用这些存根的代码.我得到以下异常: Exception in thread "main" com.sun.xml.internal.ws.wsdl.parser.InaccessibleWSDLException: 2 counts of InaccessibleWSDLException. java.io.IOException: Got Server returned HTTP response code: 401 for URL: https://host.domain.com/ews/Services.wsdl while opening stream from https://host.domain.com/ews/Services.wsdl java.io.IOException: Got Server returned HTTP response code: 401 for URL: https://host.domain.com/ews/Services.wsdl?wsdl while opening stream from https://host.domain.com/ews/Services.wsdl?wsdl at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.tryWithMex(Unknown Source) at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(Unknown Source) at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(Unknown Source) at com.sun.xml.internal.ws.client.WSServiceDelegate.parseWSDL(Unknown Source) at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(Unknown Source) at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(Unknown Source) at com.sun.xml.internal.ws.spi.ProviderImpl.createServiceDelegate(Unknown Source) at javax.xml.ws.Service.<init>(Unknown Source) at com.microsoft.schemas.exchange.services._2006.messages.ExchangeWebService.<init>(ExchangeWebService.java:58) at com.xyz.abc.EWSJavaAPI.ExchangeAuthenticator.getExchangeServicePort(ExchangeAuthenticator.java:33) at com.xyz.abc.test.ExchangeDevelopmentTest.main(ExchangeDevelopmentTest.java:35) 正如我们在上面所看到的,ExchangeDevelopmentTest是一个使用另一个类ExchangeAuthenticator的客户端,后者又使用生成的客户端存根ExchangeWebService.但是在堆栈跟踪中我得到了来自Unknown Sources的错误,大概是JDK的JAR. IOException表示它有HTTP响应代码:401,用于未经授权的访问.但我已正确指定了用户名和密码,并且还在密钥库中包含了所需的证书.这个异常的来源,我完全没有方向性. 我写的类的代码: ExchangeAuthenticator public class ExchangeAuthenticator { /** * Obtains an authenticated ExchangeServicePortType with given credentials. * */ public ExchangeServicePortType getExchangeServicePort(String username,String password,String domain,URL wsdlURL) throws MalformedURLException { // Concatinate our domain and username for the UID needed in authentication. String uid = "domain" + "" + "uname"; // Create an ExchangeWebService object that uses the supplied WSDL file,wsdlURL. ExchangeWebService exchangeWebService = new ExchangeWebService(wsdlURL,new QName("<a href="http://schemas.microsoft.com/exchange/services/2006/messages">http://schemas.microsoft.com/exchange/services/2006/messages</a>","ExchangeWebService")); ExchangeServicePortType port = exchangeWebService.getExchangeWebPort(); // Supply your username and password when the ExchangeServicePortType is used for binding in the SOAP request. ((BindingProvider)port).getRequestContext().put(BindingProvider.USERNAME_PROPERTY,uid); ((BindingProvider)port).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY,password); return port; } } ExchangeDevelopmentTest public class ExchangeDevelopmentTest { public static void main (String[] args) { ExchangeAuthenticator exchangeAuthenticator = new ExchangeAuthenticator(); // Print statement so we can easily see where our statements start in the Java console. System.out.println("Let's get started!"); try { // Create a URL object which points at the .wsdl we deployed in the previous step. URL wsdlURL = new URL("https://172.17.245.196/ews/Services.wsdl"); //URL wsdlURL = new URL("<a href="https://172.17.245.196/ews/Services.wsdl">https://172.17.245.196/ews/Services.wsdl</a>"); // Call to the class we just created to return an ExchangeServicePortType with authentication credentials. ExchangeServicePortType port = exchangeAuthenticator.getExchangeServicePort("uname","password@123","domain",wsdlURL); // Prints out the default toString() for the ExchangeServicePortType. System.out.println(port.toString()); } catch (MalformedURLException ex) { // Catch any errors that may occur. Logger.getLogger(ExchangeDevelopmentTest.class.getName()).log(Level.SEVERE,null,ex); System.out.println(ex.getMessage()+"n"+ex.getStackTrace()); } } } ExchangeWebService 由JAX-WS使用wsimport工具生成,删除了其他构造函数和方法.只保留第58行中调用super(此处为Service类)构造函数的构造函数. @WebServiceClient(name = "ExchangeWebService",targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/messages",wsdlLocation = "file:/C:/Services.wsdl") public class ExchangeWebService extends Service { private final static URL EXCHANGEWEBSERVICE_WSDL_LOCATION; private final static WebServiceException EXCHANGEWEBSERVICE_EXCEPTION; private final static QName EXCHANGEWEBSERVICE_QNAME = new QName("http://schemas.microsoft.com/exchange/services/2006/messages","ExchangeWebService"); static { URL url = null; WebServiceException e = null; try { url = new URL("file:/C:/workspace/Server%20files/Client%20files/Services.wsdl"); } catch (MalformedURLException ex) { e = new WebServiceException(ex); } EXCHANGEWEBSERVICE_WSDL_LOCATION = url; EXCHANGEWEBSERVICE_EXCEPTION = e; } //other constructos & methods removed //line 58 public ExchangeWebService(URL wsdlLocation,QName serviceName) { super(wsdlLocation,serviceName); } } 解决方法
为什么在可以拥有本地副本时访问远程WSDL文档文件(和模式文件)?当然,访问端点仍然需要安全性.
首先,您需要根据环境加载类. // Java EE Enviroment ClassLoader cl = Thread.currentThread().getContextClassLoader(); // Java Standalone Enviroment ClassLoader cl = ClassLoader.getSystemClassLoader(); 接下来,在项目中本地存储WSDL文档文件的副本(以及方案文件,如果需要). URL wsdlLocation = cl.getResource("com/mahesha999/ExchangeWebService.wsdl"); QName qName = new QName( "http://schemas.microsoft.com/exchange/services/2006/messages","ExchangeWebService" ); ExchangeWebService exchangeWebService = new ExchangeWebService(wsdlLocation,qName); ExchangeServicePortType port = exchangeWebService.getExchangeWebPort(); 如果访问Web服务端点需要身份验证,则最基本的形式如下: BindingProvider provider = (BindingProvider) port; Map<String,Object> context = provider.getRequestContext(); context.put(BindingProvider.USERNAME_PROPERTY,username); context.put(BindingProvider.PASSWORD_PROPERTY,password); 如果你需要处理证书等等,最好看看Securing WebLogic Web Services. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |