通过客户端存根访问WSDL时Java InaccessibleWSDLException [英] Java InaccessibleWSDLException while accessing WSDL through client stubs
问题描述
我正在尝试为Exchange Web服务编写自定义Java客户端。
我已经使用 wsimport
工具生成了客户端存根,如下所述这里。现在我编写了使用这些存根的代码。我得到以下异常:
I am trying to write custom Java client for Exchange Web Services.
I have generated client stubs using wsimport
tool as explained here from EWS's Services.wsdl file. And now I have written code that uses these stubs. I am getting following exception:
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。
As we can see above ExchangeDevelopmentTest
is a client that uses another class ExchangeAuthenticator
which in turn uses generated client stub ExchangeWebService
. But up in the stack trace I got errors from Unknown Sources presumably JDKs' JARs.
IOException
说得到了 HTTP响应代码:401
,用于未经授权的访问。但我已正确指定了用户名和密码,并且还在密钥库中包含了所需的证书。这个异常的来源,我完全没有方向性。
The IOException
says it got HTTP response code: 401
, that is for unauthorized access. But I have correctly specified the user name and password and also have included the needed certificate in the keystore. I am totally directionless where this exception is coming from.
我写的课程代码:
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
class)构造函数的构造函数。
Generated by JAX-WS with wsimport
tool, other constructors and methods removed. Only contructor at line 58 which calls super
(here Service
class) constructor is kept.
@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文档文件(和模式文件)?当然,访问端点仍然需要安全性。
Why access the remote WSDL document file (and schema files) when you can have a local copy? Of course, security is still required to access the endpoint.
首先,您需要根据环境加载类。
First, you need the class loader according to the environment.
// Java EE Enviroment
ClassLoader cl = Thread.currentThread().getContextClassLoader();
// Java Standalone Enviroment
ClassLoader cl = ClassLoader.getSystemClassLoader();
接下来,在您的本地存储WSDL文档文件的副本(以及方案文件,如果需要)项目。
Next, store locally a copy of the WSDL document file (and the scheme files if needed) in your project.
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服务端点,则最基本的形式如下:
If authentication is required to access the webservice endpoint, in its most basic form, is as follows:
BindingProvider provider = (BindingProvider) port;
Map<String, Object> context = provider.getRequestContext();
context.put(BindingProvider.USERNAME_PROPERTY, username);
context.put(BindingProvider.PASSWORD_PROPERTY, password);
如果你需要处理证书等等,最好看看 保护WebLogic Web服务 。
If you need to deal with certificates and that sort of thing, better have a look at Securing WebLogic Web Services.
这篇关于通过客户端存根访问WSDL时Java InaccessibleWSDLException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!