Bug 202797

Summary: Cannot create web service client for SSL protected Metro service
Product: webservices Reporter: hatspencer
Component: WSITAssignee: Martin Grebac <mgrebac>
Status: REOPENED --- QA Contact: issues <issues.netbeans.org>
Priority: P2 CC: ads, pjiricka
Version: 7.0.1   
Target Milestone: TBD   
Hardware: PC   
OS: Windows 7 x64   
Whiteboard:
Issue Type: ENHANCEMENT Exception Report:

Description hatspencer 2011-09-28 21:07:37 UTC
I've made the following steps:

1. Create Java web application
2. Create a 'default' Web Service, with a hello operation in it
3. Enable Transport Security (SSL) for the service in Metro
4. Deploy to GF3.1

5. Create Java Application
6. Create New Web Service Client
7. Enter WSDL URL.

In the last step I tried it with the hostname being: localhost, local IP, computer name. So for e.g. https://192.168.0.2:8181/myApp/myService?wsdl. The WSDL gets displayed in the browser after prompt for certificate acceptance. I tried this with the service and client being on different machines. I always got this error message right away:

"Problem with downloading wsdl or schema file.
Check the URL, proxy settings, or whether the server is running.
URL: https://192.168.0.2:8181/MyApp/myService?wsdl."

I made sure i have no proxies by setting it in NetBeans options, also there is no proxies set in JVM options of GlassFish.

