com.athena.sqs.MessageAggregator.java Source code

Java tutorial

Introduction

Here is the source code for com.athena.sqs.MessageAggregator.java

Source

/*
 * Copyright 2012 The Athena Project
 *
 * The Athena Project licenses this file to you 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 com.athena.sqs;

import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import sun.misc.BASE64Decoder;

/**
 * This class allows you to process a composite message by splitting it up,
 * and the re-aggregating the responses back into a single message.
 *
 * @author Ji-Woong Choi(ienvyou@gmail.com)
 *
 */
@Service
public class MessageAggregator {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    // Store transaction id and message map
    private static ConcurrentHashMap<String, ConcurrentHashMap<Integer, String>> txMap = new ConcurrentHashMap<String, ConcurrentHashMap<Integer, String>>();

    /**
     * Aggregate splitted messages into single message.
     * @param rawData base64 string
     * @throws MessageException
     */
    public void aggregate(String rawString) throws MessageException {
        try {
            BASE64Decoder decoder = new BASE64Decoder();

            int index = rawString.indexOf(MessageContext.DATA_DELIMITER);

            // 1. Split header
            String[] header = parseHeader(rawString.substring(0, index));
            String content = rawString.substring(index + 2);

            // 2. Assign header value to local variable
            MessageTransferType transferType = MessageTransferType.valueOf(header[0]);
            String businessName = header[1];
            String transactionId = header[2];
            MessageSplitType splitType = MessageSplitType.valueOf(header[3]);
            int current = Integer.parseInt(header[4]);
            int total = Integer.parseInt(header[5]);

            // 3 Check Message Single
            switch (splitType) {
            case SINGLE:
                // TODO single message work
                doProcess(transactionId, new String(decoder.decodeBuffer(content)));
                return;
            case MULTI:
                break;
            }

            logger.debug("Transaction ID : " + transactionId);

            // 4. Check Message Order
            // If transaction id is not exist in txMap, create new tx map object
            if (!txMap.containsKey(transactionId)) {
                ConcurrentHashMap<Integer, String> orderedMessages = new ConcurrentHashMap<Integer, String>();
                orderedMessages.put(current, content);

                txMap.put(transactionId, orderedMessages);
            } else {
                // Already same transaction message was inserted
                ConcurrentHashMap<Integer, String> orderedMessages = txMap.get(transactionId);
                orderedMessages.put(current, content);

                // Message compare
                if (orderedMessages.size() == total) {
                    // All messages arrived
                    Object[] key = orderedMessages.keySet().toArray();
                    Arrays.sort(key);

                    String finalMessage = "";
                    for (int i = 0; i < key.length; i++) {
                        finalMessage += orderedMessages.get(key[i]);
                    }

                    logger.debug("===== [ " + transactionId + "] ======");
                    logger.debug(new String(decoder.decodeBuffer(finalMessage)));
                    boolean isDelete = txMap.remove(transactionId, orderedMessages);
                    if (!isDelete) {
                        throw new MessageException("Can't delete message from transaction map");
                    }

                    doProcess(transactionId, new String(decoder.decodeBuffer(finalMessage)));
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String[] parseHeader(String header) {
        return header.split("\\|");
    }

    /**
     * Process single message type.
     * @param message
     * @throws IOException
     * @throws JsonMappingException
     * @throws JsonParseException
     */
    public void doProcess(String transactionId, String rawString) throws MessageException {
        try {
            ObjectMapper mapper = new ObjectMapper();
            Message message = mapper.readValue(rawString, new TypeReference<Message>() {
            });
            logger.debug("=======================[MESSAGES]=============================");
            logger.debug(message.toString());
            logger.debug("===========================================================");

        } catch (Exception e) {
            throw new MessageException("Error during processing message: " + e.getMessage());
        } finally {

        }
    }

}