package samples.userguide.example1; import org.apache.axis.client.Call; import org.apache.axis.client.Service; import javax.xml.namespace.QName; public class TestClient { public static void main(String [] args) { try { String endpoint = "http://nagoya.apache.org:5049/axis/services/echo"; Service service = new Service(); Call call = (Call) service.createCall(); call.setTargetEndpointAddress( new java.net.URL(endpoint) ); call.setOperationName(new QName("http://soapinterop.org/", "echoString") ); // Call to addParameter/setReturnType as described in user-guide.html call.addParameter("testParam", org.apache.axis.Constants.XSD_STRING, javax.xml.rpc.ParameterMode.IN); call.setReturnType(org.apache.axis.Constants.XSD_STRING); String ret = (String) call.invoke( new Object[] { "Hello!" } ); System.out.println("Sent 'Hello!', got '" + ret + "'"); } catch (Exception e) { System.err.println(e.toString()); } } }
<?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <env:Body> <ns1:echoString xmlns:ns1="http://soapinterop.org/"> <testParam xsi:type="xsd:string">Hello!</testParam> </ns1:echoString> </env:Body> </env:Envelope>
<?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <env:Body> <ns1:echoStringResponse xmlns:ns1="http://soapinterop.org/"> <result xsi:type="xsd:string">Hello!</result> </ns1:echoStringResponse> </env:Body> </env:Envelope>
public class Calculator { public int add(int i1, int i2) { return i1 + i2; } public int subtract(int i1, int i2) { return i1 - i2; } }
cp Calculator.java <your-webapp-root>/axis/Calculator.jws
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <service name="MyService" provider="java:RPC"> <parameter name="className" value="samples.userguide.example3.MyService"/> <parameter name="allowedMethods" value="*"/> </service> </deployment>
MyService
will result in a call to the class
samples.userguide.example3.MyService
and any of the
public methods in that class can be invoked
(allowsMethods=*
).java org.apache.axis.client.AdminClient deploy.wsdd
<service name="MyService"...> <parameter name="scope" value="value"/> ... </service>to be:
Since the web service is defined by a class, we need to have at least one instance of that class in order to invoke its methods. This raises the question of how many instances of the class should we have around, one? one for each call? a couple? In Java RMI there was only one instance of each remote service which is the equivalent of the Application-level scoping provided by SOAP. SOAP, however, allows one to have a new instance created each time a client invokes one of the methods (Request) or to have one new instance created each time a client logs-in (Session), presumably the client is using some form of HTTP authentication.
LogTestService
is called. You would use <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <!-- define the logging handler configuration --> <handler name="track" type="java:samples.userguide.example4.LogHandler"> <parameter name="filename" value="MyService.log"/> </handler> <!-- define the service, using the log handler we just defined --> <service name="LogTestService" provider="java:RPC"> <requestFlow> <handler type="track"/> </requestFlow> <parameter name="className" value="samples.userguide.example4.Service"/> <parameter name="allowedMethods" value="*"/> </service> </deployment>
LogHandler
is defined aspackage samples.userguide.example4; import org.apache.axis.AxisFault; import org.apache.axis.Handler; import org.apache.axis.MessageContext; import org.apache.axis.handlers.BasicHandler; import java.io.FileOutputStream; import java.io.PrintWriter; import java.util.Date; public class LogHandler extends BasicHandler { public void invoke(MessageContext msgContext) throws AxisFault { /** Log an access each time we get invoked. */ try { Handler serviceHandler = msgContext.getService(); String filename = (String)getOption("filename"); if ((filename == null) || (filename.equals(""))) throw new AxisFault("Server.NoLogFile", "No log file configured for the LogHandler!", null, null); FileOutputStream fos = new FileOutputStream(filename, true); PrintWriter writer = new PrintWriter(fos); Integer numAccesses = (Integer)serviceHandler.getOption("accesses"); if (numAccesses == null) numAccesses = new Integer(0); numAccesses = new Integer(numAccesses.intValue() + 1); Date date = new Date(); String result = date + ": service " + msgContext.getTargetService() + " accessed " + numAccesses + " time(s)."; serviceHandler.setOption("accesses", numAccesses); writer.println(result); writer.close(); } catch (Exception e) { throw AxisFault.makeFault(e); } } }
<soap:Envelope xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <soap:Body> <myNS:PurchaseOrder xmlns:myNS="http://commerce.com/PO"> <item>SK001</item> <quantity>1</quantity> <description>Sushi Knife</description> </myNS:PurchaseOrder> </soap:Body> </soap:Envelope>which uses the schema:
<schema targetNamespace="http://commerce.com/PO"> <complexType name="POType"> <sequence> <element name="item" type="xsd:string"/> <element name="quantity" type="xsd:int"/> <element name="description" type="xsd:string"/> </sequence> </complexType> <element name="PurchaseOrder" type="POType"/> </deployment>
public void method(PurchaseOrder po)The entire PO is fed to your method using a Bean.
xsd:base64Binary | byte[] |
xsd:boolean | boolean |
xsd:byte | byte |
xsd:dateTime | java.util.Calendar |
xsd:decimal | java.math.BigDecimal |
xsd:double | double |
xsd:float | float |
xsd:hexBinary | byte[] |
xsd:int | int |
xsd:integer | java.math.BigInteger |
xsd:long | long |
xsd:QName | javax.xml.namespace.QName |
xsd:short | short |
xsd:string | java.lang.String |
java.rmi.RemoteException
it gets mapped to a SOAP Fault.
faultcode
contains the
class name of the exception.wsdl:fault
in the WSDL of the method. Collection
(Hashtable, Set), but only another Axis will understand (.NET
won't).java org.apache.axis.wsdl.WSDL2Java (WSDL-file-URL)
<xsd:complexType name="phone"> <xsd:all> <xsd:element name="areaCode" type="xsd:int"/> <xsd:element name="exchange" type="xsd:string"/> <xsd:element name="number" type="xsd:string"/> </xsd:all> </xsd:complexType>generates this bean
public class Phone implements java.io.Serializable { public Phone() {...} public int getAreaCode() {...} public void setAreaCode(int areaCode) {...} public java.lang.String getExchange() {...} public void setExchange(java.lang.String exchange) {...} public java.lang.String getNumber() {...} public void setNumber(java.lang.String number) {...} public boolean equals(Object obj) {...} public int hashCode() {...} }
<message name="empty"> <message name="AddEntryRequest"> <part name="name" type="xsd:string"/> <part name="address" type="typens:address"/> </message> <portType name="AddressBook"> <operation name="addEntry"> <input message="tns:AddEntryRequest"/> <output message="tns:empty"/> </operation> </portType>maps to the Java code
public interface AddressBook extends java.rmi.Remote { public void addEntry(String name, Address address) throws java.rmi.RemoteException; }
<binding name="AddressBookSOAPBinding" type="tns:AddressBook"> ... </binding>gets turned into
public class AddressBookSOAPBindingStub extends org.apache.axis.client.Stub implements AddressBook { public AddressBookSOAPBindingStub() throws org.apache.axis.AxisFault {...} public AddressBookSOAPBindingStub(URL endpointURL, javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {...} public AddressBookSOAPBindingStub(javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {...} public void addEntry(String name, Address address) throws RemoteException {...} }by WSDL2Java.
service
clause in the WSDL. For example, this WSDL <service name="AddressBookService"> <port name="AddressBook" binding="tns:AddressBookSOAPBinding"> <soap:address location="http://localhost:8080/axis/services/AddressBook"/> </port> </service>gets turned into this service interface (by WSDL2Java)
public interface AddressBookService extends javax.xml.rpc.Service { public String getAddressBookAddress(); public AddressBook getAddressBook() throws javax.xml.rpc.ServiceException; public AddressBook getAddressBook(URL portAddress) throws javax.xml.rpc.ServiceException; }and this locator class
public class AddressBookServiceLocator extends org.apache.axis.client.Service implements AddressBookService { ... }
public class Tester { public static void main(String [] args) throws Exception { // Make a service AddressBookService service = new AddressBookServiceLocator(); // Now use the service to get a stub which implements the SDI. AddressBook port = service.getAddressBook(); // Make the actual call Address address = new Address(...); port.addEntry("Russell Butek", address); } }
java org.apache.axis.wsdl.Java2WSDL -o wp.wsdl -l"http://localhost:8080/axis/services/WidgetPrice" -n "urn:Example6" -p"samples.userguide.example6" "urn:Example6" samples.userguide.example6.WidgetPricewhere
java org.apache.axis.wsdl.WSDL2Java -o . -d Session -s -S true -Nurn:Example6 samples.userguide.example6 wp.wsdl
This talk available at http://jmvidal.cse.sc.edu/talks/axis/
Copyright © 2009 José M. Vidal
.
All rights reserved.
25 March 2004, 04:08PM