Package es.twentymobile.mule.modules.jpa

Source Code of es.twentymobile.mule.modules.jpa.JpaConnector

/**
* This file was automatically generated by the Mule Development Kit
*/
package es.twentymobile.mule.modules.jpa;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;

import org.mule.api.annotations.Connector;
import org.mule.api.annotations.Connect;
import org.mule.api.annotations.Source;
import org.mule.api.annotations.ValidateConnection;
import org.mule.api.annotations.ConnectionIdentifier;
import org.mule.api.annotations.Disconnect;
import org.mule.api.ConnectionException;
import org.mule.api.MuleContext;
import org.mule.api.annotations.Configurable;
import org.mule.api.annotations.Processor;
import org.mule.api.annotations.param.Default;
import org.mule.api.annotations.param.Optional;
import org.mule.api.callback.SourceCallback;
import org.mule.api.context.MuleContextAware;
import org.mule.api.execution.ExecutionCallback;
import org.mule.api.execution.ExecutionTemplate;
import org.mule.api.transaction.Transaction;
import org.mule.api.transaction.TransactionConfig;
import org.mule.api.transaction.TransactionException;
import org.mule.execution.TransactionalExecutionTemplate;
import org.mule.transaction.MuleTransactionConfig;
import org.mule.transaction.TransactionCoordination;
import org.mule.transaction.XaTransaction;
import org.mule.transaction.XaTransactionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import es.twentymobile.mule.modules.jpa.dsl.CustomJPAQuery;
import es.twentymobile.mule.modules.jpa.dsl.JPACountQueryResult;
import es.twentymobile.mule.modules.jpa.exceptions.JpaException;
import es.twentymobile.mule.modules.jpa.strategy.EntityManagerStrategy;
import es.twentymobile.mule.modules.jpa.strategy.EntityManagerStrategyFactory;
import es.twentymobile.mule.modules.jpa.strategy.EntityManagerStrategyFactory.ReceiveAction;
import es.twentymobile.mule.modules.jpa.xa.JpaXaResource;
import es.twentymobile.mule.modules.jpa.xa.JpaXaResourceForTomcatAndOpenJpa;

/**
* Cloud Connector
*
* @author Jose Maria Alvarez Fernandez at 20:20 Mobile Spain, S.A.
* @author Adolfo Gonzalaez Blazquez at 20:20 Mobile Spain, S.A.
*/
@Connector(name = "jpa", schemaVersion = "1.0")
public class JpaConnector implements MuleContextAware {

  private static final String DEFAULT_TRANSACTION_TIMEOUT = "60000";

  /**
   * The entityManagerFactory to use to create entityManagers
   */
  @Configurable
  private EntityManagerFactory entityManagerFactory;

  /**
   * The default max results to return from select queries.
   */
  @Configurable
  private Integer defaultMaxResults;

  /**
   * Property to set when the connection pool is not managed, and you want to
   * use XA Transactions. Depends on OpenJPA. Other implementations may be
   * used Overriding <a>es.twentymobile.mule.modules.jpa.xa.JpaXaResource</a>
   * class.
   */
  @Configurable
  @Optional
  @Default("false")
  private Boolean isUnmanagedPoolAndOpenJpa;

  /**
   * The properties of JPA Entity Manager
   */
  @Configurable
  @Optional
  private Map<String, Object> jpaProperties;

  @Inject
  private MuleContext muleContext;

  private static Logger log = LoggerFactory.getLogger(JpaConnector.class);

  /**
   * @return the isUnmanagedPoolAndOpenJpa
   */
  public Boolean getIsUnmanagedPoolAndOpenJpa() {
    return isUnmanagedPoolAndOpenJpa;
  }

  /**
   * @param isUnmanagedPoolAndOpenJpa
   *            the isUnmanagedPoolAndOpenJpa to set
   */
  public void setIsUnmanagedPoolAndOpenJpa(Boolean isUnmanagedPoolAndOpenJpa) {
    this.isUnmanagedPoolAndOpenJpa = isUnmanagedPoolAndOpenJpa;
  }

  /**
   * @return the jpaProperties
   */
  public Map<String, Object> getJpaProperties() {
    return jpaProperties;
  }

  /**
   * @param jpaProperties
   *            the jpaProperties to set
   */
  public void setJpaProperties(Map<String, Object> jpaProperties) {
    this.jpaProperties = jpaProperties;
  }

  public Integer getDefaultMaxResults() {
    return defaultMaxResults;
  }

  public void setDefaultMaxResults(Integer defaultMaxResults) {
    this.defaultMaxResults = defaultMaxResults;
  }

  public EntityManagerFactory getEntityManagerFactory() {
    return entityManagerFactory;
  }

