br.com.porcelli.hornetq.integration.twitter.stream.MessageQueuing.java Source code

Java tutorial

Introduction

Here is the source code for br.com.porcelli.hornetq.integration.twitter.stream.MessageQueuing.java

Source

/**
 * Copyright (c) 2010 Alexandre Porcelli <alexandre.porcelli@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package br.com.porcelli.hornetq.integration.twitter.stream;

import static br.com.porcelli.hornetq.integration.twitter.support.TweetMessageConverterSupport.buildMessage;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;

import org.hornetq.api.core.HornetQException;
import org.hornetq.api.core.Message;
import org.hornetq.api.core.TransportConfiguration;
import org.hornetq.api.core.client.ClientProducer;
import org.hornetq.api.core.client.ClientSession;
import org.hornetq.api.core.client.ClientSessionFactory;
import org.hornetq.api.core.client.HornetQClient;
import org.hornetq.core.logging.Logger;
import org.hornetq.core.remoting.impl.invm.InVMConnectorFactory;
import org.hornetq.core.server.ServerMessage;

import twitter4j.DirectMessage;
import twitter4j.Status;
import twitter4j.Tweet;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import br.com.porcelli.hornetq.integration.twitter.data.InternalTwitterConstants;
import br.com.porcelli.hornetq.integration.twitter.data.TwitterStreamDTO;
import br.com.porcelli.hornetq.integration.twitter.jmx.ExceptionNotifier;
import br.com.porcelli.hornetq.integration.twitter.stream.reclaimer.AbstractBaseReclaimLostTweets;
import br.com.porcelli.hornetq.integration.twitter.support.ReflectionSupport;

public class MessageQueuing {
    private static final Logger log = Logger.getLogger(MessageQueuing.class);
    private final TwitterStreamDTO data;
    private final Set<? extends AbstractBaseReclaimLostTweets> reclaimersSet;
    private final ExceptionNotifier exceptionNotifier;
    private ClientProducer producerLastTweet = null;
    private ClientProducer producerLastDM = null;
    private ClientSession session = null;
    private final AtomicLong tweetCount = new AtomicLong();
    private final AtomicLong dmCount = new AtomicLong();
    private final AtomicLong statusCount = new AtomicLong();
    private final AtomicLong totalCount = new AtomicLong();

    public MessageQueuing(final TwitterStreamDTO data, final ExceptionNotifier exceptionNotifier,
            final String[] reclaimers) {
        this.data = data;
        this.exceptionNotifier = exceptionNotifier;
        if (reclaimers == null) {
            reclaimersSet = null;
        } else {
            reclaimersSet = buildReclaimers(this.data, reclaimers);
        }
    }

    private <R extends AbstractBaseReclaimLostTweets> Set<R> buildReclaimers(final TwitterStreamDTO data,
            final String[] reclaimers) {
        final Class<?>[] constructorArgs = new Class<?>[] { TwitterStreamDTO.class, MessageQueuing.class,
                ExceptionNotifier.class };
        final Object[] args = new Object[] { data, this, exceptionNotifier };

        final Set<R> result = new HashSet<R>();
        for (final String activeReclaimer : reclaimers) {
            try {
                final Class<R> clazz = (Class<R>) Class.forName(activeReclaimer);
                if (AbstractBaseReclaimLostTweets.class.isAssignableFrom(clazz)) {
                    result.add(ReflectionSupport.buildInstance(clazz, constructorArgs, args));
                }
            } catch (final ClassNotFoundException e) {
                exceptionNotifier.notifyException(e);
                log.error("Twitter Reclaimer '" + activeReclaimer + "' not found");
            }
        }
        if (result.size() == 0) {
            return null;
        }
        return result;
    }

    public void postMessage(final Status status, final boolean isReclaimer) throws Exception {
        final ServerMessage msg = buildMessage(data.getQueueName(), status);
        statusCount.incrementAndGet();
        totalCount.incrementAndGet();
        internalPostTweet(msg, status.getId(), isReclaimer);
    }

    public void postMessage(final Tweet tweet, final boolean isReclaimer) throws Exception {
        final ServerMessage msg = buildMessage(data.getQueueName(), tweet);
        tweetCount.incrementAndGet();
        totalCount.incrementAndGet();
        internalPostTweet(msg, tweet.getId(), isReclaimer);
    }

    public void postMessage(final DirectMessage dm, final boolean isReclaimer) throws Exception {
        final ServerMessage msg = buildMessage(data.getQueueName(), dm);
        dmCount.incrementAndGet();
        totalCount.incrementAndGet();
        internalPostDM(msg, dm.getId(), isReclaimer);
    }

    private void internalPostTweet(final ServerMessage msg, final long id, final boolean isReclaimer)
            throws Exception {
        data.getPostOffice().route(msg, false);
        postOnLastTweetQueue(id);
        if (!isReclaimer) {
            executeReclaimers();
        }
    }

    private void internalPostDM(final ServerMessage msg, final long id, final boolean isReclaimer)
            throws Exception {
        data.getPostOffice().route(msg, false);
        postOnLastDMQueue(id);
        if (!isReclaimer) {
            executeReclaimers();
        }
    }

    private void executeReclaimers() {
        if (reclaimersSet != null && reclaimersSet.size() > 0) {
            final Twitter twitter = new TwitterFactory(data.getConf()).getInstance();
            final Set<AbstractBaseReclaimLostTweets> executedReclaimers = new HashSet<AbstractBaseReclaimLostTweets>();
            for (final AbstractBaseReclaimLostTweets reclaimer : reclaimersSet) {
                try {
                    reclaimer.execute(twitter);
                    executedReclaimers.add(reclaimer);
                } catch (final Exception e) {
                    log.error("Couldn't execute reclaimer:" + reclaimer.getClass().getName(), e);
                }
            }
            twitter.shutdown();
            for (AbstractBaseReclaimLostTweets activeExecutedReclaimer : executedReclaimers) {
                reclaimersSet.remove(activeExecutedReclaimer);
                activeExecutedReclaimer = null;
            }
        }
    }

    private void postOnLastTweetQueue(final long id) {
        if (data.getLastTweetQueueName() != null) {
            try {
                if (getSession() != null) {
                    final Message msg = getSession().createMessage(true);
                    msg.setAddress(data.getFormattedLastTweetQueueName());
                    msg.getBodyBuffer().writeLong(id);
                    msg.putStringProperty(Message.HDR_LAST_VALUE_NAME,
                            InternalTwitterConstants.LAST_TWEET_ID_VALUE);
                    producerLastTweet.send(msg);
                }
            } catch (final Exception e) {
                exceptionNotifier.notifyException(e);
                log.error("Error on postLastTweetQueue.", e);
            }
        }
    }

    private void postOnLastDMQueue(final long id) {
        if (data.getLastDMQueueName() != null) {
            try {
                if (getSession() != null) {
                    final Message msg = getSession().createMessage(true);
                    msg.setAddress(data.getFormattedLastDMQueueName());
                    msg.getBodyBuffer().writeLong(id);
                    msg.putStringProperty(Message.HDR_LAST_VALUE_NAME, InternalTwitterConstants.LAST_DM_ID_VALUE);
                    producerLastDM.send(msg);
                }
            } catch (final Exception e) {
                exceptionNotifier.notifyException(e);
                log.error("Error on postLastDMQueue.", e);
            }
        }
    }

    private ClientSession getSession() {
        if (session != null) {
            return session;
        }
        if (data.getFormattedLastTweetQueueName() == null && data.getFormattedLastDMQueueName() == null) {
            return null;
        }
        try {
            final ClientSessionFactory sf = HornetQClient
                    .createClientSessionFactory(new TransportConfiguration(InVMConnectorFactory.class.getName()));
            session = sf.createSession();
            if (data.getFormattedLastTweetQueueName() != null) {
                producerLastTweet = session.createProducer(data.getFormattedLastTweetQueueName());
            }
            if (data.getFormattedLastDMQueueName() != null) {
                producerLastDM = session.createProducer(data.getFormattedLastDMQueueName());
            }
            return session;
        } catch (final HornetQException e) {
            exceptionNotifier.notifyException(e);
            return null;
        }
    }

    public void dispose() {
        if (producerLastTweet != null) {
            try {
                producerLastTweet.close();
            } catch (final HornetQException e) {
                exceptionNotifier.notifyException(e);
                log.error("Error on producerLastTweet close.", e);
            }
        }
        if (producerLastDM != null) {
            try {
                producerLastDM.close();
            } catch (final HornetQException e) {
                exceptionNotifier.notifyException(e);
                log.error("Error on producerLastDM close.", e);
            }
        }
        if (session != null) {
            try {
                session.close();
            } catch (final HornetQException e) {
                exceptionNotifier.notifyException(e);
                log.error("Error on session close", e);
            }
        }
    }

    public long getDMCount() {
        return dmCount.get();
    }

    public long getStatusCount() {
        return statusCount.get();
    }

    public long getTweetCount() {
        return tweetCount.get();
    }

    public long getTotalCount() {
        return totalCount.get();
    }

}