Stateful services provide the web services developer with a way to
manage "seesion", here is a helpful cook book on how to create a statefull
axis based web service.
1. Create your service
/*
* StatefulService.java
*
* Created on April 1, 2003, 3:25 PM
*/
package com.noi.mailservice.web.services;
import com.noi.mailservice.web.bl.*;
import javax.activation.*;
import java.awt.*;
import javax.imageio.*;
import javax.imageio.stream.*;
import java.io.*;
import java.awt.image.*;
import java.util.*;
import javax.swing.*;
import org.apache.axis.attachments.*;
public class StatefulService
{
private String value;
public void setValue(String value)
{
this.value = value;
}
public String getValue(String empty)
{
return this.value;
}
public String[] getValues(String empty)
{
return new String[] {"hippy", "zippy", "flippy", "mippy", "tippy"};
}
public NameValue getNameValue(NameValue nv)
{
nv.setName("name1");
nv.setValue("VALUE1");
return nv;
}
public DataHandler sendImage( DataHandler dh){
try{
System.err.println("In sendImage");
System.err.println("handler content class:"+dh.getContent().getClass().getName());
dh.writeTo(new FileOutputStream(new File("/home/clay/tmp/myimage.jpg")));
}
catch(Exception e)
{
System.err.println("problem with send image:"+e.getMessage());
e.printStackTrace();
}
return dh;
}
}
2. Create your deployment file for stateful service. First you need a
deployment file for your service that allows for a stateful session handler.
I am using the Session handler that comes with axis. I place this file in
the application context such as [context]/wsdd/statefulservice-deploy.wsdd,
so it is expected to be there when the deployment servlet init is invoked.
<?xml version="1.0" encoding="UTF-8"?>
<deployment
xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
xmlns:ns1="StatefulService">
<service name="StatefulService" provider="java:RPC">
<namespace>http://meis/mailservice/</namespace>
<parameter name="scope" value="session"/>
<requestFlow>
<handler type="java:org.apache.axis.handlers.SimpleSessionHandler"/>
</requestFlow>
<responseFlow>
<handler type="java:org.apache.axis.handlers.SimpleSessionHandler"/>
</responseFlow>
<parameter name="className" value="com.noi.mailservice.web.services.StatefulService"/>
<parameter name="allowedMethods" value="*"/>
<operation name="getNameValue" returnQName="returnqname" returnType="ns1:NameValue" >
<parameter name="nv" type="ns1:NameValue"/>
</operation>
<operation name="sendImage" returnQName="returnqname" returnType="ns1:DataHandler" >
<parameter name="dh" type="ns1:DataHandler"/>
</operation>
<typeMapping deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
languageSpecificType="java:com.noi.mailservice.web.bl.NameValue"
qname="ns1:NameValue"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<typeMapping deserializer="org.apache.axis.encoding.ser.JAFDataHandlerDeserializerFactory"
languageSpecificType="java:javax.activation.DataHandler"
qname="ns1:DataHandler"
serializer="org.apache.axis.encoding.ser.JAFDataHandlerSerializerFactory"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</service>
</deployment>
3. Deploy the stateful service.
I use a servlet as part of the web application that will deploy the service.
When its init method is called it configures the server service engine with
the above wsdd. This will atomatically deploy the service when the web application
file is deployed. package com.avexus.impresaservices.web.servlet;
/*
* ServicesDeploymentServlet.java
*
* Created on April 1, 2003, 5:39 PM
*/
package com.noi.mailservice.web.servlet;
import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.axis.transport.http.*;
import org.apache.axis.*;
import org.apache.axis.deployment.wsdd.*;
import java.net.*;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import com.noi.utility.data.*;
/**
*
* @author clay
* @version
*/
public class ServicesDeploymentServlet extends HttpServlet {
/** Initializes the servlet.
*/
public void init(ServletConfig sconfig) throws ServletException {
super.init(sconfig);
AxisServlet axisServlet = new AxisServlet();
ServletConfig sC = getServletConfig();
ServletContext context = this.getServletContext();
try {
axisServlet.init(sC);
} catch (ServletException e) {
e.printStackTrace();
}
try {
AxisEngine engine = axisServlet.getEngine();
String[] services = {"myservice", "statefulservice", "noimailservice"};
for(int i=0; i<services.length; i++)
{
URL deployURL = context.getResource("/wsdd/"+services[i]+"-deploy.wsdd");
//when parsing namespace MUST be aware
//Document doc = this.parse(deployURL);
XMLDocumentReader reader = new XMLDocumentReader();
reader.parse(deployURL);
Document doc = reader.getDocument();
Element element = doc.getDocumentElement();
WSDDDocument wsddDoc = new WSDDDocument(element);
EngineConfiguration config = (EngineConfiguration)engine.getConfig();
if ( config instanceof WSDDEngineConfiguration) {
WSDDDeployment deployment = ((WSDDEngineConfiguration)config).getDeployment();
wsddDoc.deploy(deployment);
}
engine.refreshGlobalOptions();
engine.saveConfiguration();
debug("Deployed web service:"+services[i]);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
/** Destroys the servlet.
*/
public void destroy() {
//this should undeploy
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.close();
}
/** Handles the HTTP method.
* @param request servlet request
* @param response servlet response
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/** Handles the HTTP POST
method.
* @param request servlet request
* @param response servlet response
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/** Returns a short description of the servlet.
*/
public String getServletInfo() {
return "The Service Deployment Servlet";
}
private void debug(String dval)
{
ServletContext context = getServletContext();
ServletConfig config = getServletConfig();
boolean debugflag = new Boolean(config.getInitParameter("servletdebug")).booleanValue();
if(debugflag)
{
context.log(dval);
}
}
}
4. Create the client configuration file
I place this file in the application context such as [context]/wsdd/statefuleclient-deploy.wsdd,
so it is expected to be there when the client is invoked.
<?xml version="1.0" encoding="UTF-8"?>
<deployment
xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">
<transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender"/>
<transport name="local" pivot="java:org.apache.axis.transport.local.LocalSender"/>
<transport name="java" pivot="java:org.apache.axis.transport.java.JavaSender"/>
<globalConfiguration>
<requestFlow>
<handler type="java:org.apache.axis.handlers.SimpleSessionHandler"/>
</requestFlow>
<responseFlow>
<handler type="java:org.apache.axis.handlers.SimpleSessionHandler"/>
</responseFlow>
</globalConfiguration>
</deployment>
5. Use your client application to access the service.
package com.noi.mailservice.web.clients;
import org.apache.axis.client.*;
import org.apache.axis.*;
import org.apache.axis.encoding.XMLType;
import org.apache.axis.utils.Options;
import org.apache.axis.transport.http.*;
import org.apache.axis.deployment.wsdd.*;
import org.apache.axis.attachments.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import org.apache.axis.encoding.ser.*;
import javax.activation.*;
import java.net.*;
import java.io.*;
import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.ParameterMode;
import com.noi.utility.data.*;
import com.noi.mailservice.web.bl.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
public class StatefulServiceClient
{
private static final boolean stateful = true;
public static void main(String [] args)
{
try {
Options options = new Options(args);
String endpointURL = options.getURL();
String configURL = "http://meis:8080/mailservice/wsdd/statefulclient-deploy.wsdd";
String textToSend;
args = options.getRemainingArgs();
if ((args == null) || (args.length < 1)) {
textToSend = "";
} else {
textToSend = args[0];
}
Service service = new Service();
//configure the stateful client engine
AxisEngine engine = service.getEngine().getClientEngine();
//get the configuration document
URL configresource = new URL(configURL);
XMLDocumentReader reader = new XMLDocumentReader();
reader.parse(configresource);
Document doc = reader.getDocument();
Element element = doc.getDocumentElement();
//use the document to cofigure the client engine
WSDDDocument wsddDoc = new WSDDDocument(element);
EngineConfiguration config = (EngineConfiguration)engine.getConfig();
if ( config instanceof WSDDEngineConfiguration) {
WSDDDeployment deployment = ((WSDDEngineConfiguration)config).getDeployment();
wsddDoc.deploy(deployment);
}
engine.refreshGlobalOptions();
engine.saveConfiguration();
//set the value
/*Call call = (Call) service.createCall();
call.setTargetEndpointAddress( new java.net.URL(endpointURL) );
//public boolean login(String protocol, String username, String password, String hostname)
call.setOperationName( new QName("StatefulService", "setValue") );
call.addParameter( "testval", XMLType.XSD_STRING, ParameterMode.IN);
//call.setReturnType( org.apache.axis.encoding.XMLType.XSD_STRING);
//String ret = (String) call.invoke( new Object[] { textToSend } );
call.setReturnType( org.apache.axis.encoding.XMLType.XSD_ANY);
call.invoke( new Object[] { textToSend } );
System.out.println(textToSend+" has successfully been set.");
//get the value
call = (Call) service.createCall();
call.setTargetEndpointAddress( new java.net.URL(endpointURL) );
call.setOperationName( new QName("StatefulService", "getValue") );
call.addParameter( "empty", XMLType.XSD_STRING, ParameterMode.IN);
call.setReturnType( org.apache.axis.encoding.XMLType.XSD_STRING);
String ret = (String)call.invoke( new Object[] { "empty" } );
System.out.println(ret+" has successfully been retrieved.");
//get values
call = (Call) service.createCall();
call.setTargetEndpointAddress( new java.net.URL(endpointURL) );
call.setOperationName( new QName("StatefulService", "getValues") );
call.addParameter( "empty", XMLType.XSD_STRING, ParameterMode.IN);
call.setReturnType( org.apache.axis.encoding.XMLType.SOAP_ARRAY);
Object[] retlist = (Object[])call.invoke( new Object[] { "empty" } );
for(int i = 0; i<retlist.length; i++)
{
String val = (String)retlist[i];
System.out.println("item #"+i+" value:"+val);
}
//get name value object;
call = (Call) service.createCall();
call.setTargetEndpointAddress( new java.net.URL(endpointURL) );
call.setOperationName( new QName("StatefulService", "getNameValue") );
NameValue nv = new NameValue();
QName qn = new QName("StatefulService", "NameValue");
call.registerTypeMapping(
NameValue.class,
qn,
new org.apache.axis.encoding.ser.BeanSerializerFactory(NameValue.class, qn),
new org.apache.axis.encoding.ser.BeanDeserializerFactory(NameValue.class, qn)
);
call.addParameter("source", qn,
ParameterMode.IN);
call.setReturnType(qn);
nv = (NameValue)call.invoke( new Object[] { (Object)nv } );
System.out.println("name:"+nv.getName()+" value:"+nv.getValue());*/
DataHandler dh = new DataHandler(new FileDataSource("D:\\clay\\images\\self\\tantor23-1.jpg"));
Call call = (Call) service.createCall();
call.setTargetEndpointAddress( new java.net.URL(endpointURL) );
call.setOperationName( new QName("StatefulService", "sendImage") );
QName qnDataHandler = new QName("StatefulService", "DataHandler");
call.registerTypeMapping(
DataHandler.class,
qnDataHandler,
new org.apache.axis.encoding.ser.JAFDataHandlerSerializerFactory(DataHandler.class, qnDataHandler),
new org.apache.axis.encoding.ser.JAFDataHandlerDeserializerFactory(DataHandler.class, qnDataHandler)
);
call.addParameter( "dh", qnDataHandler, ParameterMode.IN);
call.setReturnType( qnDataHandler );
DataHandler ret = (DataHandler)call.invoke( new Object[] { dh } );
} catch (Exception e) {
System.err.println(e.toString());
e.printStackTrace();
}
}
}