11g et EMail : Consommer (avec modération) via UMS [2/2]

Dans le précédent article, nous avons présenté une solution permettant la mise en place de consommation de mails dans la SOA 11g.
Cette solution, basée sur l’utilisation d’UMS, avait commencé à être implémenté (configuration EMail) mais restait incomplète. Dans cet article, nous allons compléter cette mise en place en nous attardant sur la réalisation du client UMS.

Rappels

Pour rappel, voici le schéma de la solution qui est ici implémentée :

La partie concernant la configuration du driver e-mail (et des certificats associés) a été abordée dans le précédent article. Ici nous allons nous pencher sur la réalisation du war « MailListener ».

Client UMS : consommateur EMail

Dépendances

Concernant les dépendances du projet, il vous faudra :

  • Bibliothèque Oracle UMS Client (fournie dans JDeveloper et contenant sdpclient.jar et jrf-client.jar)

Et c’est tout pour un fonctionnement simple !
Voici quelques extraits de sources du client java permettant la réalisation des principales étapes. Ces exemples sont partiels, mais montrent les principales opérations. Dans le cadre de l’exemple mis en place, il s’agissait d’une web-app spring.

Configuration Spring

<!-- Mail listener bean -->
  <bean name="mailListener" class="ums.spring.sandbox.MailListener">
    …
  </bean>
  <!-- Listener subscriber bean -->
  <bean name="registerListener" class="ums.spring.sandbox.ListenerSubscriber"
        init-method="initialize" destroy-method="destroy">
    <property name="listener" ref="mailListener" />
    <property name="applicationName" value="UMS-Spring-AppName" />
    <property name="applicationInstanceNameBase" value="UMS-Spring-AppInstanceName-" />
    <property name="systemPropertyForDistinctInstance" value="weblogic.Name" />
    <property name="subscribingEmail" value="testmail.santony@gmail.com" />
    <property name="filterValue" value="(?!ok).*" /><!--only mail with subject  starting with "ok" -->
  </bean>
…

Inscription à UMS – ListenerSubscriber :

Cette classe est en charge d’inscrire le client auprès d’UMS. Pour cela, il doit (méthode initialize du bean) :

  • Fournir des paramètres de configuration (méthode getConfigurationParameters) : nom d’inscription, instance d’inscription
  • Fournir le listener
  • Fournir le point d’accès auquel s’inscrire (méthode getAccessPoint)
  • Associer des filtres si nécessaire (méthode createMessageFilter)
  • S’enregistrer

Elle montre également la possibilité de se désinscrire (méthode destroy du bean).

…
import oracle.sdp.messaging.AccessPoint;
import oracle.sdp.messaging.ApplicationInfo;
import oracle.sdp.messaging.DeliveryType;
import oracle.sdp.messaging.Listener;
import oracle.sdp.messaging.MessagingClient;
import oracle.sdp.messaging.MessagingClientFactory;
import oracle.sdp.messaging.MessagingException;
import oracle.sdp.messaging.MessagingFactory;
import oracle.sdp.messaging.AccessPoint.AccessPointType;
import oracle.sdp.messaging.NoPermissionException;
import oracle.sdp.messaging.filter.MessageFilter;
…
/**
 * Class which will create messaging client and associate a listener to an
 * UMS access point.
 *
 * Spring bean singleton
 */
