I have one final hurdle to get over with the web services application I am working with; I need to be able to override the default settings used to set the schema location and soap address location in the generated WSDL file.
When I deploy the application (GlassFish v2.1 on Red Hat linux) it uses the local server name in the URLs but it needs to use the public domain name instead. I was able to save the WSDL file locally, change the URLs, make it public, generate a test application externally from the file, and lastly was able to successfully run a test.
I have now journeyed into the realm of JAX-WS custom bindings but I'm hoping that I either overlooked a simpler solution or the bindings are not as complicated as they look at first glance. The web service implementation is through a stateless EJB (e.g. MyWS.java below). The generated WSDL file would look like MyWSDL.wsdl (see below).
In the xsd:import tag I need to change schemaLocation to
http://test.mycompany.com/MyWSService/MyWS?xsd=1
instead of
http://local-server-name/MyWSService/MyWS?xsd=1
and in the soap:address tag I need to change location to be
http://test.mycompany.com/MyWSService/MyWS
instead of
http://local-server-name/MyWSService/MyWS.
MyWS.java
#WebService(name="MyWS",
portName="MyWSPort",
serviceName="MyWSService",
targetNamespace="http://test.mycompany.com/")
#Stateless()
public class MyWS {
#WebMethod(operationName="testLogin")
public String testLogin(#WebParam(name="username") String username,
#WebParam(name="password") String password) {
String retVal = "Test Failed.";
//do some stuff
return retVal;
}
...
}
MyWSDL.wsdl
<definitions targetNamespace="http://test.mycompany.com/" name="MyWSService">
<types>
<xsd:schema>
<xsd:import namespace="http://test.mycompany.com/" schemaLocation="http://local-server-name/MyWSService/MyWS?xsd=1"/>
</xsd:schema>
</types>
<service name="MyWSService">
<port name="MyWSPort" binding="tns:MyWSPortBinding">
<soap:address location="http://local-server-name/MyWSService/MyWS"/>
</port>
</service>
</definitions>
I was able to resolve the issue by changing the configuration of the GlassFish HTTP Service. I set the server's alias name to test.mycompany.com:80 for the HTTP listener being used for the web services application. Typically we have this kind of configuration in our web servers so initially I didn't even consider the application server configuration.
How are you generating the WSDL? Are you generating it by hand? Are you generating it using wsgen with the -wsdl option?
If you're deploying with JAX-WS you shouldn't actually have to do either of those things. Instead you should be able to go to...
<SERVER_URL>/<CONTEXT_LOCATION>/<SERVLET_URL>?wsdl
...and the JAX-WS servlet will automatically generate a wsdl on the fly with the correct location.
Related
I'm consuming a webservice where the WSDL file contains imports to other wsdl and xsd schemas, e.g:
<import namespace="http://my.api.com/" location="http://other.server.com:8888/context/services/MyService?wsdl=1"/>
which in turn can import other files
<xsd:import namespace="http://my.api.com/" schemaLocation="http://other.server.com:8888/context/services/MyService?xsd=1"/>
The client is generated by cxf with a maven plugin. The main WSDL file is added as a classpath resource. However, at runtime it appears that the client actually needs access to other.server.com:8888 to resolve the WSDL completely. So the question is, does a tool exist for importing and resolving all URLs in a WSDL so that it is not dependent absolute server URLs in other imports in the WSDL, and suitable for including in a client project?
We do not control the WSDL, so we can't change it in the source.
Edit: Looking for a tool that works on Linux
Check the ServiceModel Metadata Utility Tool (Svcutil.exe) from Windows SDK.
svcutil /t:metadata http://service/metadataEndpoint
This tool locates or discovers, one or more related documents that describe a particular XML Web service using the Web Services Description Language (WSDL).
I don't know if I understood your question correctly. I'm having my battles with Jax-ws/SOAP too. :)
If you need to generate the java classes needed to call the webservice you can use Apache CXF. Inside it you have a wsdl2java. You can use it on linux.
Another option in Java SDK, on the bin folder there's the wsimport that you can use it too.
Edit: You can change the final URL at runtime using the Service class created by Apache CXF.
new SomeRandomJaxWSService(new URL(wsdl),new QName(namespace, serviceName))
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.
I've deployed a webservice to a Jboss instance running on Amazon EC2. The webservice works fine locally, but when I deploy on EC2, and go to the /jbossws/services page the Endpoint Address for the webservice is the private DNS of the ec2 instance (domU-X-X-X-X etc...), not the public dns (which I would like it to be).
I've tried loading the wsdl by changing the private hostname to the public IP; that works, but when I try to call any of the operations I get a HostNotFoundException, I'm guessing due to the fact that the generated wsdl has the stanza:
<service name='XXXService'>
<port binding='tns:XXXBinding' name='XXXPort'>
<soap:address location='http://domU-XX-XX-XX-XX-XX-XX.compute-1.internal:8080/xx/xx/xx'/>
</port>
</service>
where http://domU-XX-XX-XX-XX-XX-XX.compute-1.internal is the internal dns of the ec2 instance.
The wsdl is auto generated - Is there a JAXB annotation I can use so that I can force the generated wsdl to use the public dns of the EC2 instance?
Many thanks -
In JBoss 5.1.0 GA look at
jbossws.deployer/META-INF/jboss-beans.xml
and comment the following line
${jboss.bind.address}
it is 100% worked
or see the following
http://community.jboss.org/wiki/JBossWS-UserGuide
I have written a Web Service in Java using axis2 and the POJO deployment (to a Tomcat server). My service opens a connection to a MySQL database. To do that, I need the connection string. Where do I put the connection string, so I don't have to hard code it into the code? And how do I access it from code? I would like to set this parameter somewhere on the service level, not globally for the whole server. Is this possible?
You could use tomcat to configure the DB connectivity for you and then just look up the javax.sql.DataSource using JNDI.
Have look at these for tomcat:
JNDI resources
JNDI datasource example
Using JNDI would also mean that you automatically become a little more compatible in case you ever need to move to a different web container/app server.
If you want to use a config file, you can place one at the following location:
axis2/WEB-INF/services/classes/config-file.xml
You can access this file in code using the AxisService classloader, which is available during the startUp(ConfigurationContext configctx, AxisService service) method. startUp() is fired when your service is started (either post-deployment or after a container restart).
import org.apache.axis2.engine.ServiceLifeCycle;
public class LifeCycleImpl implements ServiceLifeCycle {
public void startUp(ConfigurationContext configctx, AxisService service) {
InputStream in = service.getClassLoader().getResourceAsStream("config-file.xml");
//Extract your database config from the input stream
//Create database connection
//Store the connection as a service parameter using service.AddParameter
}
During the init(ServiceContext serviceContext) method of your service implementation class, you can get access the database connection created during ServiceLifeCycle.startUp() via the ServiceContext.getAxisService().getParamterValue() method.
Note: You must specify the ServiceLifeCycle implementation class in the your service's services.xml file, as the class attibute of the service tag:
<!-- The class attribute defines the hook into the Service lifecycle methods
startUp and shutDown -->
<service name="YourService" class="com.macima.webservice.LifeCycleImpl">
<!--Specify the web service's implementation class -->
<parameter name="ServiceClass">com.macima.webservice.ServiceImpl</parameter>
<!--Declare methods exposed by the web service-->
<operation name="getSomething">
<messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</operation>
</parameter>
</service>
With this approach, your config file is held outside of the aar file. The benefit is you can promote the same aar file through different test environments, picking up the relevant settings for each environment in the environment specific config file. Additionally you can edit the config file without having to open up the aar file.
Does anyone know of a really simple way of publishing Java methods as web services? I don't really want the overhead of using Tomcat or Jetty or any of the other container frameworks.
Scenario: I've got a set of Java methods in a service type application that I want to access from other machines on the local LAN.
Well, Tomcat or Jetty may be overkill for publishing just some methods as a web service. But on the other hand its not too complicated and they do the job, so why not?
I had a similar problem not too long ago and used a Tomcat together with Axis2. Just download Tomcat, unpack it, deploy the Axis2 WAR. To publish a webservice, there are several aproaches, the one I took is probably one of the easiest:
Just build your application as usual and annotate the web service class and methods with the appropriate annotaions from javax.jws.*. Package everything into a jar. Create a service.xml in the META-INF directory of your jar file and put this into it:
<service name="name of the service" scope="<one of request, session or application>">
<description>
optional description of your service
</description>
<messageReceivers>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" />
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
<parameter name="ServiceClass" locked="false">put here the fully qualified name of your service class (e.g. x.y.z.FooService)</parameter>
</service>
Rename the .jar to .aar and put it into the /webapps/axis2/WEB-INF/services/ directory. Start tomcat and the service will be deployed. You can check if it is running by visiting the axis2 page (http://localhost:8080/axis2/). There you will see which services are deployed and which methods are exported. Also you can get the WSDL url there to connect to your service.
Read http://ws.apache.org/axis2/1_4_1/contents.html for more about using Axis2. The approach I described here is not found exactly like this in the docs, but it works very well.
Update: If you just want to provide web services and really don't need any of the other features of Tomcat (e.g. serving of plain old web pages, jsps or other stuff), you can also use the Axis2 standalone server. But except for the setup part it doesn't change anything I described.
I've written a slightly more detailed version of this, which can be found at: http://www.slashslash.de/lang/en/2008/10/java-webservices-mit-apache-tomcat-und-axis2/ (don't let the German in URL irritate you, it's written in English)
Web services depend on HTTP. You might not want tomcat or Jetty. In that case, you have to implement HTTP yourself.
Erhm. Why not just use RMI?
Jetty's pretty lightweight. Otherwise, I think XML-RPC is your only sensible option.
The simplier solution than the one that Simon has discribed, ist to use the tools that alrady do that. If you use eclipse you could use http://ws.apache.org/axis2/tools/1_2/eclipse/servicearchiver-plugin.html
to generate the aar file.