通过客户端存根访问 WSDL 时出现 Java InaccessibleWSDLException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19246608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java InaccessibleWSDLException while accessing WSDL through client stubs
提问by Mahesha999
I am trying to write custom Java client for Exchange Web Services.
I have generated client stubs using wsimport
tool as explained herefrom EWS's Services.wsdl file. And now I have written code that uses these stubs. I am getting following exception:
我正在尝试为 Exchange Web 服务编写自定义 Java 客户端。我已经使用生成的客户端存根wsimport
工具,说明在这里从EWS的Services.wsdl文件。现在我已经编写了使用这些存根的代码。我收到以下异常:
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)
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.
正如我们在上面看到的那样,ExchangeDevelopmentTest
一个客户端使用另一个类ExchangeAuthenticator
,而该类又使用生成的客户端存根ExchangeWebService
。但是在堆栈跟踪中,我从未知来源中得到了错误,大概是 JDK 的 JAR。
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.
该IOException
说,它得到了HTTP response code: 401
,这是未经授权的访问。但是我已经正确指定了用户名和密码,并且还在密钥库中包含了所需的证书。我完全没有方向,这个异常来自哪里。
Code of the classes I wrote:
我写的类的代码:
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
交换网络服务
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.
由 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);
}
}
回答by Satish
Did you add username and password this way?
你是这样添加用户名和密码的吗?
ShopingCart sc = scs.getShopingCartPort();
Map requestContext = ((BindingProvider)sc).getRequestContext();
requestContext.put(BindingProvider.USERNAME_PROPERTY, userName);
requestContext.put(BindingProvider.PASSWORD_PROPERTY, password);
You have not given your client code in question. Are you using proxy? Then you have to give your proxy username and password in the above.
您没有提供有问题的客户代码。你在使用代理吗?然后你必须在上面给出你的代理用户名和密码。
回答by Paul Vargas
Whyaccess 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.
当您可以拥有本地副本时,为什么还要访问远程 WSDL 文档文件(和模式文件)?当然,访问端点仍然需要安全性。
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();
Next, store locally a copy of the WSDL document file (and the scheme files if needed) in your project.
接下来,在您的项目中本地存储 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();
If authentication is required to access the webservice endpoint, in its most basic form, is as follows:
如果访问 webservice 端点需要身份验证,其最基本的形式如下:
BindingProvider provider = (BindingProvider) port;
Map<String, Object> context = provider.getRequestContext();
context.put(BindingProvider.USERNAME_PROPERTY, username);
context.put(BindingProvider.PASSWORD_PROPERTY, password);
If you need to deal with certificates and that sort of thing, better have a look at Securing WebLogic Web Services.
如果您需要处理证书之类的事情,最好查看Securing WebLogic Web Services。