I am looking for a way to easily generate SOAP requests from a wsdl file. for example, something like this:
WSDLObject myWsdl = new WSDLObject("http://www.whatever.com/myService?wsdl");
SOAPRequest myRequest = myWsdl.generateSOAPRequest();
Is there anything like that?
I am trying to do it dynamically via another application, so tools like WSDL2Java dont work for me (at least I think). I need to be able to generate these requests from user input, and then work with them from there.
any help is appreciated.
Please see this answer: How to get response from SOAP endpoint?
What you basically want to do is use the wsimport tool that ships with the JDK. So long as Java is on your system's classpath, you should be able to go to any terminal or console and do:
wsimport http://www.whatever.com/myService?wsdl -p com.company.whateveruwant -d . -keep
With a choice of options (-d specifies the directory to output the generated code). This being done, you'll be able to invoke the web service with the auto-generated code quite simply, such as like:
CustomInterface soap = new CustomEndpoint().getCustomInterface();
System.out.println(soap.getAnswerFromWs("ParamValue"));
You can with WSDL2Java, the unique change is that you work with Java proxy objects and set the attributes of this objects to generate the SOAP request. Other way is use SOAPUI, for example to generate the SOAP message, and directly construct your SOAP message as StringBuffer and use directly a socket to call the service composing the complete HTTP/SOAP message from scratch.
Related
From a colleague I have received a WSDL file that describes the web service he is offering, and which I am supposed to call from my code. I would now like to do two things:
1) Implement the client
2) Have a stub server that I can use for testing, until I have access to the real server.
What I tried is the following:
wsimport -clientjar foo.jar foo.wsdl
This gives me a jar file that contains the Datatype that will contain the data to be posted to the web service, and also an ObjectFactory. I guess I will have to use it as follows:
TestDataType testDataType = new TestDataType();
testDataType.setFoo("foo");
testDataType.setBar("bar");
ObjectFactory objectFactory = new ObjectFactory();
JAXBElement<TestDatatype> request = objectFactory.createTestRequest(testDatatype);
Now how do I send this request?
Also a class TestDemoService annotated with #WebServiceClient has been generated. How do I run this class?
Any advice is highly appreciated.
You've created the client. To use this client you need to set the endpoint(if not already set) and call the service using the generated api.
This site should be a good reference.
Using wsimport
I am building Java application for Online Web Services and let's call it application A . I got the WSDL file form the second party so I can communicate with their application and let's call it application B.
From the WSDL file I generate the Java classes needed which are Requests and Responses classes. Application A will send some request object after setting the needed parameters and excepting response object from application B.
The connection is established and both applications A and B are communicating with each other.
Question:
From application A how can I get the xml data(file or text) for the request object before sending it to application B?
As described the connection is done by passing Java object as request and I know that in some point this request will be converted to xml file. How to get it?
--- EDIT ----
Important Information is missing that may cause confusion.
I am generated the Java Classed have been generated using Axis framework
I don't have much reputation to post a comment, so here is my answer: If you aren't yet using some framework use Apache CXF, If you want to capture the request before sending it application , you can either use cxf interceptors there are some inbuilt interceptors which can do this or you can create a custom interceptor with correct phase ( e.g. post marshal)
The problem is solved by adding the following statements in the bindingStub class that has been auto generated from the WSDL file for the web-services you are trying to access.
String request = _call.getMessageContext().getRequestMessage().getSOAPPartAsString();
String response = _call.getMessageContext().getResponseMessage().getSOAPPartAsString();
These statements should be placed after the following method call _call.invoke otherwise you will get NullPointerException .
_call is a variable of type org.apache.axis.client.Cal and it is auto generated by Axis
I am using wsimport to generate client code for several WSDLs that are served by my application. I have to run the app in several different places. I am trying to simplify my client code generation/management problem.
What I have sort of slid back into is this. I have 3 interfaces and the app is installed in 3 places. At this point, I have to generate 9 source bundles. I also have 3 source directories, having driver code for each interface.
So, I have:
src/srvr1.intf1/
src/srvr1.intf2/
src/srvr1.intf3/
src/srvr2.intf1/
src/srvr2.intf2/
src/srvr2.intf3/
src/srvr3.intf1/
src/srvr3.intf2/
src/srvr3.intf2/
src/all.intf1
src/all.intf2
src/all.intf3
You can see how bad this is going to get when I have to move it up to over a dozen sites.
One thing that has occurred to me is that I can go into the generated code and replace the hard-coded WSDL locations with System.getProperty("currentWSDL") and I can set this at run-time. SO, I got from 12 to 6.
I can use introspection in the "all" code to make it so that that is one class. This gets me to 4. And adding a server does not increase that number.
So, as far as I can see, if I go in and change the WSDL references to a property look-up, then I have to re-do that every single time I run wsimport. Does this make sense?
Is there some way to get wsimport to use a property-read instead of a hard-coded string for the WSDL? I can even give it a value of the WSDL when I run wsimport. I just do not want to have to maintain n copies of the all 30+ client classes for n servers that are running the exact same app.
You can set your service url like this. there is no need for generating wsdl client for different server deployment unless it is changed. You generate proxy and then in every client read url from any resource ( local file , database ...) and set url like this
String url = //read url from config file or any other resoure like db
((BindingProvider)proxy).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
I am trying to generate the client code from a WSDL.
I need to work on the Jdeveloper 10g IDE.
I generated client code from WSDL using the inbuilt tool Oracle JAX-WS 2.1.5.
For a particular WSDL this tool is generating around 122 java classes that does not include the Locator class. While running the code, I get a class not found exception for WebServiceLocator class.
However, when I am using Apache Axis 1.4 ( Eclipse IDE ), it is generating 63 java classes and it also includes the WebServiceLocator class, but this is not generating all the required methods that are needed for authentication, though ,Oracle JAX-WS 2.1.5. is generating those methods.
I tried merging the java classes generated from Eclipse into Jdeveloper, but then I am getting a lot of errors related to method signatures.
Is there some particular reason why these two different tools are generating different client codes, and none of them complete?
This is probably a bit late, but for those running into the same issues, this might be helpful.
If you really want to use Axis 1.x authentication is done on your client class as follows:
MyLocator bindingService = new MyLocator();
bindingService .setPortEndPointAddress(myEndpoint);
MyPort port= bindingService.getMyPort();
((Stub)port)._setProperty(Stub.USERNAME_PROPERTY, myUsername);
((Stub)port)._setProperty(Stub.PASSWORD_PROPERTY, mPassword);
//Perform your query here
I would personally use JAX-WS. Use wsimport to generate the stubs (SOAPUI has a nice plug-in to simplify this). For authentication on a JAX-WS client its easiest to save the wsdl locally and export it as part of the jar then load it in the client. This removes the need for HTTP authorization required to access the wsdl in the first place.
URL myWsdlUrl = getClass().getClassLoader().getResource("wsdl/myWsdlFile.wsdl");
MyService service = new MyService(myWsdlUrl , new QName("uri", "localpart"));
myPort port= service .getPort();
BindingProvider bp= ((BindingProvider)vPort);
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, myEndPoint);
bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, myUsername);
bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, myPassword);
//Perform query here
I am using axis2 to expose a method of existing class as a web service (bottom-up approach). The method takes a complex object (non-primitive type) as a parameter and returns a complex object as well.
I understand that axis2 will try to generate the schema for me in the wsdl file when I expose the method as a web service, and I can get the wsdl file by visiting the web service url and append ?wsdl into the end of it.
But upon closer examination, some of the attributes of the complex type in the parameters are represented as xs:anyType in the schema part of the resulting wsdl. The attributes that are converted into xs:anyType is a List. The bad thing with this is that when I generate the stub code for the client code, the method signature to set that particular attributes will take in an object as a parameter i.e. setAttribute(Object obj).
So my solution to this is to use JAXB 2.0 to generate the xml schema of the classes I need and then, import the xsd into the wsdl file that is generated by axis2 (downloaded from the web service url + ?wsdl) and use the edited wsdl instead of the one automatically generated. This solution seems to be working well for the client side. The method signature to set the attributes generated by the stub code will take in the proper type i.e. setAttribute(AnotherComplexType abcd). And by using tcpmon, I can see that the xml that is sent from the client to the server seems to be correct.
However, this approach does not work well for the server side because axis2 does not use the JAXB 2.0 annotation to convert the xml received back into the classes that the exposed method will be able to process.
My question is, is there anyway to solve my problem? The possible ways I can think of is either to modify the way axis2 process the xml after receiving it (I'm okay with processing it manually if there is indeed a way), or to make axis2 work well with JAXB 2.0 annotation? Or maybe any other idea?
Note: I'm not using the JAX-WS part of axis2
In the end I solved this myself. I generated the stub code for server side using the wsdl, modify the messageReceivers to use the generated message receiver instead, write a wrapper class that implements the generated interface, write a converter to convert the object from generated types in the parameter of the wrapper class methods going to be exposed to my internal types and expose the wrapper class instead.