I'm using wsdl files to generate client & is working fine on my local server since the generated files have path like "C:\path\to\wsdl\Air.wsdl"
I'm trying to replace all the paths as above to the one that work on live server I've found some hints but I'm not so sure how to implement it (I'm new to web services).
Below is how my files currently look like
#WebServiceClient(name = "AirService",
wsdlLocation = "file:/C:/Eclipse WorkSpace/TravelPortCXF/WebContent/wsdl/air_v33_0/Air.wsdl",
targetNamespace = "http://www.travelport.com/service/air_v33_0")
static {
URL url = null;
try {
url = new URL("file:/C:/Eclipse WorkSpace/TravelPortCXF/WebContent/wsdl/air_v33_0/Air.wsdl");
} catch (MalformedURLException e) {
java.util.logging.Logger.getLogger(AirService.class.getName())
.log(java.util.logging.Level.INFO,
"Can not initialize the default wsdl from {0}", "file:/C:/Eclipse WorkSpace/TravelPortCXF/WebContent/wsdl/air_v33_0/Air.wsdl");
}
WSDL_LOCATION = url;
}
This seems to be like it should be changed (I'm not sure about that, found it on googling)
#WebServiceClient(name = "AirService",
wsdlLocation = "classpath:wsdl/air_v33_0/Air.wsdl",
targetNamespace = "http://www.travelport.com/service/air_v33_0")
static {
URL url = AirService.class.getClassLoader().getResource("wsdl/air_v33_0/Air.wsdl");
if (url == null) {
java.util.logging.Logger.getLogger(AirService.class.getName())
.log(java.util.logging.Level.INFO,
"Can not initialize the default wsdl from {0}", "classpath:wsdl/air_v33_0/Air.wsdl");
}
WSDL_LOCATION = url;
}
But I actually don't understand how that method works.. Can someone please make me understand how can I change the path and where to place the wsdl files in the project so that it works properly on the live server and also the difference between both the codes.
Also I don't want to generate every-time when build is created, I want to generate the files (that are already been generated), place the wsdl somewhere in the project folder from where it can be accessed and then change the path in the Java files (by replacing all the paths at once) as in the above codes.
Few intro points for you:
Wsdl file contains description webmethods callable on the server (in general method names, their input parameters and its types and types of results of this methods). Therefore wsdl file is like contract between client and server - client knows what methods to call on the server, what parameters it will need to send with method name, and what type of result it can expect.
You can download and store wsdl file from server, and then use it for generation of special client class(es) (called stubs). This classes have java methods 1 to 1 corresponding to web service methods described in wsdl file. Source code of these classes is generated automatically by special tool (wsimport) which reads content of wsdl file and generate corresponding methods. From your perspective as developer of client, it is then very simple - you need only in some way create instance of this class (giving it url of wsdl file on the server) and call it's method like you call any other Java class method. (Generated implementation code of this methods cares for serialization of inputs and sending of webservice request to server, and then deserialization of response back to you, so you will obtain normal Java object as a result of call).
Maybe you now ask, why you need to set url to server's wsdl file before call of webservice method. Answer is that client code before calling your webservice automatically download's wsdl from the server and check's if it does not change meantime (if yes it does not call webservice and throws error). It sometimes happen that developer of server changed e.g. parameters of webservice method and you as client developer have still old version of wsdl, therefore validation aspect of this technology saves you a lot of time.
Now real examples:
Look at JAX-WS deployment best practice: WSDL location and client generation question to see client code how webservice method (hello) is called using HelloWorldPOCImpl stub class.
For server side implementation you need only two annotation #Webservice and #WebMethod, please look at chapter 3.1 to see example: https://metro.java.net/getting-started/building-a-simple-metro-application.html
For server, you dont need to create wsdl file manually, server generates wsdl file automatically - based on your code and mentioned annotations.
Related
I'm trying to write simple java soap web service ,for that purpose download eclipse and create dynamic web application,in that project create this class and method:
package test;
public class Sayam{
public String helloworld(){
return "Hello world!";
}
}
on that class right click and choose web service and generate web service,every thing is ok and web service return this result:
<soapenv:Envelope>
<soapnv:Body>
<helloWorldResponse>
<helloWorldReturn>Hello World!</helloWorldReturn>
</helloWorldResponse>
</soapenv:Envelope>
</soapnv:Body>
i want change this line:
<helloWorldReturn>Hello World!</helloWorldReturn>
to my custome element:
<QueryResult>Hello World!</QueryResult>
You should not be aware of final contract's names, it's no matter. Any client should use any "wsdl to code" (codegen) tool.
You and your service clients should not treat directly with the XML layer (of the most general SOAP protocol).
If you are the webservice owner, you can define it as "code first" (you define your classes and methods and the platform update the WSDL definition for you).
If you aren't the owner, you should demand the contract (the WSDL) and use any codegen (wsimport is a typical one).
If you are trying to define a webservice for certain XML format and you have the XSD definition or whatelse, do not try to create a SOAP service, instead, treat that layer (the XML data) directly (using the proper tools of course like the standard specification for Java JAXB).
If anyway, you want to change that word, you have some options:
write the WSDL yourself (manually or using some tool) and then, create the webservice (eg. using wsimport).
search if you platform is able to do this (jaxws is not without hacking)
Is there any way to use soap-rpc web services such that the client is generated via a shared interface? Restful web services do it this way, but what about soap based? Do you always have to use a tool like Axis or CXF to generate your stubs and proxies, or is there something out there that will set it up dynamically?
Thanks.
EDIT #1:
To clarify, I'm looking to do something like this:
Common interface:
#WebService
public interface MyWebService {
#WebMethod
String helloWorld();
}
This common interface can already be used to create the server side component. My question is: can this type of common interface be used on the client side to generate dynamic proxies? Restful web services do it this way (Restlets & CXF) and it seems the .Net world has this type of functionality too.
I would see this tutorial of JAX-WS useful for your purposes:
In the example code the Web Services Client is configured by adding an annotation #WebServiceRef with a property pointing to the WSDL location to the client implementation class and no tools are needed to access the stuff from the Web Service that is referenced.
Was this the way you would like to have it, or did this even answer to right question?
Not exactly sure what you're looking for, but if you don't want to rely on JAX-WS/JAXB-generated artifacts (service interfaces and binding objects), you can make use of the Service and Dispatch APIs. For example:
QName serviceName = new QName(...);
Service service = Service.create(serviceName);
QName portName = new QName(...);
String endpointAddress = "...";
service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);
Dispatch<SOAPMessage> dispatch = service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);
SOAPMessage request = ...;
SOAPMessage response = dispatch.invoke(request);
Check Apache CXF. Configuring a Spring Client (Option 1).
When you want to call a webservice, you must have knowledge of methods implemented on it. For that, We need to make stubs OR we can read it from WSDL.
I have created a WS client, using AXIS2 libraries, which is without stubs. The thing is, for each diff. WS we need to create response handles.
You can call any WS method using SOAP envelops and handle the response.
//common interface for response handlers...
//implement this for diff. web service/methods
public interface WSRespHandler{
public Object getMeResp(Object respData);
}
//pass particular handler to client when you call some WS
public class WebServiceClient {
public Object getResp(WSRespHandler respHandler) {
...
return repHandler.getMeResp(xmlData);
}
}
Please check the link below, which shows the example interface for WS client.
http://javalibs.blogspot.com/2010/05/axis2-web-service-client-without.html
For every diff. WS method we can have diff. implementation for WSRespHandler interface, which will help parsing the response.
Not knowing java so well, but being forced to learn some to accomplish a task that I was given, I needed to consume a .Net service that I have already written, I had to do a little research.
I found that 99% of the examples/samples/problems with invoking a method call against a .Net service, or any service for that matter involved using J2EE (ServiceManager) or build classes and a proxy that reflect the service being invoked. Unfortunately for me, none of this would work. I was working "in a box". I could not add new classes, could not WSDL references, did not have J2EE, but DID have access to the standard java libs.
I am used to doing this sort of thing in pretty much every other language but java, but now there was no choice, and java it was.
A lot of digging and figuring out all new terminology, methods, classes, etc, I knew I was getting close, but was having issues with some small items to complete the task.
Then I came across this post: http://www.ibm.com/developerworks/xml/library/x-jaxmsoap/
As long as you have some sort of idea of what you need to send the soap service in term of the soap envelope, the above link will give you the information you need to be able to invoke a service without the classes, wsdl class generators and J2EE, apache or other dependencies.
In an hour from the time I read the mentioned article, I had a class working and about 10 minutes later, converted the code to the "in the box" solution.
Hope this helps
Apache Tuscany might help you, although it may be heavier than you want
http://tuscany.apache.org/
We have been provided with a wsdl and xsd schema by a company we are working with via email. The web-services we are interfacing with are accessed through a IPsec tunnel. There are local references(on their end) in the published WSDL which means we cannot consume it.
1st question: Is this a common setup? I thought the point of having a WSDL was not only to define the contract but to also expose the service to consumers.
I can easily generate client/server code off of the provided WSDL using wsimport, wsconsume, etc.. I know when my generated client makes a call to my generated service it produces the correct message I need.
2nd Question: Is there an easy way to route this to a different soap address?
I just want to be able to do something like:
SalesTaxService svc = new SalesTaxService();
SalesTax tax = svc.getSalesTaxPort()
tax.getRate("NY");
But not use the soap address defined in the WSDL. I would like to avoid writing a bunch of dispatch clients for each method.
Am I missing something?
*In response to skaffman:
This is what was generated. It defaulted to wsdlLocation as a name shrug
#WebServiceClient(name = "SomeService")
public class SomeService_Service extends Service {
public SomeService_Service(URL wsdlLocation, QName serviceName) {
super(wsdlLocation, serviceName);
}
public SomeService_Service(URL wsdlLocation) {
super(wsdlLocation, new QName("urn:some_service", "SomeService"));
}
}
I thought the point of having a WSDL
was not only to define the contract
but to also expose the service to
consumers.
No, WSDL is purely a descriptive tool, it has no real runtime role. The web service operates completely independently of the WSDL. It's not uncommon for the WSDL to not be exposed.
Is there an easy way to route this to
a different soap address?
That depends entirely on what web service implementation you're using, and you don't say, although I'm guessing JAX-WS. If that's the case, the artifacts that JAX-WS's tools generate allow you to pass in the URL to the client stub constructors, I think.
So I figured out why I was having a problem. I was assuming that the wsdlLocation had to be the WSDL that the actual service was publishing. This of course is not the case. The solution is to package a local WSDL with the correct SOAP:Address for the actual service into the client.
edit
I found out that you can alter the endpoint address programmatically without having to alter the actual WSDL:
HelloService service = new HelloService (
this.getClass().getResource("originalHello.wsdl"),
new QName("http://example.org/hello", "HelloService "));
HelloPort proxy = service.getHelloPort();
Map<String, Object> ctxt = ((BindingProvider)proxy ).getRequestContext();
ctxt.put(JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE, 8192);
ctxt.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://new/endpointaddress");
proxy.sayHello("Hello World!");
Credit goes to : Jianming Li
We currently have this
#WebServiceRef(wsdlLocation = "META-INF/wsdl/localhost_8080/SwitchWSService/SwitchWebService.wsdl")
private SwitchWSService switchWS;
Can't we point to the real web service and it still work.
#WebServiceRef(wsdlLocation = "www.web.com/SwitchWSService/SwitchWebService.wsdl")
private SwitchWSService switchWS;
Chapter 7.9 of the JAX-WS 2.0 spec says:
wsdlLocation:
A URL pointing to the
location of the WSDL document for the
service being referred to.
...
The wsdlLocation element, if
present, overrides theWSDL location
information specified in the
WebService annotation of the
referenced generated service class.
So your approach is basically OK. But strictly speaking
www.web.com/SwitchWSService/SwitchWebService.wsdl
is not an URL since an URL or URI in general must start with a scheme (see RFC 3986).
Let me see, you want your WSDL to be published onto some external URL and then give clients that URL to retrieve WSDL from. That means your service won't be the source of WSDL download, and thus you don't need to provide ANY wsdlLocation for it.
Is it possible with Axis2 and Eclipse to generate a Web Service client and have it use java types that you already have in packages instead of creating it's own types. Reason being of course if I have type A already created and it creates it's own Type A I can't just assign variable of type A to variable of type B.
The wsdl is being generated from a Web Service deployed to an application server.
If it's not possible to generate it from that would it be possible to generate a client from the already existing java files.
If you really want to reuse existing classes, you can call the Axis2 API directly without generating a client using wsdl2java. Below is some relatively simple code to call a web service. You just need to fill in the web service endpoint, method QName, expected return Class(es), and arguments to the service. You could reuse your existing classes as the return values or arguments.
If your web service is pretty complicated then you may find that you have to go deeper into the API to get this approach to work.
serviceClient = new RPCServiceClient();
Options options = serviceClient.getOptions();
EndpointReference targetEPR = new EndpointReference("http://myservice");
options.setTo(targetEPR);
QName methodName = new QName("ns","methodName");
Class<?>[] returnTypes = new Class[] { String.class };
Object[] args = new Object[] { "parameter" };
Object[] response = serviceClient.invokeBlocking(methodName, args,
returnTypes);
You are generating the web service client from wsdl, correct?
The only thing that the wsdl2java tool knows about is the information in the wsdl, so it won't know about any types that you have already created.
If you can get the type information into the wsdl you may get it to work, although I have never tried.
If you want an easy way to copy from Type A to Type B then you could try BeanUtils.copyProperties, as long as the setters and getters of Type A and Type B match.
pretty much most java webservices projects go through this. I don't know if the .NET/C# world have a more elegant solution.
It makes sense, as Mike mentioned, to use BeanUtils.copyProperties.
BR,
~A
If you use eclipse as your ide, that is waht you need: http://www.eclipse.org/webtools/. It does beyond other things exactly what you want.
You can directly use ServiceClient class to call web service, which provides call using XML only and returns XML response. For different methods of web service, you have to convert the XML response to some java POJO to use it. Only Response handling needs to be done at your end. that you can do like from XML to Map etc...
So you won't need any other stub classes to call any web service, only needs to handle response XML. You can convert XML to POJO using Castor or JAXB libs.
This is the way you don't need to modify your client every time for diff. web services. You can develop like providing a response handler to client externally. So that for every different web service you will have diff. response handler class which is implementation of you interface.
//common interface for response handlers...
//implement this for diff. web service/methods
public interface WSRespHandler{
public Object getMeResp(Object respData);
}
//pass particular handler to client when you call some WS
public class WebServiceClient {
public Object getResp(WSRespHandler respHandler) {
..
return repHandler.getMeResp(xmlData);
}
}
reference:
http://www.developer.com/java/web/article.php/3863416/Using-Axis2-and-Java-for-Asynchronous-Web-Service-Invocation-on-the-Client-Side.htm
http://www.devdaily.com/blog/post/java/java-web-service-client-read-array-list/
thanks.
www.techlads.com
In case this post is still of any use to someone I read the axis2 generating clients guide: http://axis.apache.org/axis2/java/core/docs/userguide-creatingclients.html.
It seems that the Axis2 Eclipse plugin is configured to call ADB code generation in integrated mode (see http://axis.apache.org/axis2/java/core/docs/adb/adb-howto.html), thus creating inner classes in the Web service stub. I don't know if changing the generation mode to expanded mode (generate data classes out of the stub class) is possible, but you can do it command line using Wsdl2Java:
%AXIS2_HOME%\bin\WSDL2Java -uri <wsdl file path> -p <package name> -u
The -u option tells the ADB code generator to create data classes as separate classes and not inner classes in the stub.