| /* |
| * |
| * Copyright (c) 2011 - 2017 - Loetz GmbH & Co KG, 69115 Heidelberg, Germany |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Initial contribution: |
| * Loetz GmbH & Co. KG |
| * |
| */ |
| package org.eclipse.osbp.dsl.dto.lib.services.impl; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.naming.InitialContext; |
| import javax.naming.NamingException; |
| import javax.persistence.EntityManager; |
| import javax.persistence.EntityManagerFactory; |
| import javax.persistence.EntityTransaction; |
| import javax.transaction.HeuristicMixedException; |
| import javax.transaction.HeuristicRollbackException; |
| import javax.transaction.NotSupportedException; |
| import javax.transaction.RollbackException; |
| import javax.transaction.SystemException; |
| import javax.transaction.UserTransaction; |
| |
| import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent; |
| import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent.EventDispatcherCommand; |
| import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent.EventDispatcherDataTag; |
| import org.eclipse.osbp.runtime.common.event.IEventDispatcher; |
| import org.eclipse.osbp.runtime.common.session.ISessionManager; |
| import org.eclipse.osbp.runtime.common.session.ITransactionHandler; |
| import org.eclipse.persistence.internal.jpa.EntityManagerImpl; |
| import org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork; |
| import org.eclipse.persistence.sessions.SessionEvent; |
| import org.eclipse.persistence.sessions.SessionEventAdapter; |
| import org.eclipse.persistence.sessions.changesets.ObjectChangeSet; |
| import org.eclipse.persistence.sessions.changesets.UnitOfWorkChangeSet; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class TransactionHandler extends SessionEventAdapter implements ITransactionHandler { |
| protected static Logger LOGGER = LoggerFactory.getLogger(TransactionHandler.class); |
| /** The em. */ |
| private EntityManager em; |
| |
| /** The affected. */ |
| private List<Object> affected = new ArrayList<>(); |
| |
| /** The session manager. */ |
| private final ISessionManager sessionManager; |
| |
| /** The is jta. */ |
| private boolean isJTA; |
| |
| /** The ut. */ |
| private UserTransaction ut; |
| |
| /** The txn. */ |
| private EntityTransaction txn; |
| |
| /** |
| * Instantiates a new transaction. |
| * |
| * @param em |
| * the em |
| */ |
| public TransactionHandler(EntityManagerFactory emf, ISessionManager sessionManager) { |
| super(); |
| this.em = emf.createEntityManager(); |
| this.sessionManager = sessionManager; |
| ((EntityManagerImpl) em).getActiveSession().getEventManager().addListener(this); |
| isJTA = isJTA(em); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.runtime.common.session.ITransactionHandler#getEntityManager() |
| */ |
| @Override |
| public EntityManager getEntityManager() { |
| return em; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.runtime.common.session.ITransactionHandler#isJTA(javax.persistence.EntityManager) |
| */ |
| @Override |
| public boolean isJTA(EntityManager em) { |
| try { |
| em.getTransaction(); |
| } catch (Exception e) { |
| return true; |
| } |
| return false; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.runtime.common.session.ITransactionHandler#begin() |
| */ |
| @Override |
| public void begin() throws NamingException, NotSupportedException, SystemException { |
| if (isJTA) { |
| ut = (UserTransaction) new InitialContext().lookup("osgi:service/javax.transaction.UserTransaction"); |
| |
| // start the user transaction |
| ut.begin(); |
| em.joinTransaction(); |
| } else { |
| txn = em.getTransaction(); |
| txn.begin(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.runtime.common.session.ITransactionHandler#commit() |
| */ |
| @Override |
| public void commit() throws IllegalStateException, SecurityException, HeuristicMixedException, HeuristicRollbackException, RollbackException, SystemException { |
| if (isJTA) { |
| ut.commit(); |
| } else { |
| txn.commit(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.runtime.common.session.ITransactionHandler#rollback() |
| */ |
| @Override |
| public void rollback() throws IllegalStateException, SecurityException, SystemException { |
| if (isJTA) { |
| ut.rollback(); |
| } else { |
| txn.rollback(); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.persistence.sessions.SessionEventAdapter# |
| * postCommitUnitOfWork (org.eclipse.persistence.sessions.SessionEvent) |
| */ |
| @SuppressWarnings("unchecked") |
| @Override |
| public void postCommitUnitOfWork(SessionEvent event) { |
| RepeatableWriteUnitOfWork uow = (RepeatableWriteUnitOfWork) event.getSource(); |
| UnitOfWorkChangeSet uowChangeSet = uow.getUnitOfWorkChangeSet(); |
| if(uowChangeSet != null) { |
| Map<ObjectChangeSet, ObjectChangeSet> changeSet = uowChangeSet.getAllChangeSets(); |
| processChangeSet(changeSet, EventDispatcherCommand.SAVE); |
| // delete |
| Map<ObjectChangeSet, ObjectChangeSet> deletedSet = uowChangeSet.getDeletedObjects(); |
| processChangeSet(deletedSet, EventDispatcherCommand.DELETE); |
| } |
| } |
| |
| private void processChangeSet(Map<ObjectChangeSet, ObjectChangeSet> changeSet, |
| EventDispatcherCommand eventCmd) { |
| for (ObjectChangeSet object : changeSet.values()) { |
| affected.add(object); |
| // insert or update |
| LOGGER.debug("affected:{} id:{}", object.getClassName(), object.getId()); |
| sessionManager.asyncAll(s -> { |
| IEventDispatcher dispatcher = s.get(IEventDispatcher.class); |
| if (dispatcher != null) { |
| EventDispatcherEvent evnt; |
| if (object.isNew()) { |
| evnt = new EventDispatcherEvent(null, EventDispatcherCommand.REFRESH, object.getClassName(), "DTOService"); |
| } else { |
| evnt = new EventDispatcherEvent(null, eventCmd, object.getClassName(), "DTOService"); |
| } |
| evnt.addItem(EventDispatcherDataTag.ID, object.getId()); |
| dispatcher.sendEvent(evnt); |
| } |
| return null; |
| }); |
| } |
| } |
| |
| /** |
| * This method is called when information about an Transaction which was |
| * previously requested using an asynchronous interface becomes |
| * available. |
| */ |
| public void dispose() { |
| ((EntityManagerImpl) em).getActiveSession().getEventManager().removeListener(this); |
| em.close(); |
| em = null; |
| } |
| } |