  public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
    this.entityManagerFactory = entityManagerFactory;
  }

  /**
   * Connect
   *
   * @throws ConnectionException
   */
  @Connect
  public void connect() throws ConnectionException {
  }

  /**
   * Disconnect
   */
  @Disconnect
  public void disconnect() {
    if (entityManagerFactory != null && entityManagerFactory.isOpen()) {
      entityManagerFactory.close();
    }
  }

  /**
   * Are we connected
   */
  @ValidateConnection
  public boolean isConnected() {
    return true;
  }

  /**
   * Are we connected
   */
  @ConnectionIdentifier
  public String connectionId() {
    return "001";
  }

  /**
   * Query database as message source
   *
   * @param query
   *            the query to execute
   * @param maxResults
   *            the maximum number of results to return
   * @param startPosition
   *            the position of the first result to retrieve
   * @param startTransaction
   *            if we must start a transaction
   * @param transactionTimeout
   *            the transaction timeout in miliseconds
   * @param callback
   *            the callback to start the process flow
   * @return the objects result of the query
   * @throws JpaException
   *             if something goes wrong
   *
   *             {@sample.xml ../../../doc/jpa-connector.xml.sample
   *             jpa:query-database}
   */
  @Source
  public Object queryDatabase(final String query, Boolean startTransaction, @Optional @Default(DEFAULT_TRANSACTION_TIMEOUT) Integer transactionTimeout,
      final SourceCallback callback, @Optional String maxResults, @Optional String startPosition) throws JpaException {

    final Integer maxRes = parseMaxResults(maxResults);
    final Integer startPos = parseStartPosition(startPosition);

    if (startTransaction) {
      TransactionConfig config = new MuleTransactionConfig();
      config.setFactory(new XaTransactionFactory());
      config.setAction(TransactionConfig.ACTION_ALWAYS_BEGIN);
      ExecutionTemplate<Object> executionTemplate = TransactionalExecutionTemplate.createTransactionalExecutionTemplate(muleContext, config);
      try {
        return executionTemplate.execute(new ExecutionCallback<Object>() {
          public Object process() throws Exception {
            return callback.process(executeJpaQuery(query, Boolean.FALSE, null, maxRes, startPos));
          }
        });
      } catch (Exception e) {
        log.error("Error processing jpa query " + query + " with transaction", e);
        throw new JpaException("Error processing jpa query", e);
      }
    } else {
      try {
        return callback.process(executeJpaQuery(query, Boolean.FALSE, null, maxRes, startPos));
      } catch (Exception e) {
        log.error("Error processing jpa query " + query + " without transaction", e);
        throw new JpaException("Error processing jpa query", e);
      }
    }

  }

  private Object executeJpaQuery(String query, Boolean singleResult, Map<String, Object> parameters, Integer maxResults, Integer startPosition)
      throws JpaException {
    EntityManager em = null;
    EntityTransaction etx = null;
    try {
      Transaction tx = TransactionCoordination.getInstance().getTransaction();
      em = getEntityManager();
      if (tx == null) {
        log.info("No transaction available, so open a new transaction");
        etx = em.getTransaction();
      }
      if (!em.isOpen()) {
        throw new Exception("Cannot open entityManager.");
      }
      if (etx != null && !etx.isActive()) {
        etx.begin();
      }
      Object resultSet = null;
      Query jpaQuery = em.createQuery(query);

      if (maxResults != 0) {
        jpaQuery.setMaxResults(maxResults);
      }

      if (startPosition != null) {
        jpaQuery.setFirstResult(startPosition);
      }

      if (parameters != null) {
        for (String key : parameters.keySet()) {
          jpaQuery.setParameter(key, parameters.get(key));
        }
      }
      if (singleResult) {
        resultSet = jpaQuery.getSingleResult();
      } else {
        resultSet = jpaQuery.getResultList();
      }
      return resultSet;
    } catch (Exception e) {
      log.error("Error querying with JPA Transport", e);
      if (etx != null && etx.isActive()) {
        etx.rollback();
      }
      throw new JpaException("Error querying with JPA. Query: " + query, e);
    }
  }

  /**
   * Persist object in database
   *
   * @param object
   *            the object(s) to persist
   * @param flush
   *            if flush() must be invoked after the operation
   * @return the objects persisted
   * @throws JpaException
   *             if something fails
   *
   *             {@sample.xml ../../../doc/jpa-connector.xml.sample
   *             jpa:persist}
   */
  @Processor
  public Object persist(Object object, @Optional Boolean flush) throws JpaException {
    EntityManagerStrategy emStrategy;
    if (flush != null) {
      emStrategy = EntityManagerStrategyFactory.createEntityManagerCommand(getEntityManager(), ReceiveAction.PERSIST, flush);
    } else {
      emStrategy = EntityManagerStrategyFactory.createEntityManagerCommand(getEntityManager(), ReceiveAction.PERSIST, Boolean.FALSE);
    }
    return executeStrategy(emStrategy, object);
  }

  /**
   * Merge object in database
   *
   * @param object
   *            the object(s) to merge
   * @param flush
   *            if flush() must be invoked after the operation
   * @return the objects merged
   * @throws JpaException
   *             if something fails
   *
   *             {@sample.xml ../../../doc/jpa-connector.xml.sample jpa:merge}
   */
  @Processor
  public Object merge(Object object, @Optional Boolean flush) throws JpaException {
    EntityManagerStrategy emStrategy;
    if (flush != null) {
      emStrategy = EntityManagerStrategyFactory.createEntityManagerCommand(getEntityManager(), ReceiveAction.MERGE, flush);
    } else {
      emStrategy = EntityManagerStrategyFactory.createEntityManagerCommand(getEntityManager(), ReceiveAction.MERGE, Boolean.FALSE);
    }
    return executeStrategy(emStrategy, object);
  }

  /**
   * Delete object from database
   *
   * @param object
   *            the object(s) to delete
   * @param flush
   *            if flush() must be invoked after the operation
   * @return the objects del
   * @throws JpaException
   *             if something fails
   *
   *             {@sample.xml ../../../doc/jpa-connector.xml.sample
   *             jpa:delete}
   */
  @Processor
  public void delete(Object object, @Optional Boolean flush) throws JpaException {
    EntityManagerStrategy emStrategy;
    if (flush != null) {
      emStrategy = EntityManagerStrategyFactory.createEntityManagerCommand(getEntityManager(), ReceiveAction.DELETE, flush);
    } else {
      emStrategy = EntityManagerStrategyFactory.createEntityManagerCommand(getEntityManager(), ReceiveAction.DELETE, Boolean.FALSE);
    }
    executeStrategy(emStrategy, object);
  }

  /**
   * Queries the database and populate the payload with the result
   *
   * @param query
   *            the query to execute
   * @param singleResult
   *            if we must return a single result
   * @param maxResults
   *            the maximum number of results to return
   * @param startPosition
   *            the position of the first result to retrieve
   * @param parameters
   *            if the query has parameters, parameters names and values
   * @return the List of objects
   * @throws JpaException
   *             if something fails
   *
   *
   *             {@sample.xml ../../../doc/jpa-connector.xml.sample
   *             jpa:execute-query}
   */
  @Processor
  public Object executeQuery(String query, @Optional Map<String, Object> parameters, @Optional Boolean singleResult, @Optional String maxResults,
      @Optional String startPosition) throws JpaException {

    Integer maxRes = parseMaxResults(maxResults);
    Integer startPos = parseStartPosition(startPosition);

    if (singleResult == null) {
      return executeJpaQuery(query, Boolean.FALSE, parameters, maxRes, startPos);
    } else {
      return executeJpaQuery(query, singleResult, parameters, maxRes, startPos);
    }
  }

  /**
   * Queries the database based on a dynamic DSL query and populate the
   * payload with the result
   *
   * @param jpaQuery
   *            the object that contains the query
   * @param maxResults
   *            the maximum number of results to return
   * @param singleResult
   *            if we must return a list or a single result object (default is
   *            false)
   * @param distinct
   *            if we must add distinct to the restrictions
   * @param returnCount
   *            if we must return the result and the count without limit of
   *            the possibly limited result
   *
   * @return the List of objects
   *
   *         {@sample.xml ../../../doc/jpa-connector.xml.sample
   *         jpa:execute-dsl-query}
   */
  @Processor
  public Object executeDslQuery(QueryDslQuery jpaQuery, @Optional String maxResults, @Optional Boolean singleResult, @Optional Boolean distinct,
      @Optional Boolean returnCount) throws JpaException {
    EntityManager em = null;
    EntityTransaction etx = null;
    Transaction tx = TransactionCoordination.getInstance().getTransaction();

    Integer maxRes = parseMaxResults(maxResults);

    try {
      em = getEntityManager();
      if (tx == null) {
        log.info("No transaction available, so open a new transaction");
        etx = em.getTransaction();
      }
      if (!em.isOpen()) {
        throw new Exception("Cannot open entityManager.");
      }
      if (etx != null && !etx.isActive()) {
        etx.begin();
      }
      CustomJPAQuery query = jpaQuery.getQuery().clone(em);
      if (distinct != null && distinct.equals(Boolean.TRUE)) {
        query = query.distinct();
      }
      Object result;
      if (singleResult == null || singleResult.equals(Boolean.FALSE)) {
        if (maxRes != 0) {
          if (!returnCount) {
            result = query.limit(maxRes).list(jpaQuery.getBasePath());
          } else {
            JPACountQueryResult queryResult = new JPACountQueryResult();
            queryResult.setResult(query.limit(maxRes).list(jpaQuery.getBasePath()));
            queryResult.setCount(query.count());
            result = queryResult;
          }
        } else {
          result = query.list(jpaQuery.getBasePath());
        }
      } else {
        result = query.uniqueResult(jpaQuery.getBasePath());
      }
      if (etx != null && etx.isActive()) {
        etx.commit();
      }
      return result;
    } catch (Exception e) {
      log.error("Error executing JPA query", e);
      if (etx != null && etx.isActive()) {
        etx.rollback();
      }
      throw new JpaException("Error querying database with QueryDSL: " + jpaQuery.getQuery(), e);
    }
  }

  private Object executeStrategy(EntityManagerStrategy emStrategy, Object payload) throws JpaException {
    EntityManager em = null;
    EntityTransaction etx = null;

    Transaction tx = TransactionCoordination.getInstance().getTransaction();
    try {
      em = emStrategy.getEntityManager();
      if (tx == null) {
        log.info("No transaction available, so open a new transaction");
        etx = em.getTransaction();
      }
      if (!em.isOpen()) {
        throw new Exception("Cannot open entityManager.");
      }
      if (etx != null && !etx.isActive()) {
        etx.begin();
      }
      Object result = null;
      if (payload instanceof List) {
        log.debug("payload type is list.");
        List<?> payloadList = (List<?>) payload;
        List<Object> resultList = new ArrayList<Object>();
        for (Iterator<?> payloadIter = payloadList.iterator(); payloadIter.hasNext();) {
          Object entity = payloadIter.next();
          log.debug("entity is " + entity.getClass() + ".");
          Object iterResult = emStrategy.execute(entity);
          resultList.add((Object) iterResult);
        }
        result = resultList;
      } else {
        log.debug("entity is " + payload.getClass() + ".");
        result = emStrategy.execute(payload);
      }
      if (etx != null && etx.isActive()) {
        etx.commit();
      }
      return result;
    } catch (Exception e) {
      log.error("Error executing JPA query", e);
      if (etx != null && etx.isActive()) {
        etx.rollback();
      }
      throw new JpaException("Error executing jpa strategy " + emStrategy, e);
    }

  }

  private EntityManager getEntityManager() {
    Transaction tx = TransactionCoordination.getInstance().getTransaction();
    if (tx != null) {
      if (tx.hasResource(entityManagerFactory)) {
        log.debug("Retrieving session from current transaction");
        Object r = tx.getResource(entityManagerFactory);
        if (r instanceof JpaXaResource) {
          return ((JpaXaResource) r).getEntityManager();
        } else {
          return (EntityManager) r;
        }
      }
    }
    log.debug("Retrieving new entityManager from factory");
    EntityManager entityManager;
    if (jpaProperties != null && !jpaProperties.isEmpty()) {
      entityManager = entityManagerFactory.createEntityManager(jpaProperties);
    } else {
      entityManager = entityManagerFactory.createEntityManager();
    }
    if (tx != null) {
      log.debug("Binding session to current transaction");
      try {
        Object r;
        if (tx instanceof XaTransaction) {
          if (isUnmanagedPoolAndOpenJpa) {
            r = new JpaXaResourceForTomcatAndOpenJpa(entityManager);
          } else {
            r = new JpaXaResource(entityManager);
          }
        } else {
          r = entityManager;
        }
        tx.bindResource(entityManagerFactory, r);
      } catch (TransactionException e) {
        throw new RuntimeException("Could not bind connection to current transaction", e);
      }
    }
    return entityManager;
  }

  private Integer parseMaxResults(String maxResults) {
    Integer maxRes = getDefaultMaxResults();
    try {
      maxRes = Integer.valueOf(maxResults);
    } catch (NumberFormatException e) {
      log.debug("Invalid maxResults value. Setting default connector value " + getDefaultMaxResults());
    }
    return maxRes;
  }

  private Integer parseStartPosition(String startPosition) {
    Integer startPos = null;
    try {
      startPos = Integer.valueOf(startPosition);
    } catch (NumberFormatException e) {
      log.debug("Invalid startPosition value. Setting default to null");
    }
    return startPos;
  }

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

}
TOP

Related Classes of es.twentymobile.mule.modules.jpa.JpaConnector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.