JBoss - Prevent WSDL splitting - java

I'm working in a SOAP WS project with JBoss. In order to define SOAP operations, I annotate my Java classes with #Local and #WebService, and my methods with #WebMethod and #WebResult.
The WSDL file is generated automatically by JBoss. I can customize some aspects of the WSDL:
https://docs.jboss.org/author/display/JBWS/Published+WSDL+customization
JBoss splits the WSDL in a few files. The 'main' WSDL uses <wsdl:import/> tags to include other files.
My web service is used from within the intranet and externally. The 'internal' hostname of my WS is different to its 'external' hostname. Since JBoss generates full URL links for the WSDL imports, and in order to ensure my WSDL is valid I have to overwrite the hostname of the URL using 'wsdl-host'.
I had to use the external URL in wsdl-host in order to allow both internal e external systems to work. As such, all internal SOAP clients fetch included parts of the WSDL using the external URL. If the external proxy is down for some reason, my internal clients become unable to use the WS since they can't load the WSDL.
Is there a way to prevent JBoss from splitting the WSDL in multiple files, or to force it to use a relative path instead of a full URL inside the <wsdl:import/> tags?

The answer given here prevents the WSDL from splitting by inlining other WSDL files in the main WSDL. I can confirm it works. In order to do that, I just used the same targetNamespace in all #WebService annotations.
#WebService(targetNamespace="<your namespace here>")

Related

Apache CXF(with spring boot) How can I return original WSDL file(not generated by cxf)?

I have WSDL and XSD schemas. I generate java classes and service interface from it with CXF.
I create SOAP endpoint with CXF:
#Bean
Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(bus, myEndpoint);
endpoint.publish(path);
return endpoint;
}
When I open service URl I get generated WSDL but I need Original WSDl.
How can I return original WSDL and not generated?
AFAIK, it seems not doable (or not quite easy) as Apache CXF publishes a WS endpoint based on its implementation (and/or relevant generated sources for XML schemas). CXF does not directly used the WSDL and XSDs, and therefore, the endpoint's WSDL might be a tad different from the original WSDL.
I have used cxf-codegen-plugin to generate Java code from WSDL+XSD, then implemented the business logics of each service and publish them using Apache CXF <jax-ws>. The generated code are well annotated so that it seems JAX-WS can use these annotations to produce very close results. The published WSDLs are only slightly different from the original WSDLs but hard to notice if not expert. You can find the project's source here: https://github.com/htr3n/loan-approval-portal.
Perhaps, the closest you might have is using Spring WS with <static-wsdl>.

Java.xml.validation.Schema from wsdl

So I have a web service in NetBeans 8.1, for which I've written the wsdl with embedded XSD (and an external ref also).
Now I need to be able call the SOAP service on other instances of the application:
i.e. have instance X call a method on instance Y, as a secondary goal of the application.
I don't like to use NetBeans automatic SOAP client wizards, as I would be pointing to the very service which I'm building - it would potentially be a chicken and the egg type of thing during building. Secondly, I already have all the required JAXB types used by the web service, so it should be easy to construct a client right?
Well my trouble starts when I want to use JAXB to marshal my request object into a javax.xml.soap.SOAPBodyElement (my current strategy is to use SAAJ for the client part), but how to add a Schema to the marshaller? the schema is embedded in the wsdl, and I can't figure out how to reference it.
I figured that I could split out the schema part into a separate XSD file, but I'm missing an annotation option for #WebService, where I can provide an XSD file, just like I can provide a wsdl file (currently the 'wsdlLocation' points to both wsdl & xsd as it is embedded).
I guess I may have to live with not doing XSD validation on the client side(it is enabled server-side), as it seems tricky to get a Schema object from the wsdl - is that possible somehow?
You can read the .wsdl as an InputStream and transform it to a DOMResult. You can then get the "schema" node from the DOMResult and turn it into a DOMSource. With that, you can make a Schema object using the Source[] constructor.
I haven't got it to work myself, I had too many imports and it became hell to manage the namespaces. The only code I found on this was in "SOA Using Java Web Services" by Mark Hansen, chapter 7.5.1: Validation. I don't think I can put that code here, but all the code you should need for this use case is in there.

How can I generate a WSDL file from a WSDL URL?

