summaryrefslogtreecommitdiffstats
path: root/java/sca-contrib/itest/transaction
diff options
context:
space:
mode:
Diffstat (limited to 'java/sca-contrib/itest/transaction')
-rw-r--r--java/sca-contrib/itest/transaction/pom.xml91
-rw-r--r--java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/AccountNotFoundException.java36
-rw-r--r--java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/AccountService.java31
-rw-r--r--java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/AccountServiceImpl.java70
-rw-r--r--java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/CheckingAccountServiceImpl.java143
-rw-r--r--java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/OverDraftException.java36
-rw-r--r--java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/SavingsAccountServiceImpl.java133
-rw-r--r--java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/TransferService.java31
-rw-r--r--java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/TransferServiceImpl.java64
-rw-r--r--java/sca-contrib/itest/transaction/src/main/resources/accounts.composite43
-rw-r--r--java/sca-contrib/itest/transaction/src/main/resources/definitions.xml99
-rw-r--r--java/sca-contrib/itest/transaction/src/main/resources/log4j.properties29
-rw-r--r--java/sca-contrib/itest/transaction/src/test/java/org/apache/tuscany/sca/itest/transaction/ConcurrentXAResourceTestCase.java119
-rw-r--r--java/sca-contrib/itest/transaction/src/test/java/org/apache/tuscany/sca/itest/transaction/TransactionTestCase.java53
14 files changed, 978 insertions, 0 deletions
diff --git a/java/sca-contrib/itest/transaction/pom.xml b/java/sca-contrib/itest/transaction/pom.xml
new file mode 100644
index 0000000000..efdd2bf5a4
--- /dev/null
+++ b/java/sca-contrib/itest/transaction/pom.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-itest</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>itest-transaction</artifactId>
+ <name>Apache Tuscany SCA Transaction Policy Integration Test</name>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-policy-transaction</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-host-embedded</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-implementation-java-runtime</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.activemq</groupId>
+ <artifactId>activemq-core</artifactId>
+ <version>4.1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.activemq</groupId>
+ <artifactId>activemq-ra</artifactId>
+ <version>4.1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jms_1.1_spec</artifactId>
+ <version>1.1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derby</artifactId>
+ <version>10.3.1.4</version>
+ </dependency>
+
+ <!--
+ <dependency>
+ <groupId>jotm</groupId>
+ <artifactId>jotm</artifactId>
+ <version>2.0.10</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>jta</artifactId>
+ <groupId>javax.transaction</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>connector</artifactId>
+ <groupId>javax.resource</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ -->
+ </dependencies>
+</project>
diff --git a/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/AccountNotFoundException.java b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/AccountNotFoundException.java
new file mode 100644
index 0000000000..d7d18181d9
--- /dev/null
+++ b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/AccountNotFoundException.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.itest.transaction;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class AccountNotFoundException extends Exception {
+ private static final long serialVersionUID = -4709084750220950706L;
+
+ public AccountNotFoundException() {
+ super();
+ }
+
+ public AccountNotFoundException(String message) {
+ super(message);
+ }
+
+}
diff --git a/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/AccountService.java b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/AccountService.java
new file mode 100644
index 0000000000..ac986dd417
--- /dev/null
+++ b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/AccountService.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.itest.transaction;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public interface AccountService {
+ float getBalance(String accountNumber) throws AccountNotFoundException;
+
+ void deposit(String accountNumber, float amount) throws AccountNotFoundException;
+
+ void withdraw(String accountNumber, float amount) throws OverDraftException, AccountNotFoundException;
+}
diff --git a/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/AccountServiceImpl.java b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/AccountServiceImpl.java
new file mode 100644
index 0000000000..a6ea036da7
--- /dev/null
+++ b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/AccountServiceImpl.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.itest.transaction;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public abstract class AccountServiceImpl implements AccountService {
+ protected Map<String, Float> accounts = new HashMap<String, Float>();
+
+ /**
+ * @see org.apache.tuscany.sca.itest.transaction.AccountService#deposit(String, float)
+ */
+ public void deposit(String accountNumber, float amount) throws AccountNotFoundException {
+ float balance = getBalance(accountNumber);
+ balance += amount;
+ save(accountNumber, balance);
+ accounts.put(accountNumber, balance);
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.itest.transaction.AccountService#getBalance(String)
+ */
+ public float getBalance(String accountNumber) throws AccountNotFoundException {
+ Float balance = accounts.get(accountNumber);
+ if (balance == null) {
+ balance = load(accountNumber);
+ accounts.put(accountNumber, balance);
+ }
+ return balance;
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.itest.transaction.AccountService#withdraw(String, float)
+ */
+ public void withdraw(String accountNumber, float amount) throws OverDraftException, AccountNotFoundException {
+ float balance = getBalance(accountNumber);
+ if (amount > balance) {
+ throw new OverDraftException("Insufficient fund");
+ }
+ balance -= amount;
+ save(accountNumber, balance);
+ accounts.put(accountNumber, balance);
+ }
+
+ protected abstract float load(String accountNumber) throws AccountNotFoundException;
+
+ protected abstract void save(String accountNumber, float balance) throws AccountNotFoundException;
+
+}
diff --git a/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/CheckingAccountServiceImpl.java b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/CheckingAccountServiceImpl.java
new file mode 100644
index 0000000000..776d23407a
--- /dev/null
+++ b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/CheckingAccountServiceImpl.java
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.itest.transaction;
+
+import java.io.File;
+import java.util.Enumeration;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.MapMessage;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.QueueBrowser;
+import javax.jms.Session;
+
+import org.apache.activemq.ActiveMQConnectionFactory;
+import org.apache.activemq.ActiveMQSession;
+import org.apache.activemq.broker.BrokerService;
+import org.oasisopen.sca.ServiceRuntimeException;
+import org.oasisopen.sca.annotation.Destroy;
+import org.oasisopen.sca.annotation.Init;
+import org.oasisopen.sca.annotation.Scope;
+import org.oasisopen.sca.annotation.Service;
+
+/**
+ * @version $Rev$ $Date$
+ */
+@Service(AccountService.class)
+@Scope("COMPOSITE")
+public class CheckingAccountServiceImpl extends AccountServiceImpl {
+ private static final String url = "tcp://localhost:61616";
+ private BrokerService broker;
+ private Queue queue;
+
+ @Init
+ public void init() throws Exception {
+ broker = new BrokerService();
+ broker.setBrokerName("localhost");
+ broker.setPersistent(false);
+ broker.addConnector(url);
+ broker.start();
+
+ ActiveMQConnectionFactory connFac = new ActiveMQConnectionFactory(url);
+ Connection conn = connFac.createConnection();
+ ActiveMQSession session = (ActiveMQSession)conn.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ queue = session.createQueue("CheckAccounts");
+ MessageProducer producer = session.createProducer(queue);
+ MapMessage map = session.createMapMessage();
+
+ for (int i = 0; i < 3; i++) {
+ String accountNumber = "C00" + (i + 1);
+ float balance = (float)(1000.0 + Math.random() * 200.0);
+ map.setStringProperty("accountNumber", accountNumber);
+ map.setFloatProperty("balance", balance);
+
+ map.setString("accountNumber", accountNumber);
+ map.setFloat("balance", balance);
+
+ producer.send(map);
+ }
+ session.commit();
+ conn.close();
+ }
+
+ @Destroy
+ public void destroy() throws Exception {
+ if (broker != null) {
+ broker.stop();
+ }
+ }
+
+ @Override
+ protected float load(String accountNumber) throws AccountNotFoundException {
+ try {
+ ActiveMQConnectionFactory connFac = new ActiveMQConnectionFactory(url);
+ Connection conn = connFac.createConnection();
+ conn.start();
+ Session session = conn.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ QueueBrowser browser = session.createBrowser(queue, "accountNumber = '" + accountNumber + "'");
+ Enumeration msgs = browser.getEnumeration();
+ if (msgs.hasMoreElements()) {
+ MapMessage msg = (MapMessage)msgs.nextElement();
+ float balance = msg.getFloat("balance");
+ conn.close();
+ return balance;
+ } else {
+ conn.close();
+ throw new AccountNotFoundException(accountNumber);
+ }
+ } catch (JMSException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void save(String accountNumber, float balance) throws AccountNotFoundException {
+ try {
+ ActiveMQConnectionFactory connFac = new ActiveMQConnectionFactory(url);
+ Connection conn = connFac.createConnection();
+ conn.start();
+ ActiveMQSession session = (ActiveMQSession)conn.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ MessageConsumer consumer = session.createConsumer(queue, "accountNumber = '" + accountNumber + "'");
+ Message msg = consumer.receive(1000);
+ if (msg == null) {
+ conn.close();
+ throw new AccountNotFoundException(accountNumber);
+ }
+ MapMessage map = session.createMapMessage();
+ map.setStringProperty("accountNumber", accountNumber);
+ map.setFloatProperty("balance", balance);
+
+ map.setString("accountNumber", accountNumber);
+ map.setFloat("balance", balance);
+
+ MessageProducer producer = session.createProducer(queue);
+ producer.send(map);
+ conn.close();
+
+ } catch (JMSException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+}
diff --git a/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/OverDraftException.java b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/OverDraftException.java
new file mode 100644
index 0000000000..4d504a6a36
--- /dev/null
+++ b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/OverDraftException.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.itest.transaction;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class OverDraftException extends Exception {
+ private static final long serialVersionUID = -4709084750220950706L;
+
+ public OverDraftException() {
+ super();
+ }
+
+ public OverDraftException(String message) {
+ super(message);
+ }
+
+}
diff --git a/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/SavingsAccountServiceImpl.java b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/SavingsAccountServiceImpl.java
new file mode 100644
index 0000000000..6010d9abad
--- /dev/null
+++ b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/SavingsAccountServiceImpl.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.itest.transaction;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.logging.Logger;
+
+import javax.sql.XAConnection;
+
+import org.apache.derby.jdbc.EmbeddedXADataSource;
+import org.oasisopen.sca.ServiceRuntimeException;
+import org.oasisopen.sca.annotation.Destroy;
+import org.oasisopen.sca.annotation.Init;
+import org.oasisopen.sca.annotation.Scope;
+import org.oasisopen.sca.annotation.Service;
+
+/**
+ * @version $Rev$ $Date$
+ */
+@Service(AccountService.class)
+@Scope("COMPOSITE")
+public class SavingsAccountServiceImpl extends AccountServiceImpl {
+ private final static Logger log = Logger.getLogger(SavingsAccountServiceImpl.class.getName());
+ private EmbeddedXADataSource xads;
+
+ @Init
+ public void init() throws SQLException {
+ // Create the database and a table
+ xads = new EmbeddedXADataSource();
+ xads.setDatabaseName("target/test");
+ xads.setCreateDatabase("create");
+
+ XAConnection xaconn = xads.getXAConnection();
+ Connection conn = xaconn.getConnection();
+ PreparedStatement ps =
+ conn.prepareStatement("create table SavingsAccounts(accountNumber char(100), balance float)");
+ try {
+ ps.execute();
+ } catch (SQLException ex) {
+ log.info(ex.getMessage());
+ }
+ ps = conn.prepareStatement("delete from SavingsAccounts");
+ ps.execute();
+
+ ps = conn.prepareStatement("insert into SavingsAccounts(accountNumber, balance) values(?, ?)");
+ for (int i = 0; i < 2; i++) {
+ ps.setString(1, "S00" + (i+1));
+ ps.setFloat(2, (float)(1000.0f + Math.random() * 500.0));
+ ps.executeUpdate();
+ }
+ conn.commit();
+ conn.close();
+ }
+
+ @Override
+ protected float load(String accountNumber) throws AccountNotFoundException {
+ try {
+ XAConnection xaconn = xads.getXAConnection();
+
+ Connection conn = xaconn.getConnection();
+ PreparedStatement ps = conn.prepareStatement("select balance from SavingsAccounts where accountNumber=?");
+ ps.setString(1, accountNumber);
+ ResultSet rs1 = ps.executeQuery();
+ boolean found = rs1.next();
+ if (found) {
+ float balance = rs1.getFloat(1);
+ conn.commit();
+ conn.close();
+ return balance;
+ } else {
+ conn.commit();
+ conn.close();
+ throw new AccountNotFoundException(accountNumber);
+ }
+ } catch (SQLException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void save(String accountNumber, float balance) throws AccountNotFoundException {
+ try {
+ XAConnection xaconn = xads.getXAConnection();
+
+ Connection conn = xaconn.getConnection();
+ PreparedStatement ps = conn.prepareStatement("update SavingsAccounts set balance=? where accountNumber=?");
+ ps.setFloat(1, balance);
+ ps.setString(2, accountNumber);
+ int rows = ps.executeUpdate();
+ conn.commit();
+ boolean found = (rows >= 1);
+ if (found) {
+ conn.close();
+ } else {
+ conn.close();
+ throw new AccountNotFoundException(accountNumber);
+ }
+ } catch (SQLException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ @Destroy
+ public void destroy() throws SQLException {
+ XAConnection xaconn = xads.getXAConnection();
+ Connection conn = xaconn.getConnection();
+ PreparedStatement ps = conn.prepareStatement("drop table SavingsAccounts");
+ ps.execute();
+ conn.commit();
+ conn.close();
+ }
+
+}
diff --git a/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/TransferService.java b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/TransferService.java
new file mode 100644
index 0000000000..b7ea5f2663
--- /dev/null
+++ b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/TransferService.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.itest.transaction;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public interface TransferService {
+ String[] getAccounts();
+
+ float getBalance(String accountNumber) throws AccountNotFoundException;
+
+ void transfer(String from, String to, float amount) throws OverDraftException, AccountNotFoundException;
+}
diff --git a/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/TransferServiceImpl.java b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/TransferServiceImpl.java
new file mode 100644
index 0000000000..45a9a26c3d
--- /dev/null
+++ b/java/sca-contrib/itest/transaction/src/main/java/org/apache/tuscany/sca/itest/transaction/TransferServiceImpl.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.itest.transaction;
+
+import org.oasisopen.sca.annotation.Reference;
+import org.oasisopen.sca.annotation.Service;
+
+/**
+ * @version $Rev$ $Date$
+ */
+@Service(TransferService.class)
+public class TransferServiceImpl implements TransferService {
+ @Reference
+ protected AccountService savings;
+
+ @Reference
+ protected AccountService checking;
+
+ /**
+ * @see org.apache.tuscany.sca.itest.transaction.TransferService#transfer(java.lang.String, java.lang.String, float)
+ */
+ public void transfer(String from, String to, float amount) throws OverDraftException, AccountNotFoundException {
+ if (from.startsWith("C")) {
+ checking.withdraw(from, amount);
+ } else {
+ savings.withdraw(from, amount);
+ }
+ if (to.startsWith("C")) {
+ checking.deposit(to, amount);
+ } else {
+ savings.deposit(to, amount);
+ }
+ }
+
+ public float getBalance(String accountNumber) throws AccountNotFoundException {
+ if(accountNumber.startsWith("C")) {
+ return checking.getBalance(accountNumber);
+ } else {
+ return savings.getBalance(accountNumber);
+ }
+ }
+
+ public String[] getAccounts() {
+ return new String[] {"S001", "S002", "C001"};
+ }
+
+}
diff --git a/java/sca-contrib/itest/transaction/src/main/resources/accounts.composite b/java/sca-contrib/itest/transaction/src/main/resources/accounts.composite
new file mode 100644
index 0000000000..f4c6b650c7
--- /dev/null
+++ b/java/sca-contrib/itest/transaction/src/main/resources/accounts.composite
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" xmlns:foo="http://foo" targetNamespace="http://account"
+ name="Accounts" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <component name="TransferServiceComponent">
+ <implementation.java class="org.apache.tuscany.sca.itest.transaction.TransferServiceImpl"
+ requires="managedTransaction.global" />
+ <service name="TransferService" />
+ <reference name="savings" requires="propagatesTransaction" target="SavingsAccountServiceComponent"></reference>
+ <reference name="checking" requires="propagatesTransaction" target="CheckingAccountServiceComponent"></reference>
+ </component>
+
+ <component name="SavingsAccountServiceComponent">
+ <implementation.java class="org.apache.tuscany.sca.itest.transaction.SavingsAccountServiceImpl"
+ requires="managedTransaction.global" />
+ <service name="AccountService" requires="propagatesTransaction" />
+ </component>
+
+ <component name="CheckingAccountServiceComponent">
+ <implementation.java class="org.apache.tuscany.sca.itest.transaction.CheckingAccountServiceImpl"
+ requires="managedTransaction.global" />
+ <service name="AccountService" requires="propagatesTransaction" />
+ </component>
+
+</composite> \ No newline at end of file
diff --git a/java/sca-contrib/itest/transaction/src/main/resources/definitions.xml b/java/sca-contrib/itest/transaction/src/main/resources/definitions.xml
new file mode 100644
index 0000000000..8aa6ba313a
--- /dev/null
+++ b/java/sca-contrib/itest/transaction/src/main/resources/definitions.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="ASCII"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<definitions xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="http://www.osoa.org/xmlns/sca/1.0"
+ xmlns:sca="http://www.osoa.org/xmlns/sca/1.0" xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0">
+
+ <policySet name="tuscany:ManagedTransactionPolicySet" provides="managedTransaction" appliesTo="sca:implementation.java">
+ <intentMap provides="managedTransaction" default="global">
+ <qualifier name="global">
+ <tuscany:transactionPolicy transactionTimeout="1200" action="REQUIRE_GLOBAL" />
+ </qualifier>
+ <qualifier name="local">
+ <tuscany:transactionPolicy transactionTimeout="1200" action="REQUIRE_LOCAL" />
+ </qualifier>
+ </intentMap>
+ </policySet>
+
+ <policySet name="tuscany:NoManagedTransactionPolicySet" provides="noManagedTransaction"
+ appliesTo="implementation">
+ <tuscany:transactionPolicy action="REQUIRE_NONE" />
+ </policySet>
+
+ <policySet name="tuscany:PropagatesTransactionPolicySet" provides="propagatesTransaction" appliesTo="sca:component">
+ <tuscany:transactionPolicy action="PROPAGATE" />
+ </policySet>
+
+ <policySet name="tuscany:SuspendsTransactionPolicySet" provides="suspendsTransaction" appliesTo="sca:binding.sca">
+ <tuscany:transactionPolicy action="SUSPEND" />
+ </policySet>
+
+ <policySet name="tuscany:TransactedOneWayPolicySet" provides="transactedOneWay" appliesTo="sca:binding.sca">
+ <tuscany:transactionPolicy action="PROPAGATE" />
+ </policySet>
+
+ <policySet name="tuscany:ImmediateOneWayPolicySet" provides="immediateOneWay" appliesTo="sca:binding.sca">
+ <tuscany:transactionPolicy action="SUSPEND" />
+ </policySet>
+
+ <intent name="managedTransaction" constrains="implementation">
+ <description>Used to indicate the transaction environment desired by a component implementation.</description>
+ </intent>
+ <intent name="managedTransaction.global">
+ <description>
+ Used to indicate that a component implementation requires a managed global transaction.
+ </description>
+ </intent>
+ <intent name="managedTransaction.local">
+ <description>
+ Used to indicate that a component implementation requires a managed local transaction.
+ </description>
+ </intent>
+ <intent name="noManagedTransaction" constrains="implementation">
+ <description>
+ Used to indicate that a component implementation will manage its own transaction resources.
+ </description>
+ </intent>
+ <intent name="propagatesTransaction" constrains="binding">
+ <description>
+ Used to indicate that a reference will propagate any client transaction or that a service will be dispatched
+ under any received transaction.
+ </description>
+ </intent>
+ <intent name="suspendsTransaction" constrains="binding">
+ <description>
+ Used to indicate that a reference will not propagate any client transaction or that a service will not be
+ dispatched under any received transaction.
+ </description>
+ </intent>
+ <intent name="transactedOneWay" constrains="binding">
+ <description>
+ Used to indicate that the component requires the SCA runtime to transact OneWay send of messages as part of
+ any client global transaction or to transact oneWay message receipt as part of any service global
+ transaction.
+ </description>
+ </intent>
+ <intent name="immediateOneWay" constrains="binding">
+ <description>
+ Used to indicate that the component requires the SCA runtime to process the sending or receiving of OneWay
+ messages immediately, regardless of any transaction under which the sending/receiving component runs.
+ </description>
+ </intent>
+
+</definitions> \ No newline at end of file
diff --git a/java/sca-contrib/itest/transaction/src/main/resources/log4j.properties b/java/sca-contrib/itest/transaction/src/main/resources/log4j.properties
new file mode 100644
index 0000000000..698ee41d7e
--- /dev/null
+++ b/java/sca-contrib/itest/transaction/src/main/resources/log4j.properties
@@ -0,0 +1,29 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+# Set root logger level to DEBUG and its only appender to A1.
+log4j.rootLogger=INFO, CONSOLE
+
+# CONSOLE is set to be a ConsoleAppender.
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+
+# A1 uses PatternLayout.
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+
+
+# Print only messages of level WARN or above in the package com.foo.
+log4j.logger.org.apache.tuscany=INFO \ No newline at end of file
diff --git a/java/sca-contrib/itest/transaction/src/test/java/org/apache/tuscany/sca/itest/transaction/ConcurrentXAResourceTestCase.java b/java/sca-contrib/itest/transaction/src/test/java/org/apache/tuscany/sca/itest/transaction/ConcurrentXAResourceTestCase.java
new file mode 100644
index 0000000000..c23628ff91
--- /dev/null
+++ b/java/sca-contrib/itest/transaction/src/test/java/org/apache/tuscany/sca/itest/transaction/ConcurrentXAResourceTestCase.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.itest.transaction;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.logging.Logger;
+
+import javax.sql.XAConnection;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import junit.framework.TestCase;
+
+import org.apache.derby.jdbc.EmbeddedXADataSource;
+import org.apache.tuscany.sca.policy.transaction.TransactionManagerHelper;
+import org.apache.tuscany.sca.policy.transaction.TransactionManagerWrapper;
+
+public class ConcurrentXAResourceTestCase extends TestCase {
+ class TestThread extends Thread {
+ private int counter;
+
+ TestThread(int i) {
+ counter = i;
+ }
+
+ public void run() {
+ log.info(this + " running...");
+
+ EmbeddedXADataSource xads = new EmbeddedXADataSource();
+ xads.setDatabaseName("target/test" + counter);
+ xads.setCreateDatabase("create");
+ Connection conn = null;
+ try {
+
+ Transaction trans = helper.managedGlobalTransactionPreInvoke();
+
+ XAConnection xaconn = xads.getXAConnection();
+
+ trans.enlistResource(xaconn.getXAResource());
+
+ conn = xaconn.getConnection();
+ try {
+ conn.prepareStatement("create table T1(col1 char(100))").execute();
+ } catch (SQLException ex) {
+ log.info("table T1 exists");
+ }
+ conn.prepareStatement("insert into T1 values('kkkkkkkk')").execute();
+ ResultSet rs = conn.prepareStatement("select count(*) from T1").executeQuery();
+ rs.next();
+ log.info(String.valueOf(rs.getInt(1)));
+
+ helper.managedGlobalTransactionPostInvoke(trans, false);
+
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ } finally {
+ try {
+ conn.close();
+ } catch (Exception _ex) {
+ _ex.printStackTrace();
+ }
+ }
+ }
+
+ }
+ private TransactionManagerWrapper activator;
+ private TransactionManagerHelper helper;
+
+ private Logger log = Logger.getLogger(this.getClass().getName());
+
+ public void setUp() throws Exception {
+ activator = new TransactionManagerWrapper();
+ activator.start();
+ TransactionManager tm = activator.getTransactionManager();
+ helper = new TransactionManagerHelper(tm);
+ }
+
+ public void tearDown() throws Exception {
+ activator.stop();
+
+ }
+
+ public void testConcurrent() {
+ TestThread[] tts = new TestThread[5];
+ for (int i = 0; i < tts.length; i++) {
+ tts[i] = new TestThread(i);
+ tts[i].start();
+ // log.info("one TestThread started...");
+ }
+ try {
+ for (TestThread tt : tts) {
+ while (tt != null && tt.isAlive()) {
+ // log.info("wait for...");
+ Thread.sleep(200);
+ }
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/java/sca-contrib/itest/transaction/src/test/java/org/apache/tuscany/sca/itest/transaction/TransactionTestCase.java b/java/sca-contrib/itest/transaction/src/test/java/org/apache/tuscany/sca/itest/transaction/TransactionTestCase.java
new file mode 100644
index 0000000000..36884f6098
--- /dev/null
+++ b/java/sca-contrib/itest/transaction/src/test/java/org/apache/tuscany/sca/itest/transaction/TransactionTestCase.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.itest.transaction;
+
+import org.apache.tuscany.sca.host.embedded.SCADomain;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TransactionTestCase {
+ private static SCADomain domain;
+
+ @BeforeClass
+ public static void init() throws Exception {
+ domain = SCADomain.newInstance("accounts.composite");
+ }
+
+ @AfterClass
+ public static void destroy() throws Exception {
+ if (domain != null) {
+ domain.close();
+ }
+ }
+
+ @Test
+ public void testTransaction() throws Exception {
+ TransferService service = domain.getService(TransferService.class, "TransferServiceComponent");
+ String[] accounts = service.getAccounts();
+ for (int i = 0; i < accounts.length; i++) {
+ float balance = service.getBalance(accounts[i]);
+ System.out.println("[" + i + "] " + accounts[i] + ":" + balance);
+ }
+ service.transfer(accounts[0], accounts[2], 200.0f);
+ }
+
+}