package org.keycloak.services.resources;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.KeycloakSessionFactory;
import org.keycloak.services.models.KeycloakTransaction;
import javax.ws.rs.core.Application;
/**
* Meant to be used as an inner class wrapper (I forget the pattern name, its been awhile).
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Transaction<T> {
protected KeycloakSession session;
protected KeycloakTransaction transaction;
protected boolean closeSession;
protected boolean created;
/**
* Pull KeycloakSession from @Context
*
* Will close session after finished
*
*/
public Transaction() {
this(true);
}
/**
* Pull KeycloakSession from @Context
*
* @param close whether to close the session or not after successful completion
*/
public Transaction(boolean close) {
this.session = ResteasyProviderFactory.getContextData(KeycloakSession.class);
if (session == null) {
KeycloakApplication app = (KeycloakApplication)ResteasyProviderFactory.getContextData(Application.class);
session = app.getFactory().createSession();
created = true;
ResteasyProviderFactory.pushContext(KeycloakSession.class, session);
}
transaction = session.getTransaction();
closeSession = close;
}
/**
* Creates and manages its own session.
*
* @param factory
*/
public Transaction(KeycloakSessionFactory factory) {
this.closeSession = true;
this.session = factory.createSession();
this.transaction = session.getTransaction();
}
protected void runImpl() {
}
/**
* Will not begin or end a transaction or close a session if the transaction was already active when called
*
*/
public void run() {
boolean wasActive = transaction.isActive();
if (!wasActive) transaction.begin();
try {
runImpl();
if (!wasActive && transaction.isActive()) transaction.commit();
} catch (RuntimeException e) {
if (!wasActive && transaction.isActive()) transaction.rollback();
if (created) closeSession = true;
throw e;
} finally {
if (!wasActive && closeSession) {
session.close();
}
}
}
protected T callImpl() {
return null;
}
/**
* Will not begin or end a transaction or close a session if the transaction was already active when called
*
*/
public T call() {
boolean wasActive = transaction.isActive();
if (!wasActive) transaction.begin();
try {
T rtn = callImpl();
if (!wasActive && transaction.isActive()) transaction.commit();
return rtn;
} catch (RuntimeException e) {
if (!wasActive && transaction.isActive()) transaction.rollback();
if (created) closeSession = true; // close if there was a failure
throw e;
} finally {
if (!wasActive && closeSession) session.close();
}
}
}