org.mule.module.mybatis.MyBatisConnector.java Source code

Java tutorial

Introduction

Here is the source code for org.mule.module.mybatis.MyBatisConnector.java

Source

/**
 * (c) 2003-2014 Ricston, Ltd. The software in this package is published under the terms of the CPAL v1.0 license,
 * a copy of which has been included with this distribution in the LICENSE.md file.
 */

package org.mule.module.mybatis;

import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.inject.Inject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.mule.api.MuleContext;
import org.mule.api.annotations.Configurable;
import org.mule.api.annotations.Connector;
import org.mule.api.annotations.Processor;
import org.mule.api.annotations.lifecycle.Start;
import org.mule.api.annotations.param.Optional;
import org.mule.api.annotations.param.Payload;
import org.mule.api.lifecycle.LifecycleException;
import org.mule.config.i18n.MessageFactory;

/**
 * 
 * MyBatis module for Mule
 * 
 * @author Alan Cassar
 * 
 */
@Connector(name = "mybatis", friendlyName = "MyBatis", schemaVersion = "1.0")
public class MyBatisConnector {

    protected Log logger = LogFactory.getLog(getClass());

    @Inject
    private MuleContext muleContext;

    /**
     * Reference to MyBatis configuration file
     */
    @Configurable
    @Optional
    private String configFile;

    /**
     * SqlSessionFactory to use to create sessions
     */
    @Configurable
    @Optional
    private SqlSessionFactory sqlSessionFactory;

    protected ThreadLocal<SqlSession> threadLocalSession = new ThreadLocal<SqlSession>();

    /**
     * Make sure that on start up, at least one of either configFile or sqlSessionFactory is set
     * 
     * @throws LifecycleException
     */
    @Start
    public void validateConfiguration() throws LifecycleException {
        if ((configFile == null) && (sqlSessionFactory == null)) {
            throw new LifecycleException(MessageFactory.createStaticMessage(
                    "One of properties 'configFile' or 'sqlSessionFactory' must be set"), this);
        }
    }

    /**
     * Create an SqlSession by first initialising the sqlSessionFactory from the config
     * file if it is not initialised yet, or not provided.
     * 
     * First this method looks for an already open sqlSession by this thread. If there is
     * one, just return it, otherwise create a new one using the autoCommit setting specified.
     * 
     * @param autoCommit
     * @return the current or a new sqlSession
     * @throws IOException
     */
    protected SqlSession createSqlSession(boolean autoCommit) throws IOException {
        //create the sql session factory from the configuration file, if not set
        if (sqlSessionFactory == null) {
            Reader config = Resources.getResourceAsReader(configFile);
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            sqlSessionFactory = builder.build(config);
        }

        SqlSession sqlSession = threadLocalSession.get();

        //if we don't have a session, create one with auto commit set to true
        if (sqlSession == null) {
            sqlSession = sqlSessionFactory.openSession(autoCommit);
        }

        return sqlSession;
    }

    /**
     * Shortcut method to create an sqlSession with autoCommit set
     * 
     * @return sqlSession with autoCommit set to true
     * @throws IOException
     */
    protected SqlSession createSqlSession() throws IOException {
        return this.createSqlSession(true);
    }

    /**
     * Shortcut method to create a new sqlSession with autoCommit set to false.
     * 
     * @return sqlSession with autoCommit set to false
     * @throws IOException
     */
    protected SqlSession createSqlSessionForTransaction() throws IOException {
        return this.createSqlSession(false);
    }

    /**
     * Closes the sqlSession, only if it is not thread local. This means
     * that the session will be closed if there is no transaction context.
     * 
     * @param sqlSession
     */
    protected void closeSqlSession(SqlSession sqlSession) {
        //only close the session if there is no transaction in progress
        if (threadLocalSession.get() == null) {
            sqlSession.close();
        }
    }

    /**
     * Starts a new transaction by initialising a session, and setting it as thread local.
     * 
     * {@sample.xml ../../../doc/mule-mybatis-module.xml.sample mybatis:begin-transaction}
     * 
     * @throws IOException Io Error
     */
    @Processor
    public void beginTransaction() throws IOException {
        SqlSession sqlSession = createSqlSessionForTransaction();
        threadLocalSession.set(sqlSession);
    }

    /**
     * Commits and closes the current transaction
     * 
     * {@sample.xml ../../../doc/mule-mybatis-module.xml.sample mybatis:commit-transaction}
     * 
     * @throws IOException Io Error
     */
    @Processor
    public void commitTransaction() throws IOException {
        SqlSession sqlSession = threadLocalSession.get();
        sqlSession.commit();
        sqlSession.close();
        threadLocalSession.set(null);
    }

    /**
     * Rollbacks and closes the current transaction
     * 
     * {@sample.xml ../../../doc/mule-mybatis-module.xml.sample mybatis:rollback-transaction}
     * 
     * @throws IOException Io Error
     */
    @Processor
    public void rollbackTransaction() throws IOException {
        SqlSession sqlSession = threadLocalSession.get();
        sqlSession.rollback();
        sqlSession.close();
        threadLocalSession.set(null);
    }

    /**
     * Execute a Mybatis mapper through interface mapper
      *
      * {@sample.xml ../../../doc/mule-mybatis-module.xml.sample mybatis:execute}
     * 
     * @param mapper Mapper class to use
     * @param method Method to invoke on the mapper
     * @param payload The payload
     * @param foreignKeyField If set, the id will be populated using the value form foreignKeyValue
     * @param foreignKeyValue If set, the id will be populated using method set + foreignKeyField + ()
     * @return Result of MyBatis call
     * @throws ClassNotFoundException Mapper not found
     * @throws IOException Io Error
     * @throws NoSuchMethodException Method on mapper not found 
     * @throws SecurityException Security Error
     * @throws InvocationTargetException Error invocating the method
     * @throws IllegalAccessException Error accessing method
     * @throws IllegalArgumentException Error in arguments passed to method
     */
    @Processor
    public Object execute(String mapper, String method, @Payload Object payload, @Optional String foreignKeyField,
            @Optional Object foreignKeyValue) throws ClassNotFoundException, IOException, SecurityException,
            NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        Class<?> mapperClass = muleContext.getExecutionClassLoader().loadClass(mapper);

        if (foreignKeyField != null && foreignKeyValue != null) {
            setForeignKey(payload, foreignKeyField, foreignKeyValue);
        }

        SqlSession sqlSession = createSqlSession();
        Object mapperInstance = sqlSession.getMapper(mapperClass);

