I work on a web application that calls multiple web service clients from within its code.
Each web service has some common namespaces, however I am currently mapping these namespaces to different packages when I generate each client
e.g.
Web Service 1's namespace1 -> com.company.webservice.client1.service
Web Service 2's namespace1 -> com.company.webservice.client2.service
Where namespace1 refers to the same namespace URL.
Using Wsdl2Java's namespace2package option:
// Web Service Client 1's namespace parameter
--namespace2package http://www.multispeak.org/Version_3.0=com.company.webservice.client1.service
// Web Service Client 2's namespace parameter
--namespace2package http://www.multispeak.org/Version_3.0=com.company.webservice.client2.service
I can generate web service client code for these services without issue and I can call each client fine on their own, so long as only one of the generated client jars is on the classpath for the given web service call. However, if I place both web service client jars on the classpath, only one of the web service clients will work (the one where its respective client jar is first on the class path).
The other web service client fails when trying to call it, with the following exception:
java.lang.ClassCastException: com.company.webservice.client1.service.impl.GetAllMetersResponseDocumentImpl cannot be cast to com.company.webservice.client2.service.GetAllMetersResponseDocument
I've obfuscated some of the actual values above.
So, the issue seems to be regarding how Axis2/XMLBeans looks up the appropriate class to match the given XML to parse from.
I can change the namespace mappings so that they match each other and it works fine after that. However, the downside to that is that I have multiple web service client jars containing the same generated code in the same package structure, whereby these classes will only be instantiated from the models from the first client jar it finds on the classpath.
Is there a way of doing this so that I can keep the different namespaces for each web service client jar?
Or am I simply going to be forced to have each namespace mapped to the same package for every client that uses that namespace?
Hopefully the issue makes sense, but if I need to provide anything else that would assist, please let me know and I will expand this question with further details, but hopefully someone with knowledge of Axis2/XMLBeans/web service client generation using Wsdl2Java should be able to answer this without much further info.
UPDATE 1:
I finally gave in and just made all of the namespace mappings point to the same package rather than bespoke per web service client and took the hit of having multiple copies of the same class in various JARs on the classpath. Not as elegant as I would have liked, but at least it works.
If anyone can come up with a better solution that allows me to use bespoke copies in each client instead, please do let me know.
UPDATE 2:
This approach equally does not work as the two web services, despite using the same namespace, produce different versions of the namespace's models which now causes compile time errors dependent on classpath order. So... Back to square one...
I have the feeling you have two versions of the GetAllMetersResponseDocument in each jar. What is happening is that it is loading the interface from the opposite jar file which ends up in Class cast exception. I may be wrong.
This is the reason why it works when you have one of the jars loaded.
There is also this option where you can have Classloader isolation, resulting in two different classloaders for the two jars you can again end up with two objects of the same type that can not be casted to each other.
UDATE
I actualy just checked if axis2 has classloader isolation defined by default and it does. https://axis.apache.org/axis2/java/core/faq.html read Class Loading
Issues
I believe also reading service and module isolation from this article will help you.
https://www.developer.com/open/article.php/10930_3589126_2/Avoiding-Mistakes-Made-Using-Axis2.htm
Related
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.
I have embedded Jetty container inside my main server and I also use Jersey 2.5 for handling REST resources.
everything seems to work well and now I would like to pass my server's context class into each of my REST resources.
I'm having hard time understanding how to do that...
If someone can provide full code example - it could be awesome!
Many thanks
What exactly do you mean when you say you have a Jetty container inside your "main server"? Are you programmatically executing Jetty within the application? Also, when you say "context" are you referring to the ServletContext?
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);
When I publish a web service created from a WSDL, the WSDL which is created after publishing is different than the original one. The difference is that WSDL/XSD created after publishing had additional element(ARG0) which wraps all root elements.
Because of the reason above, I could not share original WSDL/XSD to client developers since original WSDL and the one created after publishing is not same.
I am using Java as a programming language and JAX-WS.
using API javax.xml.ws.Endpoint to publish the web service without needing any Application server.
Endpoint.publish(url,webserviceinstance)
Thanks in advance.
Since the problem is unneccesary wrapping issue, I focused on wrapping annotations. Eventually I have found out that there is a related annotation for this issue. After adding following annotation statement at the beginning of Class ,problem has been solved.
#SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.BARE)
public class WebServiceHandler implements WebService {
//....
}
From now on, I can make succesfull request created from original WSDL to deployed machine.
If you post the wsdl, a better assessment can be made. Given that you are seeing an unexpected wrapper, my guess is that jax-ws is interpreting your original wsdl differently than you intend. The page here (http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/) discusses different wsdl configurations. My suggestion is that you follow the instructions for using the document/literal/wrapped convention as it is more or less in the mainstream for soap-based services.
The resulting published wsdl will still likely be a little different in terms of service name, port name or namespace unless you use the #Webservice annotation attributes to force these to particular values, but they will be consistent such that you can provide the published wsdl to your clients and expect success.
The most common reason for this type of issue is that the class implementing the Web service doesn't have an #WebService annotation with the correct endpointInterface attribute. In fact, it is not sufficient to implement the endpoint interface generated from the WSDL.
I got a situation that I must serve files from different folders then the one of the context my web app is running. As an example, suppose my web app is running in a servlet context on "/opt/tomcat/webapps/ROOT/" and I must serve files existent in "/opt/my_other_folder/". These folders can be changed in runtime by the client, so I can't simply add a new context pointing to these directories. I would like a solution that I wouldn't have to rewrite a web server only for that. Also, the product I work on is generic, so I can't have a solution specific to some servlet container.
Thanks!
If you're only serving files, I would consider fronting your servlet container with something like Apache HTTP Server, where you could simply use its various directives to provide a "virtual directory" pointing to an easily configured location.
Otherwise, you could write and configure a standard Java servlet that would do essentially the same thing - storing the actual path in a Java properties file that would be read by the servlet. But while this isn't a lot of work, it would be significantly more work that the above Apache HTTP Server solution. This would be very similar to several of the answers posted at Servlet for serving static content . Specifically, you could either use or extend upon Apache Tomcat's DefaultServlet. (There are some Tomcat-specific classes used in here, but they could be easily replaced with generic equivalents.) http://balusc.blogspot.com/2009/02/fileservlet-supporting-resume-and.html looks even closer to what you'd be looking for, and it is completely generic - while still having some additional, significant features.
Either of these options would be very generic, and not specific to any particular servlet container.