Last active
December 27, 2015 04:09
-
-
Save picodotdev/7264990 to your computer and use it in GitHub Desktop.
Transacciones en Apache Tapestry
http://elblogdepicodev.blogspot.com/2013/11/transacciones-en-apache-tapestry.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services; | |
... | |
public class AppModule { | |
public static void bind(ServiceBinder binder) { | |
... | |
// Servicios para la gestión de transacciones | |
binder.bind(HibernateSessionManager.class, HibernateSessionManagerImpl.class).scope(ScopeConstants.PERTHREAD).withId("AppHibernateSessionManager"); | |
binder.bind(TransactionAdvisor.class, TransactionAdvisorImpl.class); | |
binder.bind(TransactionService.class, HibernateTransactionServiceImpl.class).scope(ScopeConstants.PERTHREAD); | |
... | |
} | |
public static void contributeServiceOverride(MappedConfiguration<Class,Object> configuration, @Local HibernateSessionManager sessionManager) { | |
configuration.add(HibernateSessionManager.class, sessionManager); | |
} | |
... | |
/** | |
* Dar soporte transaccional a los servicios con una interfaz que cumplan el patrón (los advices se aplican a los métodos de una interfaz). | |
*/ | |
@Match({ "*DAO" }) | |
public static void adviseTransaction(TransactionAdvisor advisor, MethodAdviceReceiver receiver) { | |
advisor.addAdvice(receiver); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ git clone git://github.com/picodotdev/elblogdepicodev.git | |
$ cd elblogdepicodev/PlugInTapestry | |
$ ./gradlew tomcatRun | |
# Abrir en el navegador http://localhost:8080/PlugInTapestry/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.transaction; | |
import org.apache.tapestry5.hibernate.HibernateSessionManager; | |
import org.apache.tapestry5.hibernate.HibernateSessionSource; | |
import org.apache.tapestry5.ioc.services.PerthreadManager; | |
import org.hibernate.Session; | |
public class HibernateSessionManagerImpl implements HibernateSessionManager { | |
private Session session; | |
public HibernateSessionManagerImpl(HibernateSessionSource source, PerthreadManager manager) { | |
this.session = source.create(); | |
manager.addThreadCleanupCallback(new Runnable() { | |
@Override | |
public void run() { | |
cleanup(); | |
} | |
}); | |
} | |
public void abort() { | |
session.getTransaction().rollback(); | |
} | |
public void commit() { | |
session.getTransaction().commit(); | |
} | |
public Session getSession() { | |
return session; | |
} | |
private void cleanup() { | |
session.close(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.transaction; | |
import java.sql.Connection; | |
import java.sql.SQLException; | |
import java.util.Stack; | |
import org.apache.tapestry5.ioc.services.PerthreadManager; | |
import org.hibernate.Session; | |
import org.hibernate.Transaction; | |
import org.hibernate.jdbc.Work; | |
public class HibernateTransactionServiceImpl implements TransactionService { | |
private Session session; | |
private Stack<Transaction> transactionStack; | |
public HibernateTransactionServiceImpl(Session session, PerthreadManager perthreadManager) { | |
this.session = session; | |
this.transactionStack = new Stack<Transaction>(); | |
perthreadManager.addThreadCleanupCallback(new Runnable() { | |
@Override | |
public void run() { | |
cleanup(); | |
} | |
}); | |
} | |
public boolean beginIfNoPresent(TransactionDefinition definition) { | |
if (isWithinTransaction()) { | |
return false; | |
} | |
begin(definition); | |
return true; | |
} | |
public void begin(TransactionDefinition definition) { | |
Transaction transaction = session.beginTransaction(); | |
configure(session, transaction, definition); | |
transactionStack.push(transaction); | |
} | |
public void commit() { | |
if (isWithinTransaction()) { | |
transactionStack.pop().commit(); | |
} | |
} | |
public void rollback() { | |
if (isWithinTransaction()) { | |
transactionStack.pop().rollback(); | |
} | |
} | |
public boolean isWithinTransaction() { | |
return !transactionStack.empty(); | |
} | |
private void cleanup() { | |
for (Transaction transaction : transactionStack) { | |
transaction.rollback(); | |
} | |
} | |
private void configure(Session session, Transaction transaction, final TransactionDefinition definition) { | |
if (definition.getReadOnly() != null) { | |
session.setDefaultReadOnly(definition.getReadOnly()); | |
} | |
if (definition.getTimeout() != null) { | |
transaction.setTimeout(definition.getTimeout()); | |
} | |
session.doWork(new Work() { | |
public void execute(Connection connection) throws SQLException { | |
if (definition.getReadOnly() != null) { | |
connection.setReadOnly(definition.getReadOnly()); | |
} | |
if (definition.getIsolation() != null) { | |
connection.setTransactionIsolation(definition.getIsolation().intValue()); | |
} | |
} | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.transaction; | |
import org.apache.tapestry5.plastic.MethodAdvice; | |
import org.apache.tapestry5.plastic.MethodInvocation; | |
public class MandatoryTransactionAdvice implements MethodAdvice { | |
private TransactionService service; | |
public MandatoryTransactionAdvice(TransactionService service) { | |
this.service = service; | |
} | |
public void advise(MethodInvocation invocation) { | |
if (!service.isWithinTransaction()) { | |
throw new RuntimeException("Debe haber una transacción"); | |
} | |
invocation.proceed(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.transaction; | |
import org.apache.tapestry5.plastic.MethodAdvice; | |
import org.apache.tapestry5.plastic.MethodInvocation; | |
public class NestedTransactionAdvice implements MethodAdvice { | |
private TransactionDefinition definition; | |
private TransactionService service; | |
public NestedTransactionAdvice(TransactionDefinition definition, TransactionService service) { | |
this.definition = definition; | |
this.service = service; | |
} | |
public void advise(MethodInvocation invocation) { | |
try { | |
service.begin(definition); | |
invocation.proceed(); | |
service.commit(); | |
} catch (Exception e) { | |
service.rollback(); | |
throw e; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.transaction; | |
import org.apache.tapestry5.plastic.MethodAdvice; | |
import org.apache.tapestry5.plastic.MethodInvocation; | |
public class NeverTransactionAdvice implements MethodAdvice { | |
private TransactionService service; | |
public NeverTransactionAdvice(TransactionService service) { | |
this.service = service; | |
} | |
public void advise(MethodInvocation invocation) { | |
if (service.isWithinTransaction()) { | |
throw new RuntimeException("Hay una transacción activa y se require ninguna"); | |
} | |
invocation.proceed(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.transaction; | |
public enum Propagation { | |
REQUIRED, SUPPORTS, NEVER, NESTED, MANDATORY | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.transaction; | |
import org.apache.tapestry5.plastic.MethodAdvice; | |
import org.apache.tapestry5.plastic.MethodInvocation; | |
public class RequiredTransactionAdvice implements MethodAdvice { | |
private TransactionDefinition definition; | |
private TransactionService service; | |
public RequiredTransactionAdvice(TransactionDefinition definition, TransactionService service) { | |
this.definition = definition; | |
this.service = service; | |
} | |
public void advise(MethodInvocation invocation) { | |
boolean isNew = service.beginIfNoPresent(definition); | |
try { | |
invocation.proceed(); | |
if (isNew) { | |
service.commit(); | |
} | |
} catch (Exception e) { | |
if (isNew) { | |
service.rollback(); | |
} | |
throw e; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.transaction; | |
import org.apache.tapestry5.ioc.MethodAdviceReceiver; | |
public interface TransactionAdvisor { | |
void addAdvice(MethodAdviceReceiver methodAdviceReceiver); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.transaction; | |
import java.lang.reflect.Method; | |
import org.apache.tapestry5.ioc.MethodAdviceReceiver; | |
public class TransactionAdvisorImpl implements TransactionAdvisor { | |
private TransactionService service; | |
public TransactionAdvisorImpl(TransactionService service) { | |
this.service = service; | |
} | |
public void addAdvice(final MethodAdviceReceiver receiver) { | |
for (Method method : receiver.getInterface().getMethods()) { | |
Transactional transactional = method.getAnnotation(Transactional.class); | |
if (transactional != null) { | |
adviceMethod(buildTransactionDefinition(transactional), method, receiver); | |
} | |
} | |
} | |
private void adviceMethod(TransactionDefinition definition, Method method, MethodAdviceReceiver receiver) { | |
switch (definition.getPropagation()) { | |
case REQUIRED: | |
receiver.adviseMethod(method, new RequiredTransactionAdvice(definition, service)); | |
break; | |
case NESTED: | |
receiver.adviseMethod(method, new NestedTransactionAdvice(definition, service)); | |
break; | |
case MANDATORY: | |
receiver.adviseMethod(method, new MandatoryTransactionAdvice(service)); | |
break; | |
case NEVER: | |
receiver.adviseMethod(method, new NeverTransactionAdvice(service)); | |
break; | |
case SUPPORTS: | |
break; | |
} | |
} | |
private TransactionDefinition buildTransactionDefinition(Transactional transactional) { | |
return new TransactionDefinition(transactional.propagation(), (transactional.isolation() == -1) ? null : transactional.isolation(), transactional.readonly(), | |
(transactional.timeout() == -1) ? null : transactional.timeout()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.transaction; | |
import java.lang.annotation.ElementType; | |
import java.lang.annotation.Retention; | |
import java.lang.annotation.RetentionPolicy; | |
import java.lang.annotation.Target; | |
@Retention(RetentionPolicy.RUNTIME) | |
@Target({ ElementType.METHOD }) | |
public @interface Transactional { | |
Propagation propagation() default Propagation.REQUIRED; | |
int isolation() default -1; | |
boolean readonly() default false; | |
int timeout() default -1; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.transaction; | |
public class TransactionDefinition { | |
private Propagation propagation; | |
private Integer isolation; | |
private Boolean readOnly; | |
private Integer timeout; | |
public TransactionDefinition(Propagation propagation, Integer isolation, Boolean readOnly, Integer timeout) { | |
this.propagation = propagation; | |
this.isolation = isolation; | |
this.readOnly = readOnly; | |
this.timeout = timeout; | |
} | |
public Propagation getPropagation() { | |
return propagation; | |
} | |
public void setPropagation(Propagation propagation) { | |
this.propagation = propagation; | |
} | |
public Integer getIsolation() { | |
return isolation; | |
} | |
public void setIsolation(Integer isolation) { | |
this.isolation = isolation; | |
} | |
public Boolean getReadOnly() { | |
return readOnly; | |
} | |
public void setReadOnly(Boolean readOnly) { | |
this.readOnly = readOnly; | |
} | |
public Integer getTimeout() { | |
return timeout; | |
} | |
public void setTimeout(Integer timeout) { | |
this.timeout = timeout; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.transaction; | |
public interface TransactionService { | |
boolean beginIfNoPresent(TransactionDefinition definition); | |
void begin(TransactionDefinition definition); | |
void commit(); | |
void rollback(); | |
boolean isWithinTransaction(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment