org.belio.mq.RabbitConsumer.java Source code

Java tutorial

Introduction

Here is the source code for org.belio.mq.RabbitConsumer.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.belio.mq;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.ConsumerCancelledException;
import com.rabbitmq.client.MessageProperties;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.client.ShutdownSignalException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.math.BigInteger;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import org.belio.Launcher;
import org.belio.domain.tix.Outbox;
import org.belio.domain.tix.OutboxList;
import org.belio.model.MessageConsumer;
import org.belio.model.QueueType;
import org.belio.model.Status;
import static org.belio.mq.RabbitConsumer.NETWORK.AIRTEL;
import static org.belio.mq.RabbitConsumer.NETWORK.ORANGE;
import static org.belio.mq.RabbitConsumer.NETWORK.SAFARICOM;
import static org.belio.mq.RabbitConsumer.NETWORK.YU;
import org.belio.service.consumer.Consumer;
import org.belio.service.gateway.SafcomGateway;

/**
 *
 * @author jacktone
 */
public class RabbitConsumer extends EndPoint implements MessageConsumer, Status {

    private final OutboxList outboxes;
    private final long sleepTime;
    ScheduledExecutorService executor;
    private Properties spproperties;
    private Properties networkproperties;
    private SOAPConnectionFactory soapConnectionFactory;
    protected Channel publishingChannel;
    protected Connection publishingConnection;