Thanks in advance,
Daniel Szalay
Comment 1 hatspencer 2011-09-28 21:53:11 UTC
Retriever output:
Error: An I/O error occured. sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target`
Comment 2 hatspencer 2011-09-28 22:19:02 UTC
I am using the default development certificates
Comment 3 hatspencer 2011-09-29 10:09:27 UTC
I got this working by setting the NetBeans VMargs as suggested:

<NETBEANS_HOME>/bin/netbeans.exe
-J-Djavax.net.ssl.trustStore=<AS_HOME>/domains/domain1/config/cacerts.jks 
-J-Djavax.net.ssl.keyStore=<AS_HOME>/domains/domain1/config/keystore.jks 
-J-Djavax.net.ssl.trustStorePassword=changeit 
-J-Djavax.net.ssl.keyStorePassword=changeit

I set those VM options in etc/netbeans.conf. This should be there as default isn't it? With this set, the client gets generated, however there is still an error:

"Exception in thread "main" javax.xml.ws.WebServiceException: Cannot find 'https://localhost:8181/myApp/myService?wsdl' wsdl. Place the resource correctly in the classpath."

I guess now the generated client is having problems downloading the WSDL and initializing the property 'DATASTOREWS_WSDL_LOCATION'. I did a workaround with a method like this, so it does not want to download it again:

private static URL getURL() {
        try {
            return new URL("https://localhost:8181/myApp/myService?wsdl");
        } catch (MalformedURLException ex) {
            Logger.getLogger(DataStoreWS_Service.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
Comment 4 Denis Anisimov 2011-09-30 16:07:37 UTC
This is definitely not P2.
The original problem is just an user issue and it is solved by the user.
The following problem has a workaround.
Comment 5 Denis Anisimov 2011-10-03 04:47:20 UTC
So the first of all port 8181 is not required for wsdl file retrieval.
One can use HTTP port 8080 instead of HTTPS port 8181.

JaxWs client is generated with additional settings in NB. So this is not an issue.

The last problem : the generated client cannot access to wsdl via HTTPS. And I don't understand how you have resolved it via not used method.
Also it doesn't fix the problem in  my case and I don't see how it can be fixed 
in this way at all: the URL is the same HTTPS location which has a problem 
with retrieval. The workaround could be using local WSDL instead of remote.

The current behavior is the issue in wsimport tool in JAX-WS library.
So it should be either fixed on its side or there should be some option for HTTPS urls. I need to check this.
Comment 6 hatspencer 2011-10-03 08:07:08 UTC
Thanks for your response!

See http://metro.java.net/guide/Example_Applications.html#gfrlg or http://download.oracle.com/docs/cd/E19355-01/820-1072/gfrlg/index.html. Here the Oracle / Metro User Guide suggests that I should use an HTTPS URL and FQHN. Should I just ignore this and simply use HTTP to create a secured client?

"The last problem : the generated client cannot access to wsdl via HTTPS. And I
don't understand how you have resolved it via not used method."

I did use the getURL method mentioned earlier in of my posts. However, the generated WSIT client code differs if you generate it for a Java Web Application. I needed the client for a web application, and it works with that.

WSDL URL retrieval code for Java Application:

static {
        DATASTOREWS_WSDL_LOCATION = ssl.DataStoreWS_Service.class.getResource("https://localhost:8181/DataMiner/DataStoreWS?wsdl");
        WebServiceException e = null;
        if (DATASTOREWS_WSDL_LOCATION == null) {
            e = new WebServiceException("Cannot find 'https://localhost:8181/DataMiner/DataStoreWS?wsdl' wsdl. Place the resource correctly in the classpath.");
        }
        DATASTOREWS_EXCEPTION = e;
    }

WSDL URL retrieval code for Java Web Application:

static {
        URL url = null;
        WebServiceException e = null;
        try {
            url = new URL("https://localhost:8181/DataMiner/DataStoreWS?wsdl");
        } catch (MalformedURLException ex) {
            e = new WebServiceException(ex);
        }
        DATASTOREWS_WSDL_LOCATION = url;
        DATASTOREWS_EXCEPTION = e;
    }

As you can see, in the case of a Java Web Application it does not try to retrieve the WSDL.
Comment 7 Denis Anisimov 2011-10-05 09:28:27 UTC
(In reply to comment #6)
> Thanks for your response!
> 
> See http://metro.java.net/guide/Example_Applications.html#gfrlg or
> http://download.oracle.com/docs/cd/E19355-01/820-1072/gfrlg/index.html. Here
> the Oracle / Metro User Guide suggests that I should use an HTTPS URL and FQHN.
> Should I just ignore this and simply use HTTP to create a secured client?

OK. I've thought that both WSDL files has the same content. So it doesn't matter
what WSDL to use. I was wrong. HTTPS wsdl has a HTTPS WS url but HTTP wsdl has
HTTP WS url.
Now I see the problem.
> 
> "The last problem : the generated client cannot access to wsdl via HTTPS. And I
> don't understand how you have resolved it via not used method."
> 
> I did use the getURL method mentioned earlier in of my posts. However, the
> generated WSIT client code differs if you generate it for a Java Web
> Application. I needed the client for a web application, and it works with that.
> 
> WSDL URL retrieval code for Java Application:
> 
> static {
>         DATASTOREWS_WSDL_LOCATION =
> ssl.DataStoreWS_Service.class.getResource("https://localhost:8181/DataMiner/DataStoreWS?wsdl");
>         WebServiceException e = null;
>         if (DATASTOREWS_WSDL_LOCATION == null) {
>             e = new WebServiceException("Cannot find
> 'https://localhost:8181/DataMiner/DataStoreWS?wsdl' wsdl. Place the resource
> correctly in the classpath.");
>         }
>         DATASTOREWS_EXCEPTION = e;
>     }
> 
> WSDL URL retrieval code for Java Web Application:
> 
> static {
>         URL url = null;
>         WebServiceException e = null;
>         try {
>             url = new URL("https://localhost:8181/DataMiner/DataStoreWS?wsdl");
>         } catch (MalformedURLException ex) {
>             e = new WebServiceException(ex);
>         }
>         DATASTOREWS_WSDL_LOCATION = url;
>         DATASTOREWS_EXCEPTION = e;
>     }
> 
> As you can see, in the case of a Java Web Application it does not try to
> retrieve the WSDL.

What does it mean ? Sorry I don't understand you.
The last code is what you suggested or it is somehow generated ?
Please describe it exactly. 

This code is generated by wsimport tool. You can see the command line which 
is used for it in the output tab. This command line contains the local copy of
wsdl file along with original remote URL.
So there is not other way to say wsimport to use something different from 
original URL which is the problem ( I suggest it is consequence of untrusted 
HTTPS acceess ).
In my case the same code with getResource() method is generated 
in any type of project . 
This should not be a problem for trusted HTTPS url.
But it is for untrusted which is your case. 
I don't know whether this is issue actually or not but please report in 
in JAX-WS RI bug tracker , against wsimport tool.
This is not NB issue.
Comment 8 hatspencer 2011-10-05 09:46:44 UTC
(In reply to comment #7)
> (In reply to comment #6)
> > Thanks for your response!
> > 
> > See http://metro.java.net/guide/Example_Applications.html#gfrlg or
> > http://download.oracle.com/docs/cd/E19355-01/820-1072/gfrlg/index.html. Here
> > the Oracle / Metro User Guide suggests that I should use an HTTPS URL and FQHN.
> > Should I just ignore this and simply use HTTP to create a secured client?
> 
> OK. I've thought that both WSDL files has the same content. So it doesn't
> matter
> what WSDL to use. I was wrong. HTTPS wsdl has a HTTPS WS url but HTTP wsdl has
> HTTP WS url.
> Now I see the problem.
> > 
> > "The last problem : the generated client cannot access to wsdl via HTTPS. And I
> > don't understand how you have resolved it via not used method."
> > 
> > I did use the getURL method mentioned earlier in of my posts. However, the
> > generated WSIT client code differs if you generate it for a Java Web
> > Application. I needed the client for a web application, and it works with that.
> > 
> > WSDL URL retrieval code for Java Application:
> > 
> > static {
> >         DATASTOREWS_WSDL_LOCATION =
> > ssl.DataStoreWS_Service.class.getResource("https://localhost:8181/DataMiner/DataStoreWS?wsdl");
> >         WebServiceException e = null;
> >         if (DATASTOREWS_WSDL_LOCATION == null) {
> >             e = new WebServiceException("Cannot find
> > 'https://localhost:8181/DataMiner/DataStoreWS?wsdl' wsdl. Place the resource
> > correctly in the classpath.");
> >         }
> >         DATASTOREWS_EXCEPTION = e;
> >     }
> > 
> > WSDL URL retrieval code for Java Web Application:
> > 
> > static {
> >         URL url = null;
> >         WebServiceException e = null;
> >         try {
> >             url = new URL("https://localhost:8181/DataMiner/DataStoreWS?wsdl");
> >         } catch (MalformedURLException ex) {
> >             e = new WebServiceException(ex);
> >         }
> >         DATASTOREWS_WSDL_LOCATION = url;
> >         DATASTOREWS_EXCEPTION = e;
> >     }
> > 
> > As you can see, in the case of a Java Web Application it does not try to
> > retrieve the WSDL.
> 
> What does it mean ? Sorry I don't understand you.
> The last code is what you suggested or it is somehow generated ?
> Please describe it exactly. 

Both code blocks are generated by wsimport, and somehow it is different for the project types.
> 
> This code is generated by wsimport tool. You can see the command line which 
> is used for it in the output tab. This command line contains the local copy of
> wsdl file along with original remote URL.
> So there is not other way to say wsimport to use something different from 
> original URL which is the problem ( I suggest it is consequence of untrusted 
> HTTPS acceess ).
> In my case the same code with getResource() method is generated 
> in any type of project . 
> This should not be a problem for trusted HTTPS url.
> But it is for untrusted which is your case. 
> I don't know whether this is issue actually or not but please report in 
> in JAX-WS RI bug tracker , against wsimport tool.
> This is not NB issue.

Well this should be improved if you ask me. If I do the same in Visual Studio, it just prompts if I want to trust the service certificate, and after accepting, no other configuration is needed. I would expect the same from NB.
Comment 9 Denis Anisimov 2011-10-05 12:28:56 UTC
> 
> Well this should be improved if you ask me. If I do the same in Visual Studio,
> it just prompts if I want to trust the service certificate, and after
> accepting, no other configuration is needed. I would expect the same from NB.
Generally I agree that this is not good. But one more time :
NB uses a lot of external tools and libraries. JaxWS client is generated by 
standard "wsimport" utility tool from JAX-WX RI. 
We can hack generated Java code by this tool but this is not good approach.
"wsimport" is separate product external for NB and it used widely in different 
places not just NB.
The good approach is fixing the issue in the product where it exist. This 
allows to avoid the duplication if efforts.
Nb downloads for you WSDL file as you suggest : with asking certificate trust .
All subsequent work is done by wsimport. So it is the source of the problem.

I don't know VS details but probably it doesn't use some existing external common tool for JaxWs client generation. So that's why they don't have such problems.
Comment 10 Martin Grebac 2011-10-05 18:22:41 UTC
Hi, please do not close the bug without filing RFE or Bug to the 3rd party component. You also did not address the very first comment on having keystores setup for IDE by default, which is a valid one.

 Let us know how we can help in this case. AFAIK, the error mentioned in the beginning is coming from retriever, which requires additional configuration to be able to overcome. At the very least this can be detected and helpful info provided to the user.

 The second I didn't get to reproduce, but isn't it coming from the client itself running without the correct ssl setup?
Comment 11 Denis Anisimov 2011-10-06 07:45:20 UTC
OK. I change it to the RFE.

I don't see how options which are required for first problem could be set 
by default:
- its a Java SE project which doesn't know about J2EE servers at all.
- there could be a number of J2EE servers registered in the IDE.
- there is no possibility to know J2EE server domains path without knowing the
target J2EE server ( and for each specific J2EE server they could differ ).

So there are just no default options because their values cannot be 
defined automatically .

>The second I didn't get to reproduce, but isn't it coming from the client
>itself running without the correct ssl setup?
What do you mean "without the correct ssl setup" ?
Comment 12 Denis Anisimov 2011-10-06 07:58:09 UTC
What I see from very beginning that can be improved :
run Ant with the same java properties which has been set for NB start.
I don't know is it acceptable but the problem could be fixed f.e. :
go to Options->Miscellaneous->Ant and put into the properties text area the same
content for SSL settings as for NB.
Run the client and all works fine.

But this is out of WS functionality scope.
Comment 13 hatspencer 2011-10-06 11:57:30 UTC
(In reply to comment #11)
> OK. I change it to the RFE.
> 
> I don't see how options which are required for first problem could be set 
> by default:
> - its a Java SE project which doesn't know about J2EE servers at all.
> - there could be a number of J2EE servers registered in the IDE.
> - there is no possibility to know J2EE server domains path without knowing the
> target J2EE server ( and for each specific J2EE server they could differ ).

First of all there shouldn't be anything like setting properties at the IDE level, at least not in netbeans.conf. There should be a tab for that in options, so you can set it. Also at the project level, this should be supported in the wizard, so you can add these:

-Djavax.net.ssl.trustStore=${truststore.location}
-Djavax.net.ssl.trustStorePassword=${ssl.password}

Update on this exception:
Exception in thread "main" javax.xml.ws.WebServiceException: Cannot find 'https://localhost:8181/DataMiner/DataStoreWS?wsdl' wsdl. Place the resource correctly in the classpath.

I did get different DATASTOREWS_WSDL_LOCATION initialization code because my Java Web Application project uses newer JAX-WS libraries (JAX-WS RI 2.2.5-b04 - imported with the latest Metro). However when I made the import with a Java Application, it still used the older one (JAX-WS RI 2.2-hudson-752-). So this is already fixed in the newer wsimport I guess.

Also I think more tutorials would make these things a lot easier. Especially an 'SSL protected Metro service with HTTP basic authentication + Client' kind of tutorial would be extremely helpful. The tutorials I've found on Metro or elsewhere are vague or out of date.

The only NB tutorial about 'Advanced Web Service Interoperability' is this: http://netbeans.org/kb/docs/websvc/wsit.html#Exercise_2 . I've found this tutorial strange, because nothing happens if you change the web service security settings at 'Edit web service attributes' in the secure example. I think this is because there is a WSIT xml in WEB-INF, that has been built manually, so it seems that it weren't even built using the IDE's wizards.
By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo