I have a web service written in Java now I want to consume that web service in the .NET world. I use the WSDL to add a proxy class to my .NET application but when I invoke the Java web service method the response is always null. Anyone familiar with this issue?
UPDATE 1:
Another thing I noted is that I opened one of the svcinfo files and found the following code:
<endpoint normalizedDigest="<?xml version="1.0" encoding="utf-16"?><Data address="http://fff.mywebserive/somewebservie" binding="basicHttpBinding" bindingConfiguration="DOC_TOI_Binding" contract="ServiceReference1.DOC_TOI_PortType" name="DOC_TOI_Port" />" digest="<?xml version="1.0" encoding="utf-16"?><Data
This does not look right to me!
UPDATE 2: Solution (Kind of)
The problem was that the response had a different namespace than used by the client proxy class. This way the object was never deserialized correctly. Once, I changed the namespace to match the response namespace it worked fine. But now if I update the web service reference I will again get the same issue as the namespace will be updated. What is a good way to solve this problem? The only solution I can think of is to ask the creator of the webservice to use the correct namespace.
Using .Net, we can add the java web service in our application using Service Referrence or Web Service Referrence.
Service Reference - This is a dedicated way of calling Microsoft WCF Web Services 3.5 and higher.
Web Service Reference - Way of referencing Non Microsoft Web Service and lower version of Microsoft webservice such as 2.0
We can also use Service reference in non Microsoft web service, we just need to modify some configuration in app.config such as Security Configurations()
Now, when Invoking the web service request method it always ends up with the NULL object response.
(This is caused by the discrepancy between the proxy namespace expected response and the actual xml namespace webservice response )
Sample:
Proxy Code
[return: System.Xml.Serialization.XmlElementAttribute("GetResponse ", Namespace = "http://AJ_TUASON.COM ")]
Public GetResponse Get()
{}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://AJ_TUASON.COM")]
public partial class GetResponse
{}
Actual XML Namespace Response
webservice:GetResponse xmlns:"http://AJTUASON.COM"
To resolve this issue, install fiddler2. This will helps you track and confirm that the web services are working fine.
Then, copy the actual namespace in the XML response from web service.
Paste the actual xml namespace response in proxy class of .NET:
Sample:
[return: System.Xml.Serialization.XmlElementAttribute("GetResponse ", Namespace = "http://AJTUASON.COM ")]
Public GetResponse Get()
{}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://AJTUASON.COM")]
public partial class GetResponse
{}
This will resolve the Null issue.
Note: Do not always rely on the tool that generates proxy class. Tools can surely translate but doing analysis is another thing - AJ
It suggests to me that either your WSDL or your client is incorrect. The client should not be able to tell from the WSDL what language it's implemented in. Check your namespaces.
SOAP UI is a very nice tool for testing SOAP services. I'd recommend it for sorting out this issue.
Looks to me like something tried to escape that snippet. You don't want > you want >
You need to make sure that the service and the client are using the same namespace. Communication is paramount here.
Related
I am trying to do a POC where I am not able to change where the soap client gets their WSDL definition. This soap client has a ".wsdl" hardcoded in their code when they instantiate the service I am POCing. To start I have a pretty simple service, basically, a hello world which can be found here: https://github.com/apache/cxf/tree/master/distribution/src/main/release/samples/jaxws_spring_boot/src/main/java/sample/ws
The issue I am having is that I can't figure out how to configure jaxws or apache CXF to switch the WSDL URL response from http://localhost:8080/Service/Hello?wsdl to http://localhost:8080/Service/Hello.wsdl
I removed the metrics part from the example above and my WebServiceConfig looks like this:
#Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(bus, new HelloPortImpl());
endpoint.publish("/Hello");
return endpoint;
}
Is there any way to get apache CXF to respond with the WSDL document from localhost/<myservice>.wsdl instead of localhost/<myservice>?wsdl
I feel like I am missing something really obvious.
The easiest thing is probably to issue a redirect or if the client doesn't honor that configure a rewrite rule.
You can also switch from a code first approach to a contract (WSDL) first approach and save the WSDL document somewhere else.
?wsdl is hard-coded in several places inside CXF and therefore not just a configuration to change.
I am writing a restlet client that will invoke some Resteasy coded rest services (cannot change the server code, hence cannot use the Restlet way of annotating resources).
Resource Interface is using JAX-RS annotations and have more than one #POST method (one of the biggest problems of Restlet when dealing with this).
I was trying to do my implementaion this way:
IAppLoginResource resource = JaxRsClientResource.createJaxRsClient("http://localhost:9090/rest", IAppLoginResource.class);
final GetLoginAppInfoResponse response = resource.getLoginAppInfo( getLoginAppInfoRequest );
The problem is that the request by default is GET, I didn't find a way to specify the request method like when using ClientResource (which I can't use because I need to deal with JaxbRepresentation and Jaxb problems).
Any sample/snippet of code that implement a Restlet client using JAX-RS annotated resources?
Any ideas?
Thanks,
I've entered an issue for this topic:
https://github.com/restlet/restlet-framework-java/issues/1081
I've tested a sample application based on your code, and it works properly using the current 2.3 branch (future 2.3.3). I wonder if the fix for this issue https://github.com/restlet/restlet-framework-java/issues/1072 helps.
Regarding the documentation, I 'll complete the current page (http://restlet.com/technical-resources/restlet-framework/guide/2.3/extensions/jaxrs), cf this issue: https://github.com/restlet/restlet-framework-java/issues/1084.
You can also have a look at the org.restlet.test project, especially in this package https://github.com/restlet/restlet-framework-java/tree/2.3/modules/org.restlet.test/src/org/restlet/test/ext/jaxrs.
So there is a SOAP webservice. The targetNamespace in the WSDL dynamically changes based on customer's configurable string. Think of it like
targetNamespace="http://myservice."+ [CouldBeAnyString] + "domain.com"
I have two questions:
My basic research tells me that this is a pretty weird(bad?) practice for developing webservices. Thoughts ?
How does one write a client for such a webservice ? I have tested using jax-ws stub and it isn't compatible when targetNamespace changes. Any other suggestions ? I have been trying to understand dynamic client generation based on wsdl. Would prefer a nicer path though if one exists
Update:
I am only the client. Service is provided by someone else.
Same customer has multiple environments (eg test,production) where the service is hosted under different targetNamespaces
If the SOAPUI call works even if the targetNamespace has change, you could use a lightweight HTTP library called HTTPCLIENT.
With this library you don't need to generate client, since you are sending the SOAP envelope as a string, the way you would do via SOAPUI.
The downside is to work with Strings.
In theory, it is feasible to create such a Web Service client.
Steps:
Create Java artifacts based on the WSDL using wsimport.exe of JDK (see: http://www.mkyong.com/webservices/jax-ws/jax-ws-wsimport-tool-example as a reference)
For the purposes of the code displayed below, I have used the Calculator WSDL provided by Microsoft
Create a "Dynamic Web Project" via Eclipse J2EE
Copy the Java artifacts created in step #1, under src folder of the project created in step #2.
Create a new Class containing you main method. Normally you would have something similar to:
String wsdlLocation = "127.0.0.1:8088";//Normally you should retrieve that value dynamically
Url url = new URL(wsdlLocation + "?wsdl");// ?wsdl is actually needed
String namespaceURI = "http://Example.org";//Normally you should retrieve that value dynamically
String localPart = "CalculatorService";// as specified in WSDL file (see name attribute of service tag)
QName qname = new QName(namespaceURI, localPart);
CalculatorService service = new CalculatorService(url,qname);
ICalculator iCalculator = service.getICalculator();
int response = iCalculator.add(1, 2);
System.out.println(response);
Now for the tricky part:
If you have followed the example with the aforementioned WSDL, you should now have several Annotated Classes having hard-coded namespace (e.g. ICalculator is annotated with:
#WebResult(name = "result", targetNamespace = "..."))//where ... is similar to http ://example .org
Using Java reflection modify all the hard-coded values at runtime (see an example here: https://stackoverflow.com/a/14276270/2625635 on how to modify Annotations)
The aforementioned solution should do the trick.
Most client frameworks allow you to create an interface for calling your client (i.e. they create a contract interface). They also provide an implementation for that interface and it is the implementation that has specific annotations or extends "SOAP aware" classes, while the interface is clean of such details.
From what you posted I assume the clients have the same interface, it's just the implementation namespace that's different? If yes, then write your application to use the interface then build a jar for each environment's implementation. When you deploy on test servers deploy with the test jar, while on production deploy with the production jar (i.e. pick a different implementation for the same contract depending on the environment).
Even if the framework you use doesn't create an interface for you, you can create one yourself and hide the various implementations behind an adapter of some sort.
You can also do something like edubriguenti suggested but I wouldn't go as far as working with strings. Work with SAAJ instead.
Background:
I need to consume an existing web service (SOAP over http) that has a couple of issues:
1) The wsdl on the server doesn't even resemble the web service as described in their documentation, which includes a completely different wsdl file
2) The wsdl file provided with their documentation seems to come close to describing the web service on the server, but when I generated java client code using cxf and used it to access the web service, cxf throws exceptions like the following
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://us-labs.companyxyz.com/", local:"searchResponse"). Expected elements are <{http://companyxyz.com/xyz-xml/2.0/}searchResponse>
... 33 more
I'm no SOAP expert, but assuming this means the namespaces in their response don't match those defined in the wsdl.
Since my application is written in java, I was able to connect and get a response using commons http client and a handcrafted SOAP request, so worst case I can fall back to that and parse the response to get what I need.
My questions:
Did I interpret the exception correctly?
If no: any suggestions on how I can debug this?
If yes: can anyone suggest better alternatives to handcrafting http requests and parsing xml by hand? (Getting correct wsdl is, unfortunately, not an option)
Thanks in advance.
Most likely. The response is using the namespace "http://us-labs.companyxyz.com/", but in the WSDL, the same element is declared with namespace "http://companyxyz.com/xyz-xml/2.0/".
I'm not familiar with CXF, but other SOAP frameworks usually offer some kind of logging capabilities. It would probably help you if the SOAP requests and responses are logged somewhere for more specific analysis.
Why is it not an option to get a correct WSDL? If you really are able to "handcraft" correct SOAP requests and expect to be able to "handparse" the responses, you should be able to write the WSDL yourself as well. Of course, the WSDL should be provided to you by the service operator, but if you mean that noone is able to provide you with a correct WSDL, I would consider writing it myself instead of creating and parsing the SOAP messages manually.
I think you interpreted the exception correctly - the namespace is different than expected.
It is also not really unexpected. it is a fact of life that vendor supplied wsdls are not always correct. We actually write our own WSDLs and XSDs for vendor applications for just that reason.
You can use your own WSDL even run-time. There are some SO questions on that, here and here.
You could also have a look here. I haven't tried it, but it could work.
We actually extend the generated service and create a port supplying a WSDL located on the classpath using the JaxWS Service constructor. That works fine for us.
We debug CXF by dumping the incoming and outgoing messages. There seem to be quite a lot of methods to do just that. We use either a proxy between de web service and our client, or recently a cxf.xml file somewhere. Using a -D flag we temprarily configure this.
-Dcxf.config.file=/home/me/cxf-debug.xml
and cxf-debug.xml contains something like:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<cxf:bus>
<cxf:features>
<cxf:logging/>
</cxf:features>
</cxf:bus>
</beans>
http://cxf.apache.org/docs/debugging-and-logging.html
Both responses suggested the same basic approach, which turned out to be the correct one.
I fixed the provided wsdl to make it match the web service, and I was able to use cxf, which saved me a lot of hand coding.
The main problem with their wsdl was in fact a namespace issue. The essence of the problem was as follows: their wsdl defined two namespaces, both of which have a "searchResponse" element.
{http://us-labs.companyxyz.com/}searchResponse
was defined in the wsdl to contain 0 or more
{http://companyxyz.com/xyz-xml/2.0/}searchResponse
But in their response the nested searchResponse wasn't qualified by {http://companyxyz.com/xyz-xml/2.0/} so cxf interpreted it as a {http://us-labs.companyxyz.com/}searchResponse
I fixed it by introducing a new type.
Thanks to both responders.
I had a .Net webService that returns a custom class, lets call it "MyClass", used like this example:
[WebMethod]
public MyClass sampleMethod()
{
return new MyClass();
}
If works ok when invoked from a .Net application.
From a Java application using AXIS I am getting the error "MyClass is referenced but not defined".
How can I overcome this issue?
Two things that spring to mind:
You're missing a schema that defines MyClass
A namespace issue surrounding the definition of MyClass
People will be able to help you further if you can post the WSDL and Schema(s)
First, you have to create a Java proxy: This can be achieved by generating a client by pointing axis to the Web Service WSDL location.
Your Web Service might look like this: http(s)://server:port/path/service_def.asmx and add ?wsdl to the end of the wsdl definition (i.e. like this http(s)://server:port/path/service_def.asmx?wsdl).
From there, generate and client and use the proxy to talk to your .NET Web Service.
PS The possible cause for this is that your class is not defined in a namespace. Check your WSDL definition and see if there's an <xsd:element /> for your class and try adding an ns: to it and generate java proxy with Axis.