        Method methodInstsance = mapperClass.getMethod(method, payload.getClass());
        Object result = methodInstsance.invoke(mapperInstance, payload);
        closeSqlSession(sqlSession);
        return result;

    }

    /**
     * Converts the name of an field into a setter method name, example personId will be converted to setPersonId
     * 
     * @param idField the name of the id field to be set
     * @return set + upper case of first character of idField + the rest of idField
     */
    protected String formatSetterName(String idField) {
        char firstCharacter = idField.charAt(0);
        firstCharacter = Character.toUpperCase(firstCharacter);

        return "set" + firstCharacter + idField.substring(1);
    }

    /**
     * Sets the idField with the value passed in idValue. First we get the setter method using reflection.
     * 
     * 
     * @param payload the object on which the id field will be set
     * @param idField the name of the id field
     * @param idValue the value of the id field
     * @throws NoSuchMethodException
     * @throws SecurityException
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws InvocationTargetException
     */
    protected void setForeignKey(Object payload, String idField, Object idValue) throws NoSuchMethodException,
            SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Method setter = payload.getClass().getMethod(formatSetterName(idField), idValue.getClass());
        setter.invoke(payload, idValue);
    }

    /**
     * Execute Mybatis select one function
     * 
     * {@sample.xml ../../../doc/mule-mybatis-module.xml.sample mybatis:select-one}
     * 
     * @param statement Fully qualified SQL statement ex: org.mybatis.example.BlogMapper.selectBlog
     * @param payload The parameter to the SQL statement
     * @return Result of MyBatis call
     * @throws IOException Io Error
     */
    @Processor
    public Object selectOne(String statement, @Payload Object payload) throws IOException {
        SqlSession sqlSession = createSqlSession();

        Object result = sqlSession.selectOne(statement, payload);
        closeSqlSession(sqlSession);
        return result;
    }

    /**
     * Execute Mybatis select list function
     * 
     * {@sample.xml ../../../doc/mule-mybatis-module.xml.sample mybatis:select-list}
     * 
     * @param statement Fully qualified SQL statement ex: org.mybatis.example.BlogMapper.selectBlog
     * @param payload The parameter to the SQL statement
     * @return Result of MyBatis call
     * @throws IOException Io Error
     */
    @Processor
    public Object selectList(String statement, @Payload Object payload) throws IOException {
        SqlSession sqlSession = createSqlSession();

        Object result = sqlSession.selectList(statement, payload);
        closeSqlSession(sqlSession);
        return result;
    }

    /**
     * Execute Mybatis select map function
     * 
     * {@sample.xml ../../../doc/mule-mybatis-module.xml.sample mybatis:select-map}
     * 
     * @param statement Fully qualified SQL statement ex: org.mybatis.example.BlogMapper.selectBlog
     * @param payload The parameter to the SQL statement
     * @param mapKey The key to use in the result map
     * @return Result of MyBatis call
     * @throws IOException Io Error
     */
    @Processor
    public Object selectMap(String statement, @Payload Object payload, String mapKey) throws IOException {
        SqlSession sqlSession = createSqlSession();

        Object result = sqlSession.selectMap(statement, payload, mapKey);
        closeSqlSession(sqlSession);
        return result;
    }

    /**
     * Execute Mybatis update function
     * 
     * {@sample.xml ../../../doc/mule-mybatis-module.xml.sample mybatis:update}
     * 
     * @param statement Fully qualified SQL statement ex: org.mybatis.example.BlogMapper.selectBlog
     * @param payload The parameter to the SQL statement
     * @return Result of MyBatis call
     * @throws IOException Io Error
     */
    @Processor
    public Object update(String statement, @Payload Object payload) throws IOException {
        SqlSession sqlSession = createSqlSession();

        Object result = sqlSession.update(statement, payload);
        closeSqlSession(sqlSession);
        return result;
    }

    /**
     * Execute Mybatis insert function
     * 
     * {@sample.xml ../../../doc/mule-mybatis-module.xml.sample mybatis:insert}
     * 
     * @param statement Fully qualified SQL statement ex: org.mybatis.example.BlogMapper.selectBlog
     * @param payload The parameter to the SQL statement
     * @return Result of MyBatis call
     * @throws IOException Io Error
     */
    @Processor
    public Object insert(String statement, @Payload Object payload) throws IOException {
        SqlSession sqlSession = createSqlSession();

        Object result = sqlSession.insert(statement, payload);
        closeSqlSession(sqlSession);
        return result;
    }

    /**
     * Execute Mybatis delete function
     * 
     * {@sample.xml ../../../doc/mule-mybatis-module.xml.sample mybatis:delete}
     * 
     * @param statement Fully qualified SQL statement ex: org.mybatis.example.BlogMapper.selectBlog
     * @param  Set if you want to commit immediately
     * @param payload The parameter to the SQL statement
     * @return Result of MyBatis call
     * @throws IOException Io Error
     */
    @Processor
    public Object delete(String statement, @Payload Object payload) throws IOException {
        SqlSession sqlSession = createSqlSession();

        Object result = sqlSession.delete(statement, payload);
        closeSqlSession(sqlSession);
        return result;
    }

    public String getConfigFile() {
        return configFile;
    }

    public void setConfigFile(String configFile) {
        this.configFile = configFile;
    }

    public SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }

    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    public void setMuleContext(MuleContext muleContext) {
        this.muleContext = muleContext;
    }

}