blob: 31531adfae5322aaaa9bc785cb2f45dcb749f113 [file] [log] [blame]
/*
*
* 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;
}
}