Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended Spring Tests, Added CDI-Support #92

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ addons:
language: java
jdk:
- oraclejdk8
- oraclejdk7
- openjdk6

Binary file added btm-cdi/doc/CdiTransactions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
98 changes: 98 additions & 0 deletions btm-cdi/doc/CdiTransactions.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
@startuml

actor client as c
participant TransactionalBean as s
participant TInterceptor as ti
participant TFrameStack as ts
participant TransactionInfo as tif
participant emdelegate as emd
participant tm
participant em
participant pfactory as pf
participant query1 as q1
participant query2 as q2

c -> s: call
activate s
s -> ti: manageTransaction
activate ti
ti -> ts: pushTra(attribute)
create tif
ts -> tif: new
ts -> tm: begin
tm --> ts: ok
ts --> ti: ok
ti -> s: invoke
activate s
s -> emd: createQuery
activate emd
emd -> pf: getTransactional
activate pf
pf -> ts: getEntityManager(this)
activate ts
ts -> ts: searchEmInTopTInfo
ts -> pf: createEntityManager
create em
pf -> em: new
pf --> ts: em
ts -> em: joinTransaction
ts -> tif: register(em)
ts --> pf: ok
deactivate ts
pf --> emd: em
deactivate pf
emd -> em: createQuery
create q1
em -> q1: createQuery
em --> emd: q1
emd --> s: q1
deactivate emd
s -> q1: execute
activate q1
q1 --> s: results
deactivate q1
destroy q1
s -> emd: createQuery
activate emd
emd -> pf: getTransactional
activate pf
pf -> ts: getEntityManager(this)
activate ts
ts -> ts: searchEmInTopTInfo
ts --> pf: em
deactivate ts
pf --> emd: em
deactivate pf
emd -> em: createQuery
create q2
em -> q2: createQuery
em --> emd: q2
emd --> s: q2
deactivate emd
s -> q2: execute
activate q2
q2 --> s: results
deactivate q2
destroy q2
s --> ti: return
deactivate s
activate ti
ti -> ts: popTra
activate ts
ts -> tm: commit
tm -> em: flush
em --> tm: ok
tm --> ts: ok
ts -> em: close
em --> ts: ok
destroy em
ts --> tif: close
destroy tif
ts --> ti: ok
deactivate ts
deactivate ti
ti --> s: return from intercept
deactivate ti
s --> c: return
deactivate s
@enduml
144 changes: 144 additions & 0 deletions btm-cdi/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.codehaus.btm</groupId>
<artifactId>btm-parent</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>btm-cdi</artifactId>
<name>Bitronix Transaction Manager :: CDI Integration</name>

<properties>
<version.org.hibernate.api>1.0.1.Final</version.org.hibernate.api>
<version.org.hibernate>4.2.2.Final</version.org.hibernate>
<version.org.hibernate.validator>4.3.1.Final</version.org.hibernate.validator>
<slf4j.version>1.7.21</slf4j.version>
</properties>
<dependencies>
<dependency>
<groupId>org.codehaus.btm</groupId>
<artifactId>btm</artifactId>
</dependency>

<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.codehaus.btm</groupId>
<artifactId>btm</artifactId>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
<!-- but compatible with cd 1.1 -->
<!--version>1.1.14.Final</version-->
<version>2.3.5.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
<!--dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency-->
<!--dependency>
<groupId>net.oneandone</groupId>
<artifactId>ejb-cdi-unit</artifactId>
<version>1.1.4</version>
</dependency-->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.transaction</groupId>
<artifactId>jboss-transaction-api_1.1_spec</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.jglue.cdi-unit</groupId>
<artifactId>cdi-unit</artifactId>
<version>3.1.4</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
<version>1.4.196</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${version.org.hibernate}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${version.org.hibernate.validator}</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>${version.org.hibernate.api}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
109 changes: 109 additions & 0 deletions btm-cdi/src/main/java/bitronix/tm/integration/cdi/CdiTInterceptor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package bitronix.tm.integration.cdi;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;


import javax.ejb.ApplicationException;
import javax.ejb.EJBException;
import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
import javax.transaction.RollbackException;
import javax.transaction.TransactionManager;
import javax.transaction.Transactional;

@Interceptor
@CdiTransactional
public class CdiTInterceptor {

Logger logger = LoggerFactory.getLogger(CdiTInterceptor.class);

@Inject
TransactionManager tm;

@AroundInvoke
public Object manageTransaction(InvocationContext ctx) throws Exception {
final Class<?> declaringClass = ctx.getMethod().getDeclaringClass();
TFrameStack ts = new TFrameStack();
TransactionInfo lastTransactionInfo = ts.topTransaction();
Transactional.TxType attribute = null;
Transactional classTransactional =
declaringClass.getAnnotation(
Transactional.class);
Transactional transactionMethod = ctx.getMethod().getAnnotation(Transactional.class);

Class[] rollbackon = null;
Class[] dontRollBackOn = null;

if (transactionMethod != null) {
attribute = transactionMethod.value();
rollbackon = transactionMethod.rollbackOn();
dontRollBackOn = transactionMethod.dontRollbackOn();

} else if (classTransactional != null) {
if (classTransactional != null) {
attribute = classTransactional.value();
rollbackon = classTransactional.rollbackOn();
dontRollBackOn = classTransactional.dontRollbackOn();
} else {
attribute = Transactional.TxType.REQUIRED;
}
}
if (attribute == null) {
logger.error("CdiTransactionalInterceptor should not be used at this class: {}", declaringClass.getName());
return ctx.proceed();
} else {
boolean passThroughRollbackException = true;
try {
logger.info("Thread {} L{} changing from {} to {} xid: {} in {}.{}",
Thread.currentThread().getId(), ts.currentLevel(),
ts.currentTxType(),
attribute, MDC.get("XID"), declaringClass.getSimpleName(), ctx.getMethod().getName());
ts.pushTransaction(attribute);
return ctx.proceed();
} catch (Throwable ex) {
logger.info("Thread {} L{} Exception {} in {} xid: {} in {}.{}",
Thread.currentThread().getId(), ts.currentLevel(),
ex.getClass().getSimpleName(), attribute, MDC.get("XID"), declaringClass.getSimpleName(),
ctx.getMethod().getName());
boolean doRollback = !isSubOrClassOfAny(ex.getClass(), dontRollBackOn)
&& (isSubOrClassOfAny(ex.getClass(), rollbackon) || ex instanceof RuntimeException);
if (doRollback) {
passThroughRollbackException = false;
tm.rollback();
}

throw ex;
} finally {
logger.info("Thread {} L{} finally in {} xid: {} in {}.{}",
Thread.currentThread().getId(), ts.currentLevel(), attribute, MDC.get("XID"), declaringClass.getSimpleName(),
ctx.getMethod().getName());
try {
ts.popTransaction();
} catch (RollbackException rbe) {
if (passThroughRollbackException) {
throw rbe;
}
} finally {
logger.info("Thread {} L{} done {} back to {} xid: {} in {}.{}",
Thread.currentThread().getId(), ts.topTransaction(), attribute,
lastTransactionInfo == null ? "undefined" : lastTransactionInfo.currentTxType,
MDC.get("XID"), declaringClass.getSimpleName(), ctx.getMethod().getName());
}
}
}
}

public boolean isSubOrClassOfAny(Class c, Class[] classes) {
for (Class clazz: classes) {
if (clazz.isAssignableFrom(c)) {
return true;
}
}
return false;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package bitronix.tm.integration.cdi;

import javax.interceptor.InterceptorBinding;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* @author aschoerk
*/
@InterceptorBinding
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface CdiTransactional {
}
Loading