public class ListenerSubscriber {
    ….
    /**
     * Initializing method for this bean
     */
    public void initialize() {
        logger.debug("Initializing");
        if (getMessagingClient() == null) {
            setMessagingClient();
        }
        logger.debug("Initialized");
    }
    /**
     * Destroying method for this bean
     */
    public void destroy() {
        logger.debug("Destroying");
        if (getMessagingClient() != null) {
            logger.info("Removing messaging client, to permit release of involved resources");
            MessagingClientFactory.remove(getMessagingClient());
        }
        logger.debug("Destroyed");
    }
    /**
     * Prepare configuration parameters map in order to create a messaging client
     * @return messaging client configuration parameters map
     */
    private Map<String, Object> getConfigurationParameters() {
        Map<String, Object> configurationParameters = new HashMap<String, Object>();
        // Common identifier for all instances in cluster
        configurationParameters.put(ApplicationInfo.APPLICATION_NAME, getApplicationName());
        // Unique identifier for each instance in cluster
        configurationParameters.put(ApplicationInfo.APPLICATION_INSTANCE_NAME, getApplicationInstanceName());
        return configurationParameters;
    }
    /**
     * Create a message filter
     * Actually make an email subject filter
     * @return a message filter or null (depends on filterValue)
     */
    private MessageFilter createMessageFilter() {
        MessageFilter filter = null;
        if (!getFilterValue().equals("")) {
            filter = MessagingFactory.createMessageFilter(getFilterValue(),
                                                         MessageFilter.FieldType.SUBJECT,
                                                         null,
                                                         MessageFilter.Action.REJECT);
        }
        return filter;
    }
    /**
     * Create an access point to UMS
     * @return an access point
     */
    private AccessPoint getAccessPoint() {
        AccessPoint ap =
            MessagingFactory.createAccessPoint(AccessPointType.SINGLE_ADDRESS,
                                               DeliveryType.EMAIL,
                                               getSubscribingEmail(), "");
        return ap;
    }
    /**
     * Create / configure a messaging client to UMS
     */
    public void setMessagingClient() {
        // Messaging client creation / configuration
        try {
            Map<String, Object> configurationParameters = getConfigurationParameters();
            MessageFilter filter = createMessageFilter();
            if (configurationParameters == null || listener == null) {
                logger.error("Missing parameters for messaging client creation");
                return;
            }
            logger.info("Creating messaging client using parameters : " + configurationParameters.toString());
            messagingClient = MessagingClientFactory.createMessagingClient(configurationParameters);
            logger.info("Register listener for messaging client.");
            messagingClient.setMessageListener(getListener());
            // add filter if one exist
            if (filter != null) {
                logger.info("Register filter for messaging client.");
                messagingClient.registerMessageFilter(filter);
            } else {
                logger.info("No filter associated to messaging client.");
            }
        } catch (MessagingException e) {
            logger.error("Error while creating messaging client", e);
        }
        // Access Point registration
        try {
            logger.info("Register to access point : " + getSubscribingEmail());
            messagingClient.registerAccessPoint(getAccessPoint());
        } catch (NoPermissionException npe) {
            logger.error("Error while registering messaging client to access point", npe);
        } catch (MessagingException me) {
            logger.error("Error while registering messaging client to access point", me);
        }
    }

Consommation de messages – MailListener

Cette classe implémente l’interface oracle.sdp.messaging.Listener qui propose un mécanisme similaire aux MDB, via une méthode onMessage. C’est dans cette méthode que l’on pourra mettre en place le nécessaire pour appeler un composite par exemple.
Le message reçu est de type oracle.sdp.messaging.Message, qui fournira notamment une méthode getContent qui renverra dans le cadre de consommation de mails des objets javax.mail.internet.MimeMultipart.
Il existe aussi dans l’interface une méthode onStatus, qui semble utile pour d’autres types d’échanges (messagerie instantannée).

…
import oracle.sdp.messaging.Listener;
import oracle.sdp.messaging.ListenerException;
import oracle.sdp.messaging.Message;
import oracle.sdp.messaging.Status;
…
public class MailListener implements Listener {
    …
    public void onMessage(Message message,
                          Serializable serializable) throws ListenerException {
        logger.info("Listener onMessage");
        // JOB FOR MAIL HERE
    }
    public void onStatus(Status status,
                         Serializable serializable) throws ListenerException {
        logger.info("Listener onStatus");
    }
     …
}

Conclusion

Cet article nous a permis finalement de voir :

  • Configuration du driver email (avec SSL)
  • Utilisation d’UMS via ses API Java

Bien sûr, je ne conseillerais pas comme source d’initialisation de composites les emails. La solution mise en place reste d’une certaine complexité, pour une simple consommation de messages emails. Posez-vous au préalable la question concernant la nécessité de cette opération, et les alternatives envisageables. Elles seront souvent plus acceptables qu’une telle solution.
Cependant à travers cette problématique, vous aurez pu découvrir UMS, et la possibilité pour des applications tierces d’utiliser un mécanisme de communication / notification simple et robuste : chat, mail, SMS…