My problem is that I created a web service client with wsimport and when creating its service object, it fails because of the HTTPS, like that:
MyService_Service service = new MyService_Service(
new URL("https://www.aaa.com/myws/MyService?WSDL"));
So, I am trying to initialize a service object from a WSDL file, but how can I create a WSDL file from that URL "https://www.aaa.com/myws/MyService?WSDL"?
Thanks a lot.
Navigate to the URL in a browser and save the file it generates. You'll need to make sure you also save any schemas imported by the wsdl.
JAX-WS needs WSDL document every time one initializes service instance. Since issues like one you described might occur, its possible to package WSDL and associated XSD schemas, so that they would be accessible no matter what.
I'd prefer using XML catalogs, since there would be no need to change WSLD document or XSD schema.
Another option would be to specify #WebService wsdlLocation property and set path to WSDL file. Though if path to XSD schemas is absolute you'll have to modify WSLD document.
If you're working with wsimport utility version that supports clientjar option, that might save you some time.
Creates the jar file of the generated artifacts along with the WSDL
metadata required for invoking the web service.

Using CXF With an WSDL that has unpublished metadata

I'm using CXF to to communicate with a WSDL made in WCF. The WCF side of things was created following a tutorial. The Java code has been generated using a Maven script.
I have gotten things working using HTTPS for encryption. I have gotten authentication working. However, I would like to have the WSDL metadata turned off on the WCF side and still be able to use the Java side to talk to the service.
Currently, I can access the service with metadata publishing on from the Java side using this code:
URL wsdlLocation = new URL("https://server.com:7010/Hservice?wsdl");
HttpsURLConnection connection = (HttpsURLConnection) wsdlLocation.openConnection();
HService service = new HService(wsdlLocation);
HAdminService calc = service.getHAdminService();
... (authentication using WSS4JOutInterceptor code and unrelated code here)
System.out.println(calc.add(new Double(5), new Double(5)));
However, when I turn off metadata publishing on the WCF side I get this error:
Exception in thread "main" javax.xml.ws.WebServiceException:
org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:149)
at org.apache.cxf.jaxws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:90)
at javax.xml.ws.Service.<init>(Service.java:56)
at com.blah.hservice.v_1_0.HService.<init>(HService.java:49)
at Main.main(Main.java:85)`
The page the wsdl is on displays this with metadata publishing turned off (this is an excerpt):
This is a Windows© Communication Foundation service.
Metadata publishing for this service is currently disabled.
If you have access to the service, you can enable metadata publishing by completing the following steps to modify your web or application configuration file:
I expected to be able to search "CXF metadata unpublished" and see lots of people doing this...but have not found anything. How do I communicate with this service without the WSDL being published?
You really have two options:
Copy the wsdl locally and point the client at the local wsdl. This is likely the "best" option as it makes sure all the information in the wsdl (like policies and such) is used.
Use "null" for the wsdl location (note: not JAX-WS portable). You will need to call service.addPort(....) after creating the service and before calling getHAdminService to add the port with the appropriate binding and endpoint address. CXF can work most of the time without the WSDL (will internally generate what is needed from the annotations). However, if things like policies are defined in the WSDL, then it cannot.
I got this to work with Client code I generated using CXF 2.6.5
Make sure the QName(first argument) matches the QName the getHAdminService() method references. The bindingId(second argument) should be one of the constants defined in SOAPBinding Interface (javax.xml.ws.soap.SOAPBinding).

CXF java2ws: how to include external xsd files?

I generate WSDL files for several web services (from the server service definitions) where I have already XML schemas (*.XSD) for the beans used as parameters. How do I tell java2ws to reference these (include the external XSD) and not generate its own into the WSDL?
I have tried the -createxsdimports, but that does generate its own XSD files.
Is there a Java Annotation that I can use to let CXF know where the XSD for each file/package is?
Try the #XmlSchema annotation. It includes a location parameter that is used to tell JAXB that a real schema exists:
#XmlSchema(location="http://www.example.com/xsds/foo.xsd")
package com.example.foo;
I have a CXF Webservice that imports external schema files. When I built it; I spent quite a bit of time trying to sort out the exact scenario you're trying to achieve. Unfortunately, it appears that CXF does not respect the #XmlSchema(location="") annotation when generating WSDL from java. Daniel Kulp, the main CXF dev told me at the time this was a known issue but not enough people are complaining about it so it's not high on their list of priorities to fix.
So I ended up writing the WSDL by hand and then generating the SEI from the WSDL file. Of course, if you hand-write the WSDL you can do whatever you want.
Do bear in mind that one side-effect of this is that the external schema file needs to be accessible by an HTTP GET - both while generating the SEI AND when the webservice app starts up - CXF will retrieve the schema file on startup. Same goes for when you generate the client, of course. This does create a bit of a messy architectural dependency; but there appears to be no way to tell CXF "myschema.xsd" is available at http://myurl.com/myschema.xsd but ALSO in /src/main/schema/myschema.xsd.

Categories