All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xuml.tools.model.compiler.runtime.actor.EntityActor Maven / Gradle / Ivy

package xuml.tools.model.compiler.runtime.actor;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;

import akka.actor.UntypedActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import xuml.tools.model.compiler.runtime.Entity;
import xuml.tools.model.compiler.runtime.QueuedSignal;
import xuml.tools.model.compiler.runtime.SignalProcessorListener;
import xuml.tools.model.compiler.runtime.SignalProcessorListenerDoesNothing;
import xuml.tools.model.compiler.runtime.message.CloseEntityActor;
import xuml.tools.model.compiler.runtime.message.Signal;
import xuml.tools.model.compiler.runtime.message.StopEntityActor;

public class EntityActor extends UntypedActor {

    private EntityManagerFactory emf;
    private final LoggingAdapter log;
    private SignalProcessorListener listener = SignalProcessorListenerDoesNothing.getInstance();

    public EntityActor() {
        log = Logging.getLogger(getContext().system(), this);
    }

    @Override
    public void onReceive(Object message) throws Exception {
        log.debug("received message {}", message.getClass().getName());
        if (message instanceof EntityManagerFactory)
            handleMessage((EntityManagerFactory) message);
        else if (message instanceof SignalProcessorListener)
            listener = (SignalProcessorListener) message;
        else if (message instanceof Signal) {
            handleMessage((Signal) message);
        } else if (message instanceof StopEntityActor) {
            getContext().stop(getSelf());
        }
    }

    @SuppressWarnings("unchecked")
    private void handleMessage(@SuppressWarnings("rawtypes") Signal signal) {
        if (emf != null) {
            // otherwise perform the event on the entity after it has been
            // refreshed within the scope of the current entity manager

            EntityManager em = null;
            EntityTransaction tx = null;
            try {
                listener.beforeProcessing(signal, this);
                em = emf.createEntityManager();
                tx = em.getTransaction();
                tx.begin();
                log.debug("started transaction");
                Entity en;
                // TODO remove commented out code
                // synchronized (signal) {
                // // because signal is not an immutable object make sure we
                // // have its latest values
                // en = signal.getEntity();
                // }
                // entity = em.merge(en);
                // log.debug("merged");
                // em.refresh(entity);
                en = (Entity) em.find(signal.getEntityClass(), signal.getEntityId());
                log.debug("calling event {} on entity id = ",
                        signal.getEvent().getClass().getSimpleName(), signal.getEntityId());
                en.helper().setEntityManager(em);
                en.event(signal.getEvent());
                // en.helper().setEntityManager(em);
                log.debug("removing signal from persistence signalId={}, entityId={}",
                        signal.getId(), signal.getEntityId());
                int countDeleted = em
                        .createQuery("delete from " + QueuedSignal.class.getSimpleName()
                                + " where id=:id")
                        .setParameter("id", signal.getId()).executeUpdate();
                if (countDeleted == 0)
                    throw new RuntimeException("queued signal not deleted: " + signal.getId());
                tx.commit();
                log.debug("committed");
                listener.afterProcessing(signal, this);
                em.close();
                // TODO do this in finally?
                en.helper().setEntityManager(null);
                // only after successful commit do we send the signals to other
                // entities made during onEntry procedure.
                en.helper().sendQueuedSignals();
            } catch (RuntimeException e) {
                try {
                    if (tx != null && tx.isActive())
                        tx.rollback();
                    if (em != null && em.isOpen())
                        em.close();
                    listener.failure(signal, e, this);
                } catch (RuntimeException e2) {
                    log.error(e2.getMessage(), e2);
                    throw e;
                }
            } finally {
                // give RootActor a chance to dispose of this actor
                getSender().tell(new CloseEntityActor(signal.getEntityUniqueId()), getSelf());
            }
        }
    }

    private void handleMessage(EntityManagerFactory message) {
        this.emf = message;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy