We have some existing Java code running on a Tomcat server that we want to allow code on another machine to execute, so we are looking into web services. I am new to web services and I think I'm probably doing something wrong here.
I have followed a few online tutorials on how to deploy a JAX-WS web service in Tomcat. I have created a web service class and annotated it with #WebService, written a web.xml and sun-jaxws.xml file, packaged those files (plus the JAX-WS jar files) into a .war file, and deployed it into Tomcat. That appears to be working, as I can load the WSDL file in a browser pointed at Tomcat.
It's the web service client I'm having trouble with. First of all, there are existing classes on the server side that get mapped into a database. We want to allow the client to use those same existing classes and create instances of out of them, invoke the web service, and then have the objects get stored into the database. However, when I ran the wsimport command against the server's WSDL file, it generated a bunch of Java classes, a lot of which are similar to our existing classes. I guess we have to use those instead of our existing classes? So much for code reuse, unless I'm confused, which is very possible.
So now I've written the client using those classes that wsimport generated. But I'm getting compile errors. Some of the fields in our existing Java classes are of type java.net.InetAddress. But for some reason, wsimport generated its own InetAddress class, and this is what it looks like:
package ems.server.webservices;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "inetAddress")
public class InetAddress {
}
Yeah it's just a class with nothing in it! So a lot of the compile errors I'm getting say:
WSClient.java:37: setAddress(ems.server.webservices.InetAddress) in ems.server.webservices.NetworkAddress cannot be applied to (java.net.InetAddress)
networkAddress.setAddress(InetAddress.getByName("1.1.1.1"));
I'm trying to create a java.net.InetAddress, but it wants me to use the empty class that was generated by wsimport. I must be doing something wrong here. Please enlighten me.
We have some existing Java code running on a Tomcat server that we
want to allow code on another machine to execute, so we are looking
into web services
Web services for this? Why?
First of all, there are existing classes on the server side that get
mapped into a database. We want to allow the client to use those same
existing classes....So much for code reuse
Really bad idea. The purpose of Web Services is not code-reusability but interoperability. Trying to reuse business classes that actually carry the semantics of the programing language you are using, is not only a bad practice but can lead you to many issues unless for most trivial web services where you also control the client.
when I ran the wsimport command against the server's WSDL file, it
generated a bunch of Java classes
When you run the wsimport all the necessary artifacts required for the web service client to communicate to the web server are created. This includes all the stub classes that help in transforming your classes during the SOAP marshalling/demarshalling
But I'm getting compile errors. Some of the fields in our existing
Java classes are of type java.net.InetAddress
java.net.InetAddress is a Java specific class. You should not be exposing that in the first place. That is why the code generator creates the empty java.net.InetAddress.
To be honest I can not give you a direct answer for making this work. The only I hint could give you is that if you annotate the InetAddress fields with #XmlTransient they will not be exposed in WSDL and you will not have that problem. Of course, you don't say if this field is needed for you so, perhaps my suggestion is useless to you.
But my recomendation is to switch your approach. You are on the wrong path IMHO.
The only recomendation is to change your approach.
Related
We have a SOAP axis2 server that we cannot control that exposes some webservices.
We created a webservice client using the wsdl from that webservice. It generated the java code from the wsdl using Eclipse
This will be deployed in production but if the server adds a outputfield for example, our code will break and we will need to generate the java code again, make a jar and deploy on the server.
This does not make any sense. It should be 100% or extremely close of update.
Does it make sense to generate the java code from the WSDL and xsd from the local files?
All the examples I saw were like this
you can configure your JAXB2-Deserializer to ignore unkown (optional) elements, that preserves a bit of compatibility. Or modify the generated xsd to allow additional elements (xs:any) on the desired level.
But yes, that's a problem mostly solved by management
I inherited a codebase, a chunk of which is a webservice built using the Eclipse generators. The generated code appears to have numerous file paths (for wsdls, etc) which refer to locations on the original developer's box. For example, in a service class's static constructor:
url = new URL(baseUrl, "file:/C:/Users/OldDeveloperName/workspace/ServiceProject/WebContent/WEB-INF/edmo/AXIS-1-4/MainEntityService-1.0.wsdl");
Seems like a bad thing, to my naive eyes. Is this a) OK, or b) fixable? I know I could just edit it now, but there's quite a few service files and it seems like there'd be an easy correction if it's a common problem. I mean, as-is it doesn't even look deployable to me.
Original developer obviously followed the approach to store WSDL locally, which is actually a good practice. Namely, JAX-WS client before execution needs to retrieve WSDL once more from the original location to check additional metadata etc. (it sounds weird, but that's how it works). But, what if original WSDL is not available anymore or the Web service developer updated the WSDL with e.g. new method? Your Web service call would not be executed and that is not probably what you want. Therefore, people started to store WSDL together with their client, to avoid vulnerability on WSDL availability/change.
Is this a) OK, or b) fixable?
It is not OK to store WSDL on local filesystem, and that is where the original developer made the huge mistake. WSDL should be packed together with Web service client (in same JAR) and retrieved directly from the archive. There are several ways how to retrieve WSDL locally, see this tutorial for instructions. One way or another, you will have either edit the WSDL location or completely change the old code :)
References:
Why does JAX-WS clients need WSDL access?
My question probably sounds all wrong since I'm not sure what to ask exactly. I'm very new to web services in general but get a very high level idea. I'm looking at some code where the classes/methods are annotated and exposed for service calls.
The wsimport command can be used to call the http://.....?wsdl which it looks like dynamically generates these the client classes. I do not see a specific WSDL file so i'm guessing the JAX-WS is creating and sending the client source code to the client whcih downloads it and compiles it to the respective classes.
I notice some difference in the client generated class and the original server side class such as the missing toString() method and equals() method. Trying to read about this suggested something about custommized JAXB bindings and stuff. My questions are:
Does anyone know and can share information that gives a better
understanding of the kind of process I'm seeing. i.e. how the
annotated methods are magically appearing on the client side as part
of their respective classes?
Regarding the JAXB binding most of the websites begin from an
existing WSDL. How does this fit into my current problem?
Thanks
I have a public EJB class that I want accessible online as a web service. I have generated a WSDL and the SOAP mesasging seems to work. I used soapUI to test the connection. What I'm not clear about is how would I then use this exposed web service. I'd like to try another language like Python to then make calls through that interface. I know that the WSDL is supposed to help a potential client build it's client side code but I'm not sure about how to specify the connection and location and login information if I had that. I know I'm asking a large topic but any information would help. Thanks
Edit: so basicaly I'm just wondering do I have to use tools to generate my client code from the WSDL like axis2. Or whatever Python uses. Or can I write the code by hand? What's generally done. is the server reference included in that WSDL and are call methods generated usually?
Take a look at ZSI
But ZSI is too complex and spends more time to generate proxies
I suggest you to use suds. suds generates the proxies On the fly and so fast, i used it in some projects.
another packages are available:
soaplib
SOAPy
pysimplesoap
I've seen this problem all over the Web, but still haven't found a clear solution that has worked for me. Here's the issue:
I am trying to create a Web service client in Java. The client needs to be a console app that will be placed on a server and automatically run at a certain time interval. The Web service I am trying to consume was written and is hosted by a third party company. The service was written in ASP.NET. The company in question has several services that we hit. All of them are written in ASP.NET. I have never dealt with these services until 2 days ago when I was tasked with consuming 2 of the services and building an Excel spreadsheet from the data. Before I continue, let me describe my development environment. Some of this is relevant, some is not, but I want to include everything:
Windows 7 Professional 32-bit
NetBeans IDE 6.9.1
Java JDK 1.6.0_17
jre6
Glassfish 3 Open Source Full-Platform Release
All software has had all available updates applied
On to the problem. When I added the first Web Service Client to my console app, I was surprised at how smoothly the process went. Most of my experience writing Web Service apps is in .NET. I was able to import the WSDL and NetBeans generated all classes on the first try. Within 5 minutes, I was able to make my first call to the service and was greeted with the expected response, letting me know that my attempt was successful. I then added the second Web Service Client to the console app using the address to the second WSDL I needed. This is where I ran into a major problem.
Upon importing the WSDL, I was alerted to an error by NetBeans stating:
Web Service Client can not be created by JAXWS:wsimport utility.
Reason: undefined element declaration 's:schema'
After abusing Google for the next hour looking for a solution, I finally decided to apply some trial and error. Looking at the Output window in NetBeans, I could see that it was complaining about 3 specific lines. Once I took a look at the WSDL, I could see that those 3 lines were exactly the same, as follows:
<s:element ref="s:schema" />
These 3 lines were found in random places from the top of the WSDL, down to about half-way through. I removed these lines from the WSDL found in the Web Service References folder, leaving the WSDL in the META-INF folder alone. I then did a refresh on the service reference and much to my surprise, NetBeans parsed the WSDL and generated my classes just as before. Great, right? Well, here's where problem #2 comes into play.
Now that I was able to compile my app with no errors, I had to try to hit the service to see if my hack had worked. It did not. Because of another bug in JAXWS, I have to provide the URL to the WSDL in the constructor when creating a service object. This means that the WSDL I fixed is being ignored and the service is now back to using the WSDL that can not be parsed. When I tried to provide the location of WSDL I edited locally within my project, I was greeted with another compilation error stating that I had a NullPointerException. It said that I needed to initialize the object before using it.
I have researched what seems like an infinite amount of topics on this site looking for and trying any solutions that have been provided. I have also tried solutions from all over the Web, all with no luck. If anyone has any advice for me, any tips, tricks, hacks, please let me know. I'm open to any suggestions at this point.
Thanks in advance for any assistance provided.
One-sided contract changes may lead to problems.
Assuming the s prefix refers to the http://www.w3.org/2001/XMLSchema namespace, it looks like your WSDL references XML schema types. JAX-WS is probably unable to resolve this when generating the JAXB bindings.
You can download the XSD from http://www.w3.org/2001/XMLSchema.html; at a minimum, you'll need XMLSchema.xsd, XMLSchema.dtd and datatypes.dtd. Generating Java types from this may require fiddling with your JAXB binding configuration.
Alternatively, it may be easier to just use dynamic JAX-WS client code. You can use a tool like soapUI to create/test sample XML requests.
If you do decide to edit the WSDL, the generated service code should have a constructor of the form Foo_Service(URL, QName) that allows you to provision the WSDL locally (e.g. from your classpath).
The first thing I'd do is try to open it in one of the tools meant for testing SOAP services, like SoapUI. If you have schema not resolving, that is possible there will be pieces of code that you may need that won't be generated as well. I had that happen recently with a vendor supplied "web service", and after much dissembling they "miraculously" found an alternative set of services that worked fine.
You could also try some of the alternatives to Jax-Ws, like CXF or Axis.