<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <title>Invoking a service using
a mail</title>
</head>
<body>
<h1>Invoking
a service using a mail</h1>
<h2>Prologue</h2>
<p>Most of the web services that we
interact with are synchronous and request-response in nature. However,
we see that the synchronous request-response type of interaction is
only a part of the messaging scenarios we encounter in real life.
Asynchronous messaging is very important in constructing loosely
coupled systems. Take for an instance a chain of stores, at the end of
the day all the stores all over can send a mail to the central system
telling it what that days business activity was and in the morning when
the store opens there will be a reply to that mail with new
instructions and updates. It is a lot like the way the old business
worked but with a modern touch. Similarly Axis2 mail transport can be
used to implement SETI@HOME through mail.</p>
<h2>Introduction</h2>
<p>To get things started you will
first need to go through the Mail Transport <a
 href="mail-configuration.html">configuration document</a>. It will give you all
the information you need about how to configure Axis2 to get the mail
transport working.</p>
<p>Broadly speaking there are 3
ways of calling a service through mail.
</p>
<blockquote>1. Using the simple
mail server included in Axis2.<br>
2. Using a generic mail server.<br>
3. Using mailets.<br>
</blockquote>
<p></p>
<p>Option number 1 and 2 are
fairly simple and easy to implement, whereas option 3 is somewhat
harder [unless of course you are one of those guys who see mails going
around in your dreams.]. However the mailet scenario provides a more robust and useful
solution in a production environment.</p>
<p>If you are not a guru in mail
related issues you should probably get started on the simple mail server
that has been provided with Axis2. Once you get the hang of the Axis2
related issues then you can move onto tackle the mail beast. Please do
keep in mind that the mail server we have implemented is ONLY FOR
DEMONSTRATION/TESTING PURPOSES.</p>
<h3>1. Using the simple mail
server included in Axis2</h3>
<p>Before we start I want to
reiterate the fact that the mail server included with Axis2 is ONLY FOR
DEMONSTRATION/TESTING PURPOSES.</p>
<p>The SMTP/POP server that we
have included has the ability to function as a standalone SMTP/POP
server and also has the ability to work as a mailet. All this is done
through a small filter that keeps watch for certain pre-configured
email addresses. These pre-configured email addresses can be changed by
doing a simple edit of the filter class
org.apache.axis2.transport.mail.server.Sorter.</p>
<p>Now that we have the
environment set up, let us start pumping out some code to get the mail
functionality off the ground. First we'll have a look at it from the
mail server side. <br>
</p>
<source><pre>
        // Start the mail server using the default configurations.
        ConfigurationContext configContext = UtilsMailServer.start();

        // Start the default mail listener. It will starting poling for mail
        // using the configuration from the XML file.
        SimpleMailListener ml = new SimpleMailListener();
        ml.init(configContext, configContext.getAxisConfiguration()
                .getTransportIn(new QName(Constants.TRANSPORT_MAIL)));
        ml.start();

        // Setup a service that will echo what we send to the server.
        AxisService axisService = Utils.createSimpleService(serviceName,
                Echo.class.getName(), new QName("echoOMElement"));
        configContext.getAxisConfiguration().addService(axisService);
        Utils.resolvePhases(configContext.getAxisConfiguration(), axisService);
        ServiceContext serviceContext = configContext
                .createServiceContext(new QName("EchoXMLService"));
</pre></source>
<p>This code sets up your Axis2
server working through mail, with a single service. If you need to
have a look under the hood have a look at the MailServer and
UtilsMailServer classes.</p>
<p>Moving onto the client side
have a look at the code listing below. It will call the axisService that
was setup on the previous code listing.</p>
<source><pre>
        ConfigurationContext configContext = UtilsMailServer
                .createClientConfigurationContext();
        AxisService axisService = new AxisService(serviceName);
        AxisOperation axisOperation = new AxisOperation(operationName);
        axisOperation.setMessageReceiver(new MessageReceiver() {
                public void receive(MessageContext messgeCtx) throws AxisFault {
                        envelope = messgeCtx.getEnvelope();
                }
        });
        axisService.addOperation(axisOperation);
        configContext.getAxisConfiguration().addService(axisService);
        Utils.resolvePhases(configContext.getAxisConfiguration(), axisService);
        ServiceContext serviceContext = configContext
                .createServiceContext(serviceName);
        org.apache.axis2.clientapi.Call call = new org.apache.axis2.clientapi.Call(
                serviceContext);
        call.setTo(targetEPR);
        call.setTransportInfo(Constants.TRANSPORT_MAIL,
                Constants.TRANSPORT_MAIL, true);
        // Create a callback to set to the axisService invocation.
        Callback callback = new Callback() {
                public void onComplete(AsyncResult result) {
                        try {
                                result.getResponseEnvelope().serialize(
                                        XMLOutputFactory.newInstance()
                                                .createXMLStreamWriter(System.out));
                        } catch (XMLStreamException e) {
                                reportError(e);
                        } finally {
                                finish = true;
                        }
                }
                public void reportError(Exception e) {
                        log.info(e.getMessage());
                        finish = true;
                }
         };

        // Call the service and start poling for the reply from the server.
        call.invokeNonBlocking(operationName.getLocalPart(), createEnvelope(),
                callback);
        int index = 0;
        while (!finish) {
                Thread.sleep(1000);
                index++;
                if (index &gt; 10) {
                        throw new AxisFault(
                                "Server is being shutdown as the Async response is taking too long.");
                }
        }
        call.close();