    public RabbitConsumer(Properties properties, QueueType queuetype, long sleepTime) throws IOException {
        super(properties, queuetype);
        this.outboxes = new OutboxList(queuetype);
        this.sleepTime = sleepTime;
        try {
            this.spproperties = Launcher.fetchConfigurations("spid.properties");
        } catch (IOException ex) {
            Logger.getLogger(SafcomGateway.class.getName()).log(Level.SEVERE, null, ex);
        }

        Logger.getLogger(Launcher.class.getName()).log(Level.INFO, " consumer constructor");

        try {
            soapConnectionFactory = SOAPConnectionFactory.newInstance();
        } catch (SOAPException ex) {
            Logger.getLogger(RabbitConsumer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedOperationException ex) {
            Logger.getLogger(RabbitConsumer.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    @Override
    public void open() throws IOException {

        try {
            com.rabbitmq.client.ConnectionFactory factory = new com.rabbitmq.client.ConnectionFactory();
            factory.setHost(mqproperties.getProperty("host"));
            factory.setVirtualHost(mqproperties.getProperty("vhost"));
            factory.setUsername(mqproperties.getProperty("username"));
            factory.setPassword(mqproperties.getProperty("password"));
            factory.setPort(Integer.parseInt(mqproperties.getProperty("port")));
            factory.setAutomaticRecoveryEnabled(true);
            factory.setNetworkRecoveryInterval(1);
            // Create a new connection to MQ
            connection = factory.newConnection();
            // Create a new channel and declare it's type and exhange as well
            //Create a new rabbit publisher           
            executor = Executors.newScheduledThreadPool(
                    Integer.parseInt(threadproperties.getProperty(queueType.name().toLowerCase()).split(",")[0]));

        } catch (IOException ex) {
            Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ShutdownSignalException ex) {
            Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ConsumerCancelledException ex) {
            Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    private void publish(OutboxList outboxList) throws IOException {
        openPublisher();
        final String message = xStream.toXML(outboxList);
        publishingChannel.basicPublish(queueType.name().concat(EXCHANGE_SUFFIX),
                queueType.name().concat(QUEUE_SUFFIX), MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
        Launcher.LOG.info("Republished " + outboxList);
        closePublisher();
    }

    private void openPublisher() {
        try {
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost(mqproperties.getProperty("host"));
            factory.setVirtualHost(mqproperties.getProperty("vhost"));
            factory.setUsername(mqproperties.getProperty("username"));
            factory.setPassword(mqproperties.getProperty("password"));
            factory.setPort(Integer.parseInt(mqproperties.getProperty("port")));
            // Create a new connection to MQ
            publishingConnection = factory.newConnection();
            // Create a new channel and declare it's type and exhange as well
            publishingChannel = connection.createChannel();
            publishingChannel.queueDeclare(queueType.name().concat(QUEUE_SUFFIX), true, false, false, null);
            publishingChannel.exchangeDeclare(queueType.name().concat(EXCHANGE_SUFFIX),
                    mqproperties.getProperty("type"));
            publishingChannel.queueBind(queueType.name().concat(QUEUE_SUFFIX),
                    queueType.name().concat(EXCHANGE_SUFFIX), "");
        } catch (IOException exception) {
            Launcher.LOG.error(exception.getLocalizedMessage(), exception);
        }
    }

    private void closePublisher() {
        if (publishingConnection.isOpen()) {
            try {
                publishingConnection.close();
            } catch (IOException exception) {
                Launcher.LOG.error(exception.getLocalizedMessage(), exception);
            }
        }
    }

    @Override
    public void consume() {

        try {
            open();
        } catch (IOException ex) {
            Logger.getLogger(RabbitConsumer.class.getName()).log(Level.SEVERE, null, ex);
        }

        try {

            final QueueingConsumer consumer = new QueueingConsumer(channel);
            channel = connection.createChannel();
            try {
                channel.basicConsume(queueType.name().concat(QUEUE_SUFFIX), false, consumer);
                channel.basicQos(Integer.parseInt(threadproperties.getProperty("qos")));
            } catch (Exception e) {
                Logger.getLogger(Launcher.class.getName()).log(Level.SEVERE, e.getMessage());
                channel = connection.createChannel();
            }

            while (true) {
                Logger.getLogger(Launcher.class.getName()).log(Level.INFO, " Waiting for messages ''");
                final QueueingConsumer.Delivery delivery = consumer.nextDelivery();
                Runnable worker = new Runnable() {

                    @Override
                    public void run() {

                        try {
                            Thread.sleep(Long.valueOf(threadproperties.getProperty("sleep")));
                            String message = new String(delivery.getBody());
                            Object fromXML = xStream.fromXML(message);
                            if (fromXML instanceof OutboxList) {
                                OutboxList outboxList = (OutboxList) fromXML;
                                for (NETWORK network : NETWORK.values()) {
                                    if (outboxList.getOutboxes().get(0).getNetwork()
                                            .equalsIgnoreCase(network.name())) {
                                        Logger.getLogger(Launcher.class.getName()).log(Level.INFO,
                                                "Sending " + outboxList);
                                        boolean sent = sendMessagesToGateWay(network, outboxList);
                                        if (!sent) {
                                            try {
                                                publish(outboxList);
                                            } catch (IOException exception) {
                                                Launcher.LOG.error(exception.getLocalizedMessage(), exception);
                                            }
                                        }
                                        try {
                                            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
                                        } catch (IOException exception) {
                                            Launcher.LOG.error(exception.getLocalizedMessage(), exception);
                                        }
                                    }
                                }
                            }
                        } catch (ShutdownSignalException ex) {
                            Logger.getLogger(RabbitConsumer.class.getName()).log(Level.SEVERE, null, ex);
                        } catch (ConsumerCancelledException ex) {
                            Logger.getLogger(RabbitConsumer.class.getName()).log(Level.SEVERE, null, ex);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(RabbitConsumer.class.getName()).log(Level.SEVERE, null, ex);
                        }

                    }
                };
                executor.execute(worker);
                Logger.getLogger(Launcher.class.getName()).log(Level.INFO, "SLEEPING FOR " + sleepTime);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        try {
            close();
        } catch (IOException ex) {
            Logger.getLogger(RabbitConsumer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public int queueSize() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public OutboxList getMessages() {
        return outboxes;

    }

    private boolean sendMessagesToGateWay(NETWORK network, OutboxList outboxList) {
        boolean sent = false;
        switch (network) {
        case SAFARICOM:
            long startTime = System.currentTimeMillis();
            sent = sendSafaricomMessage(queueType, outboxList);
            long endTime = System.currentTimeMillis();
            long timeTaken = endTime - startTime;
            break;
        case AIRTEL:
        case YU:
        case ORANGE:
            //                sent = Gateway.getInstance().sendBulkMessages(outboxList);
            sent = true;
            break;
        default:
            break;
        }
        return sent;
    }

    @Override
    public void close() throws IOException {
        executor.shutdown();
        try {
            executor.awaitTermination(1, TimeUnit.HOURS);
        } catch (InterruptedException exception) {
        }
        super.close(); //To change body of generated methods, choose Tools | Templates.
    }

    public enum NETWORK {

        SAFARICOM, AIRTEL, YU, ORANGE,
    }

    private boolean sendSafaricomMessage(QueueType queueType, OutboxList outboxList) {
        return sendMessage(queueType, outboxList);

    }

    private boolean sendMessage(QueueType queueType, OutboxList outboxList) {
        try {
            String now = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
            MessageDigest md = MessageDigest.getInstance("MD5");
            String serviceId = outboxList.getOutboxes().get(0).getServiceID();
            String endpointDef = "";
            //            if (queueType.equals(QueueType.BULK)) {
            //                endpointDef = networkproperties.getProperty("safcom_mt_endpoint");
            //            } else {
            endpointDef = networkproperties.getProperty("safcom_endpoint");
            // }
            String code = outboxList.getOutboxes().get(0).getShortCode();
            String spIdString = outboxList.getOutboxes().get(0).getSdpId();
            String spPasswordString = createSpPass(spIdString, now, md);
            String actualmessage = URLDecoder
                    .decode(URLEncoder.encode(outboxList.getOutboxes().get(0).getText(), "UTF-8"), "UTF-8");
            Launcher.LOG.info("T----------------------------------------J" + actualmessage);
            String gencorrelator = String.valueOf(outboxList.getOutboxes().get(0).getRefNo());
            // Create SOAP Connection

            SOAPConnection soapConnection = soapConnectionFactory.createConnection();
            // Send SOAP Message to SOAP Server
            SOAPMessage messageToSend = getSoapMessageFromString(getMessage(spIdString, spPasswordString,
                    outboxList, serviceId, now, actualmessage, code, gencorrelator, endpointDef));
            Calendar start = Calendar.getInstance();
            System.out.println("XXXXXXXXXXXXXXXXXXX====Sending Safaricom message");
            printSOAPResponse(messageToSend);
            SOAPMessage soapResponse = soapConnection.call(messageToSend,
                    networkproperties.getProperty("safcom_sms"));
            Launcher.LOG.info("Took " + (Calendar.getInstance().getTimeInMillis() - start.getTimeInMillis()));
            //            SOAPMessage soapResponse = null;  
            printSOAPResponse(soapResponse);//TODO log
            SOAPBody body = soapResponse.getSOAPBody();
            if (body.hasFault()) {
                SOAPFault newFault = body.getFault();
                System.out.println(">>>>>>>>>>>>>" + newFault.getFaultString());
                soapConnection.close();
                System.out.println("XXXXXXXXXXXXXXXXXXX====DOne Sending Safaricom message");
                return false;
            } else {
                //TO DO log
                soapConnection.close();
                System.out.println("XXXXXXXXXXXXXXXXXXX====DOne Sending Safaricom message");
                return true;

            }
        } catch (Exception ex) {
            Launcher.LOG.info(ex.getMessage());
        }
        //System.out.println("XXXXXXXXXXXXXXXXXXX====DOne Sending Safaricom message");
        return false;
    }

    private String createSpPass(String spIdString, String now, MessageDigest md) {
        String allpass = spIdString + (spproperties.getProperty(spIdString).split(",")[0]) + now;
        Launcher.LOG.info(spIdString);
        md.update(allpass.getBytes());
        byte[] digest = md.digest();
        BigInteger bigInt = new BigInteger(1, digest);
        String spPasswordString = bigInt.toString(16);
        while (spPasswordString.length() < 32) {
            spPasswordString = "0" + spPasswordString;
        }
        Launcher.LOG.info(spPasswordString);
        //String recepient = "tel:254724170138";
        return spPasswordString;
    }

    private static String getMessage(String spId, String spPassword, OutboxList outboxList, String serviceId,
            String timeStamp, String actualmessage, String senderName, String correlator, String endpoint) {
        StringBuilder builder = new StringBuilder();
        builder.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n")
                .append("xmlns:v2=\"http://www.huawei.com.cn/schema/common/v2_1\"\n")
                .append("xmlns:loc=\"http://www.csapi.org/schema/parlayx/sms/send/v2_2/local\">\n")
                .append("<soapenv:Header>").append("<v2:RequestSOAPHeader>").append("<spId>").append(spId)
                .append("</spId>").append("<spPassword>").append(spPassword).append("</spPassword>")
                .append("<serviceId>").append(serviceId).append("</serviceId>").append("<timeStamp>")
                .append(timeStamp).append("</timeStamp>").append("</v2:RequestSOAPHeader>")
                .append("</soapenv:Header>").append("<soapenv:Body>").append("<loc:sendSms>");
        for (Outbox outbox : outboxList.getOutboxes()) {
            builder.append("<loc:addresses>").append(String.valueOf(outbox.getMsisdn())).append("</loc:addresses>");
        }
        builder.append("<loc:senderName>").append(senderName).append("</loc:senderName>").append("<loc:message>")
                .append(actualmessage).append("</loc:message>").append("<loc:receiptRequest>").append("<endpoint>")
                .append(endpoint).append("</endpoint>").append("<interfaceName>SmsNotification</interfaceName>")
                .append("<correlator>").append(correlator).append("</correlator>").append("</loc:receiptRequest>")
                .append("</loc:sendSms>").append("</soapenv:Body>").append("</soapenv:Envelope>");

        return builder.toString();
    }

    private static SOAPMessage getSoapMessageFromString(String xml) throws SOAPException, IOException {
        MessageFactory factory = MessageFactory.newInstance();
        javax.xml.soap.SOAPMessage message = factory.createMessage(new MimeHeaders(),
                new ByteArrayInputStream(xml.getBytes(Charset.forName("UTF-8"))));
        return message;
    }

    /**
     * Method used to print the SOAP Response
     */
    private static void printSOAPResponse(SOAPMessage soapResponse) throws Exception {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        Source sourceContent = soapResponse.getSOAPPart().getContent();
        // System.out.print("\nResponse SOAP Message = ");
        StreamResult result = new StreamResult(new StringWriter());
        transformer.transform(sourceContent, result);
        String xmlString = result.getWriter().toString();
        Launcher.LOG.info(xmlString);
    }

}