org.springside.examples.showcase.log.appender.JdbcLogWriter.java Source code

Java tutorial

Introduction

Here is the source code for org.springside.examples.showcase.log.appender.JdbcLogWriter.java

Source

/**
 * Copyright (c) 2005-2009 springside.org.cn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * 
 * $Id: JdbcAppenderTask.java 353 2009-08-22 09:33:28Z calvinxiu
 */
package org.springside.examples.showcase.log.appender;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.apache.log4j.spi.LoggingEvent;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springside.examples.showcase.queue.BlockingConsumer;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * Queuelog4j event?.
 * 
 * ??Queue,??Jdbc??.
 * ???,PeriodConsumer???.
 * 
 * @see BlockingConsumer
 * 
 * @author calvin
 */
public class JdbcLogWriter extends BlockingConsumer {

    protected String sql;
    protected int batchSize = 10;

    protected List<LoggingEvent> eventsBuffer = Lists.newArrayList();
    protected SimpleJdbcTemplate jdbcTemplate;
    protected TransactionTemplate transactionTemplate;

    /**
     * Named Parameterinsert sql.
     * 
     * Named Parameter???AppenderUtils?.
     */
    public void setSql(String sql) {
        this.sql = sql;
    }

    /**
     * ???, 10.
     */
    public void setBatchSize(int batchSize) {
        this.batchSize = batchSize;
    }

    /**
     * ?DataSourcejdbcTemplate.
     */
    @Resource
    public void setDataSource(DataSource dataSource) {
        jdbcTemplate = new SimpleJdbcTemplate(dataSource);
    }

    /**
     * ?PlatformTransactionManagertransactionTemplate.
     */
    @Resource
    public void setDefaultTransactionManager(PlatformTransactionManager defaultTransactionManager) {
        transactionTemplate = new TransactionTemplate(defaultTransactionManager);
    }

    /**
     * ??,?buffer,bufferbatchSize?.
     */
    @Override
    protected void processMessage(Object message) {
        LoggingEvent event = (LoggingEvent) message;
        eventsBuffer.add(event);

        if (logger.isDebugEnabled()) {
            logger.debug("get event: {}", new LoggingEventWrapper(event).convertToString());
        }

        //BufferSize???
        if (eventsBuffer.size() >= batchSize) {
            updateBatch();
        }
    }

    /**
     * Buffer???.
     */
    @SuppressWarnings("unchecked")
    public void updateBatch() {
        try {
            //?, ?jdbc??.
            int i = 0;
            Map[] paramMapArray = new HashMap[eventsBuffer.size()];
            for (LoggingEvent event : eventsBuffer) {
                paramMapArray[i++] = parseEvent(event);
            }
            final SqlParameterSource[] batchParams = SqlParameterSourceUtils.createBatch(paramMapArray);

            //??,?.
            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    try {
                        jdbcTemplate.batchUpdate(getActualSql(), batchParams);
                        if (logger.isDebugEnabled()) {
                            for (LoggingEvent event : eventsBuffer) {
                                logger.debug("saved event: {}", new LoggingEventWrapper(event).convertToString());
                            }
                        }
                    } catch (DataAccessException e) {
                        status.setRollbackOnly();
                        handleDataAccessException(e, eventsBuffer);
                    }
                }
            });

            //?Buffer
            eventsBuffer.clear();
        } catch (Exception e) {
            logger.error("????.", e);
        }
    }

    /**
     * ?,?buffer??.
     */
    @Override
    protected void clean() {
        if (!eventsBuffer.isEmpty()) {
            updateBatch();
        }
        logger.debug("cleaned task {}", this);
    }

    /**
     * ?Event, Parameter Map, sqlNamed Parameter.
     */
    protected Map<String, Object> parseEvent(LoggingEvent event) {
        Map<String, Object> parameterMap = Maps.newHashMap();
        LoggingEventWrapper eventWrapper = new LoggingEventWrapper(event);

        parameterMap.put("thread_name", eventWrapper.getThreadName());
        parameterMap.put("logger_name", eventWrapper.getLoggerName());
        parameterMap.put("log_time", eventWrapper.getDate());
        parameterMap.put("level", eventWrapper.getLevel());
        parameterMap.put("message", eventWrapper.getMessage());
        return parameterMap;
    }

    /**
     * ?????,?.
     */
    protected void handleDataAccessException(DataAccessException e, List<LoggingEvent> errorEventBatch) {
        if (e instanceof DataAccessResourceFailureException) {
            logger.error("database connection error", e);
        } else {
            logger.error("other database error", e);
        }

        for (LoggingEvent event : errorEventBatch) {
            logger.error("event insert to database error, ignore it: "
                    + new LoggingEventWrapper(event).convertToString(), e);
        }
    }

    /**
     * ???sql??,?sql?????? LOG_2009_02_31.
     */
    protected String getActualSql() {
        return sql;
    }
}