|
Creating consumers with Axis is really not that much different than the examples in Chapter 7. There are some different include files and a tool to create proxy code much like the WSDL tool found in .NET, but the concept of creating consumers is the same.
In this chapter, we focus on creating a simple command line consumer and the same program that creates a proxy. Using Axis within JSP and other consumers is covered in Chapter 9. which is a case study of using .NET and Java Web Services together.
The following code is a simple command line application that invokes the Axis Web Service example shown earlier in the chapter. The example starts off by defining all the different Java libraries needed for this example with the import statements. Then there is a class definition followed by the definition of the main method.
Then the example begins to call the Web Service by reading the options passed in from the command line, creating a call to the URL where the Web Service resides, defining the class and method to call from the server, defining the result, and finally printing the result.
import org.apache.axis.AxisFault; import org.apache.axis.client.Call; import org.apache.axis.client.Service; import org.apache.axis.encoding.XMLType; import org.apache.axis.utils.Options; import javax.xml.rpc.ParameterMode; import javax.xml.namespace.QName; import java.net.URL; public class getSimpleStock { public static void main (String[] args) throws Exception { String symbol = null; //get command line args Options myOpts = new Options( args ); args = myOpts.getRemainingArgs(); //begin a call to a Web Service Service myService = new Service(); Call myCall = (Call) myService.createCall(); //location of axis server myOpts.setDefaultURL( "http://localhost:8000/axis/servlet/AxisServlet" ); myCall.setTargetEndpointAddress ( new URL(myOpts.getURL()) ); myCall.setUseSOAPAction( true ); //the method to call myCall.setSOAPActionURI( "getTestQuote" ); //how to encode the request/response myCall.setEncodingStyle ("http://schemas.xmlsoap.org/soap/encoding/" ); //define the class and method used myCall.setOperationName( new QName("SimpleStockExample", "getTestQuote") ); //add symbol to the request myCall.addParameter ( "symbol", XMLType.XSD_STRING, ParameterMode.IN ); myCall.setReturnType( XMLType.XSD_FLOAT ); //make the actual object call Object myResult = myCall.invoke( new Object[] { symbol = args[0] } ); //print the result System.out.println("This is the returned value: " + ((Float)myResult).floatValue()); } }
If you compare this to the examples in Chapter 6, this is a lot of code to write to call a Web Service when compared to .NET—especially since this code needs to be used each time one particular method gets called.
To make calling a Web Service easier with Apache tools, Axis comes with WSDL2Java application that generates Java proxy code to make calling the Web Service easier and quicker. The next section covers the creation of this proxy.
With Axis, WSDL is generated automatically and can be seen by simply putting “wsdl” in the query string. Consider the following URL: http://localhost:8080/axis/ services/SimpleStockExample?wsdl
This will display the WSDL for the SimpleStockExample Web Service shown earlier in this chapter. Figure 8.11 shows how the WSDL appears in Internet Explorer.
Figure 8.11: The WSDL output for the SimpleStockExample Web Service.
To create a Java proxy for a client to use, execute WSDL2Java and send the URL of the SimpleStockQuote’s WSDL output. The command should look something like the following.
java org.apache.axis.wsdl.WSDL2Java http://localhost:8080/axis/services/SimpleStockExample?wsdl
This creates a directory called localhost. Within that directory you will find the following four files.
SimpleStockExample.javaSimpleStockExampleSoapBindingStub.java SimpleStockExampleService.java SimpleStockExampleServiceLocator.java.
SimpleStockExample and SimpleStockExampleService are both interfaces that define the functionality that the other two Java files must implement. SimpleStockExampleServiceLocator implements SimpleStockExampleService and defines the location of the Web Service and methods.
SimpleStockExampleSoapBindingStub.java implements SimpleStockExampleServiceLocator.java and handles the code related to the call.
The following is the code for SimpleStockExample.java.
/** * SimpleStockExample.java * * This file was auto-generated from WSDL * by the Apache Axis WSDL2Java emitter. */ package localhost; public interface SimpleStockExample extends java.rmi.Remote { public float getTestQuote(java.lang.String in0) throws java.rmi.RemoteException; }
Notice how the code simply defines an interface, and notice how SimpleStockExampleServiceLocator.java utilizes this interface.
/** * SimpleStockExampleServiceLocator.java * * This file was auto-generated from WSDL * by the Apache Axis WSDL2Java emitter. */ package localhost; public class SimpleStockExampleServiceLocator extends org.apache.axis.client.Service implements localhost.SimpleStockExampleService { // Use to get a proxy class for SimpleStockExample private final java.lang.String SimpleStockExample_address = "http://localhost:8080/axis/services/SimpleStockExample"; public String getSimpleStockExampleAddress() { return SimpleStockExample_address; } public localhost.SimpleStockExample getSimpleStockExample() throws javax.xml.rpc.ServiceException { java.net.URL endpoint; try { endpoint = new java.net.URL (SimpleStockExample_address); } catch (java.net.MalformedURLException e) { return null; } return getSimpleStockExample(endpoint); } public localhost.SimpleStockExample getSimpleStockExample(java.net.URL portAddress) throws javax.xml.rpc.ServiceException { try { return new localhost.SimpleStockExampleSoapBindingStub (portAddress, this); } catch (org.apache.axis.AxisFault e) { return null; // ??? } } /** * For the given interface, get the stub * implementation. * If this service has no port for the given interface, * then ServiceException is thrown. */ public java.rmi.Remote getPort(Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException { try { if (localhost.SimpleStockExample.class.isAssignableFrom (serviceEndpointInterface)) { return new localhost.SimpleStockExampleSoapBindingStub (new java.net.URL(SimpleStockExample_address), this); } } catch (Throwable t) { throw new javax.xml.rpc.ServiceException(t); } throw new javax.xml.rpc.ServiceException("There is no stub implementation for the interface: " + (serviceEndpointInterface == null ? "null" : serviceEndpointInterface.getName())); } }
The previous Java code is mainly centered on finding the name of the service. The following code snippet is SimpleStockExampleService.java. This defines the interface for the actually getting values from the Web Service.
/** * SimpleStockExampleService.java * * This file was auto-generated from WSDL * by the Apache Axis WSDL2Java emitter. */ package localhost; public interface SimpleStockExampleService extends javax.xml.rpc.Service { public String getSimpleStockExampleAddress(); public localhost.SimpleStockExample getSimpleStockExample() throws javax.xml.rpc.ServiceException; public localhost.SimpleStockExample getSimpleStockExample(java.net.URL portAddress) throws javax.xml.rpc.ServiceException; }
Finally, SimpleStockExampleSoapBindingStub.java contains the code defined in the previous interface. This code focuses on creating the call and getting values back from the Web Service.
/** * SimpleStockExampleSoapBindingStub.java * * This file was auto-generated from WSDL * by the Apache Axis WSDL2Java emitter. */ package localhost; public class SimpleStockExampleSoapBindingStub extends org.apache.axis.client.Stub implements localhost.SimpleStockExample { private java.util.Vector cachedSerClasses = new java.util.Vector(); private java.util.Vector cachedSerQNames = new java.util.Vector(); private java.util.Vector cachedSerFactories = new java.util.Vector(); private java.util.Vector cachedDeserFactories = new java.util.Vector(); public SimpleStockExampleSoapBindingStub() throws org.apache.axis.AxisFault { this(null); } public SimpleStockExampleSoapBindingStub (java.net.URL endpointURL, javax.xml.rpc.Service service) throws org.apache.axis.AxisFault { this(service); super.cachedEndpoint = endpointURL; } public SimpleStockExampleSoapBindingStub (javax.xml.rpc.Service service) throws org.apache.axis.AxisFault { try { if (service == null) { super.service = new org.apache.axis.client.Service(); } else { super.service = service; } } catch(java.lang.Exception t) { throw org.apache.axis.AxisFault.makeFault(t); } } private org.apache.axis.client.Call createCall() throws java.rmi.RemoteException { try { org.apache.axis.client.Call call = (org.apache.axis.client.Call) super.service.createCall(); if (super.maintainSessionSet) { call.setMaintainSession(super.maintainSession); } if (super.cachedUsername != null) { call.setUsername(super.cachedUsername); } if (super.cachedPassword != null) { call.setPassword(super.cachedPassword); } if (super.cachedEndpoint != null) { call.setTargetEndpointAddress (super.cachedEndpoint); } if (super.cachedTimeout != null) { call.setTimeout(super.cachedTimeout); } java.util.Enumeration keys = super.cachedProperties.keys(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); if(call.isPropertySupported(key)) call.setProperty(key, super.cachedProperties.get(key)); else call.setScopedProperty(key, super.cachedProperties.get(key)); } // All the type mapping information is //registered // when the first call is made. // The type mapping information is actually //registered in // the TypeMappingRegistry of the service, //which // is the reason why registration is only //needed for the first call. synchronized (this) { if (firstCall()) { // must set encoding style before //registering serializers call.setEncodingStyle (org.apache.axis.Constants.URI_SOAP11_ENC); for (int i = 0; i < cachedSerFactories.size(); ++i) { Class cls = (Class) cachedSerClasses.get(i); javax.xml.namespace.QName qName = (javax.xml.namespace.QName) cachedSerQNames.get(i); Class sf = (Class) cachedSerFactories.get(i); Class df = (Class) cachedDeserFactories.get(i); call.registerTypeMapping (cls, qName, sf, df, false); } } } return call; } catch (Throwable t) { throw new org.apache.axis.AxisFault ("Failure trying to get the Call object", t); } } more and more lines of code ... }
The last example code was cut short for a very good reason. You don’t really need to know what the code is doing, much like you don’t need to worry about the proxy code in .NET.
Once the Java files are created, compile them with the following command within the localhost directory:
javac *.java
This should make all the corresponding class files and compile without error. Now the classes are available to any client you wish to create. The following example utilizes these classes.
The import statement brings in all the classes that WSDL2Java created and you compiled. Then the class getSimpleStockWSDL is created with a main method. The result variable is defined so it handles a value returned by the method. Next, the code creates the object myService, which contains information about where the object and method you need to call reside. The next step creates the object mySOAP, which is the actual object that represents the SimpleStockQuote class. Notice that the next step is the mySOAP object calling the getTestQuote method. Then the value of result is output. This piece of code is the simplest call to a Java Web Service shown in this book so far.
import localhost.*; public class getSimpleStockWSDL { public static void main(String [] args) throws Exception { //The type the service returns. double result; SimpleStockExampleServiceLocator myService = new SimpleStockExampleServiceLocator(); localhost.SimpleStockExample mySOAP = myService.getSimpleStockExample(); result = mySOAP.getTestQuote("C"); System.out.println ("This is the value: " + result); } }
Note | Doesn’t this seem a little like using the WSDL tool found in .NET? It should. Microsoft and IBM collaborated on the WSDL standard, and Apache Axis has its roots as a project that began at IBM. So it’s no wonder that the two processes are similar. |
|