</pre></source>
<p>This will call the service that
was setup on the server and will poll the mail server till the response
is received. Well that is all there is to it.</p>
<p></p>
<h3>2. Using a generic mail server</h3>
<p>First you need two email
accounts that works with POP/SMTP. One will act as a server and the
other will act as the client. For the time being we will use
server@somewhere.org and client@somewhere.org as the server and the
client email addresses. Now that we have the email addresses you will
have to set up the client and the server looking at the Mail Transport <a
 href="http://ws.apache.org/axis2/mail-transport.html">introduction
document</a>.</p>
<p>When calling the generic mail
server the client side code will remain the same and there will be some
modification to the server-side code.</p>
<p>
</p>
<source><pre>
        // Create a configuration context. This will also load the details about the mail
        // address to listen to from the configuration file.
        File file = new File(MAIL_TRANSPORT_SERVER_ENABLED_REPO_PATH);
        ConfigurationContextFactory builder = new ConfigurationContextFactory();
        ConfigurationContext configContextbuilder
                .buildConfigurationContext(file.getAbsolutePath());

        // Startup the default mail server and start listening to a 
        // mail address.
        SimpleMailListener ml = new SimpleMailListener();
        ml.init(configContext, configContext.getAxisConfiguration()
                .getTransportIn(new QName(Constants.TRANSPORT_MAIL)));
        ml.start();

        // Setup a simple service.
        AxisService axisService = Utils.createSimpleService(serviceName,
                Echo.class.getName(), operationName);
        configContext.getAxisConfiguration().addService(axisService);
        Utils.resolvePhases(configContext.getAxisConfiguration(), axisService);
        ServiceContext serviceContext = configContext.createServiceContext(serviceName);
</pre></source>
<p>We have to create a separate ConfigurationContext and then use that. We are done; wasn't that simple?</p>
<h3>3. Calling Axis through a
James mailet</h3>
<p>This process will be a bit more
challenging than the other two methods but will provide a really
elegant way to use the mail transport. Before we get started you will
have to go though the James documents <a
 href="http://james.apache.org/custom_matcher_2_1.html">Writing
a Custom Matcher</a> and <a
 href="http://james.apache.org/custom_mailet_2_1.html">Writing
a Custom Mailet</a>.</p>
<p>Now that we know the James part of it lets dive into to the Axis2 part of the code. Once you have set up the James side of business we just need to use the same functionality that is used in the above code. Have a look at the code listing below for more details</p>
<source><pre>
    public void processMail(ConfigurationContext confContext, MimeMessage mimeMessage) {
        // create an Axis server
        AxisEngine engine = new AxisEngine(confContext);
        MessageContext msgContext = null;
        // create and initialize a message context
        try {
            // Create a message context with mail as in and out transports.
            msgContext =
                    new MessageContext(confContext,
                            confContext.getAxisConfiguration().getTransportIn(new QName(Constants.TRANSPORT_MAIL)),
                            confContext.getAxisConfiguration().getTransportOut(new QName(Constants.TRANSPORT_MAIL)));
            msgContext.setServerSide(true);

            msgContext.setProperty(MailConstants.CONTENT_TYPE, mimeMessage.getContentType());
            msgContext.setWSAAction(getMailHeader(MailConstants.HEADER_SOAP_ACTION, mimeMessage));

            // The service path is in the subject of the mail.
            String serviceURL = mimeMessage.getSubject();
            if (serviceURL == null) {
                serviceURL = "";
            }

            String replyTo = ((InternetAddress) mimeMessage.getReplyTo()[0]).getAddress();
            if (replyTo != null) {
                msgContext.setReplyTo(new EndpointReference(replyTo));
            }

            String recipients = ((InternetAddress) mimeMessage.getAllRecipients()[0]).getAddress();

            if (recipients != null) {
                msgContext.setTo(new EndpointReference(recipients + "/" + serviceURL));
            }

            // add the SOAPEnvelope
            String message = mimeMessage.getContent().toString();
            ByteArrayInputStream bais = new ByteArrayInputStream(message.getBytes());
            XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(bais);

            // This is just in place to work with SOAP 1.1 and 1.2.
            String soapNamespaceURI = "";
            if (mimeMessage.getContentType().indexOf(SOAP12Constants.SOAP_12_CONTENT_TYPE) > -1) {
                soapNamespaceURI = SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI;
            } else if (mimeMessage.getContentType().indexOf(SOAP11Constants.SOAP_11_CONTENT_TYPE) > -1) {
                soapNamespaceURI = SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI;

            }
            StAXBuilder builder = new StAXSOAPModelBuilder(reader, soapNamespaceURI);

            SOAPEnvelope envelope = (SOAPEnvelope) builder.getDocumentElement();
            msgContext.setEnvelope(envelope);
            if (envelope.getBody().hasFault()) {
                engine.receiveFault(msgContext);
            } else {
                engine.receive(msgContext);
            }
        } catch (Exception e) {
            try {
                if (msgContext != null) {
                    MessageContext faultContext = engine.createFaultMessageContext(msgContext, e);
                    engine.sendFault(faultContext);
                }
            } catch (Exception e1) {
                log.error(e);
            }
        }
    }
</pre>
</source>
<p>If you don't happen to have a ConfigurationContext lying around to call this method you can use the following bit of code to get one. Once you create one you can store that on the mailet and keep using it.
</p>
<source><pre>
        File file = new File(MAIL_TRANSPORT_SERVER_ENABLED_REPO_PATH);
        ConfigurationContextFactory builder = new ConfigurationContextFactory();
        ConfigurationContext configContextbuilder
                .buildConfigurationContext(file.getAbsolutePath());
</pre>
</source>
<p>Well that seems to be all from the wonderful world of mail for now. :)</p>
</body>
</html>
