org.belio.mq.RabbitPublisher.java Source code

Java tutorial

Introduction

Here is the source code for org.belio.mq.RabbitPublisher.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.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.belio.Launcher;
import org.belio.domain.tix.Alert;
import org.belio.domain.tix.Outbox;
import org.belio.domain.tix.OutboxList;
import org.belio.model.MessagePublisher;
import org.belio.model.Queuable;
import org.belio.model.QueueType;
import org.belio.model.Status;
import org.belio.service.producer.DbReader;

/**
 *
 * @author dena
 */
public class RabbitPublisher extends EndPoint implements MessagePublisher, Status {

    final List<? extends Queuable> messageQueue;
    final List<Queuable> failedMessageQueue;
    DbReader dbReader;
    Alert alert;
    String[] hosts;

    public RabbitPublisher(DbReader dbReader, final Properties properties, List<? extends Queuable> messageQueue,
            final QueueType queuetype, Alert alert) {
        super(properties, queuetype);
        this.dbReader = dbReader;
        this.messageQueue = messageQueue;
        this.alert = alert;
        this.failedMessageQueue = new ArrayList<>();
    }

    @Override
    public void open() throws IOException {
        synchronized (RabbitPublisher.class) {
            try {
                // Create a connection factory and 
                hosts = mqproperties.getProperty("host").split(",");

                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
                connection = factory.newConnection();
                // Create a new channel and declare it's type and exhange as well
                channel = connection.createChannel();
                channel.queueDeclare(queueType.name().concat(QUEUE_SUFFIX), true, false, false, null);
                channel.exchangeDeclare(queueType.name().concat(EXCHANGE_SUFFIX), mqproperties.getProperty("type"));
                channel.queueBind(queueType.name().concat(QUEUE_SUFFIX), queueType.name().concat(EXCHANGE_SUFFIX),
                        "");
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    @Override
    public void publish() {
        try {
            open();
        } catch (IOException ex) {
            Logger.getLogger(RabbitPublisher.class.getName()).log(Level.SEVERE, null, ex);
        }
        //        synchronized (this) {
        OutboxList outboxList = new OutboxList(queueType);
        outboxList.setOutboxes((ArrayList<Outbox>) messageQueue);
        Long startTime = System.currentTimeMillis();
        int MQTHREADS = 3;
        ExecutorService executor = Executors.newFixedThreadPool(MQTHREADS);

        try {
            channel.txSelect();
            dbReader.insertSublistBatch(messageQueue);
            // check that insert is complete
            int alertsSaved = dbReader.saveAlertsToOutboxCount(alert);
            if (alertsSaved == messageQueue.size()) {
                Launcher.LOG.info("publishing " + alert + " to " + alert.getType().name());
                // create a map that will hold the outbox lists of different networks
                Map<String, OutboxList> map = new HashMap<>();
                // loop through the messages to add them onto outbox lists in batches of 10
                for (Outbox outbox : outboxList.getOutboxes()) {
                    // check if the map contains an outbox list of the network
                    if (map.containsKey(outbox.getNetwork())) {
                        // check if the max of 10 has been reached in the size of the outboxlist
                        if (map.get(outbox.getNetwork()).getOutboxes().size() < Integer
                                .parseInt(threadproperties.getProperty("batch_size"))) {
                            // add the outbox to the outboxlist if the size is less than 10
                            map.get(outbox.getNetwork()).add(outbox);
                        } else {
                            // publish the outboxlist to MQ and reset the outboxlist 
                            OutboxList ol = map.get(outbox.getNetwork());
                            final String message = xStream.toXML(ol);

                            Runnable worker = new Runnable() {

                                @Override
                                public void run() {
                                    try {
                                        channel.basicPublish(alert.getType().name().concat(EXCHANGE_SUFFIX),
                                                alert.getType().name().concat(QUEUE_SUFFIX),
                                                MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
                                    } catch (IOException ex) {
                                        Logger.getLogger(RabbitPublisher.class.getName()).log(Level.SEVERE, null,
                                                ex);
                                    }
                                }
                            };
                            executor.execute(worker);
                            // clear the outboxlist of the network
                            map.get(outbox.getNetwork()).getOutboxes().clear();
                        }
                    } else {
                        // create the outbox list for the network
                        map.put(outbox.getNetwork(), new OutboxList(queueType));
                        // add an outbox to the outboxlist
                        map.get(outbox.getNetwork()).add(outbox);
                    }

                }
                // get the iterator of the entries in the map for publishing
                for (Map.Entry<String, OutboxList> entry : map.entrySet()) {
                    // publish the outboxlist to MQ and reset the outboxlist 
                    OutboxList ol = entry.getValue();
                    final String message = xStream.toXML(ol);

                    Runnable worker = new Runnable() {

                        @Override
                        public void run() {
                            try {
                                channel.basicPublish(alert.getType().name().concat(EXCHANGE_SUFFIX),
                                        alert.getType().name().concat(QUEUE_SUFFIX),
                                        MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
                            } catch (IOException ex) {
                                Logger.getLogger(RabbitPublisher.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    };
                    executor.execute(worker);
                    // clear the outboxlist of the network
                    entry.getValue().getOutboxes().clear();
                }

                channel.txCommit();
                dbReader.updateAlertStatus(alert, "SENT", messageQueue.size(),
                        new Timestamp(Calendar.getInstance().getTimeInMillis()));
                dbReader.deleteCSVFile(alert);
            } else {
                channel.txRollback();
                Launcher.LOG.info("unable to publish " + alert + " to " + alert.getType().name() + " " + alertsSaved
                        + " - " + messageQueue.size());
                dbReader.updateAlertStatus(alert, "UNSENT", null, null);
                //TO:DO
                //delete from outboxes where alert
                dbReader.deleteCSVFile(alert);
            }
        } catch (IOException exception) {
            Launcher.LOG.error("Error publishing", exception);
            //TODO log exception
            dbReader.updateAlertStatus(alert, "UNSENT", null, null);
            dbReader.deleteCSVFile(alert);
            //TO:DO
            //delete from outboxes where alert
            // reset message to unsent
            //failedMessageQueue.add(queuable);
            try {
                channel.txRollback();
            } catch (IOException ioe) {
                //TODO log message
            }
        }
        Long endTime = System.currentTimeMillis();
        Long timeTaken = endTime - startTime;
        Launcher.LOG.info("Took " + timeTaken + " to publish");
        try {
            //        System.exit(0);
            close();
        } catch (IOException ex) {
            Logger.getLogger(RabbitPublisher.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public int queueSize() {
        return failedMessageQueue.size();
    }

}