diff options
Diffstat (limited to 'java/sca-contrib/itest/transaction')
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); + } + +} |