diff --git a/jta-1_2-in-wildfly/README.md b/jta-1_2-in-wildfly/README.md new file mode 100644 index 0000000000..79e52533fb --- /dev/null +++ b/jta-1_2-in-wildfly/README.md @@ -0,0 +1,26 @@ +JTA 1.2 in Wildfly example. +================================================================================================== +Author: Gytis Trikleris; +Level: Intermediate; +Technologies: JTA, JPA, JMS + +What is it? +----------- + +This example demonstrates how to use new JTA 1.2 features inside WildFly application server. + + +QuickstartEntityRepository and QuickstartQueue classes demonstrace usage of @Transactional annotation. +TransactionScopedPojo class demonstrates @TransactionScoped annotation. TestCase class is used to drive the example. + + +Build and Deploy the Quickstart +------------------------------- + +In order to run quickstart in the managed Wildfly application server, run the following command: + + mvn clean install + +In order to run quickstart in the remote Wildfly application server, run the following command: + + mvn clean install -Parq-jbossas-remote diff --git a/jta-1_2-in-wildfly/pom.xml b/jta-1_2-in-wildfly/pom.xml new file mode 100644 index 0000000000..92f7c7846e --- /dev/null +++ b/jta-1_2-in-wildfly/pom.xml @@ -0,0 +1,192 @@ + + + + 4.0.0 + + org.jboss.narayana.quickstarts + jta-1_2-in-wildfly + 5.1.0.Alpha1-SNAPSHOT + + Narayana Quickstarts: JTA 1.2 in Wildfly + Example demonstrates new JTA 1.2 features inside the Wildfly application server + + http://narayana.io + + + UTF-8 + 1.7 + 1.7 + 8.0.1.Final-SNAPSHOT + 1.0.0.Final + 1.0.0.Final + 1.0.0.Final + 1.0.0.Final + 1.1 + 4.11 + 1.1.2.Final + + + + + jboss-public-repository-group + JBoss Public Maven Repository Group + https://repository.jboss.org/nexus/content/groups/public/ + + true + + + true + + + + + + + org.jboss.spec.javax.transaction + jboss-transaction-api_1.2_spec + ${version.org.jboss.spec.javax.transaction} + provided + + + + org.jboss.spec.javax.ejb + jboss-ejb-api_3.2_spec + ${version.org.jboss.spec.javax.ejb} + provided + + + + org.jboss.spec.javax.jms + jboss-jms-api_2.0_spec + ${version.org.jboss.spec.javax.jms} + + + + org.hibernate.javax.persistence + hibernate-jpa-2.1-api + ${version.org.hibernate.javax.persistence} + provided + + + + javax.enterprise + cdi-api + ${version.javax.enterprise} + provided + + + + junit + junit + ${version.junit} + test + + + + org.jboss.arquillian.junit + arquillian-junit-container + ${version.org.jboss.arquillian} + test + + + + org.jboss.arquillian.protocol + arquillian-protocol-servlet + ${version.org.jboss.arquillian} + test + + + + + ${project.artifactId} + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + + + + + arq-jbossas-managed + + true + + + + org.wildfly + wildfly-arquillian-container-managed + ${jboss-as.version} + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + false + + + + + + + + + + arq-jbossas-remote + + + org.wildfly + wildfly-arquillian-container-remote + ${jboss-as.version} + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + false + + + + + + + + diff --git a/jta-1_2-in-wildfly/src/main/java/org/jboss/narayana/quickstarts/jta/QuickstartEntity.java b/jta-1_2-in-wildfly/src/main/java/org/jboss/narayana/quickstarts/jta/QuickstartEntity.java new file mode 100644 index 0000000000..6699bb0c73 --- /dev/null +++ b/jta-1_2-in-wildfly/src/main/java/org/jboss/narayana/quickstarts/jta/QuickstartEntity.java @@ -0,0 +1,62 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed 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.jboss.narayana.quickstarts.jta; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +/** + * @author Gytis Trikleris + */ +@Entity +public class QuickstartEntity { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + public QuickstartEntity() { + } + + public QuickstartEntity(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public boolean isTransient() { + return this.id == null; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/jta-1_2-in-wildfly/src/main/java/org/jboss/narayana/quickstarts/jta/QuickstartEntityRepository.java b/jta-1_2-in-wildfly/src/main/java/org/jboss/narayana/quickstarts/jta/QuickstartEntityRepository.java new file mode 100644 index 0000000000..7fe958a37d --- /dev/null +++ b/jta-1_2-in-wildfly/src/main/java/org/jboss/narayana/quickstarts/jta/QuickstartEntityRepository.java @@ -0,0 +1,50 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed 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.jboss.narayana.quickstarts.jta; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import javax.transaction.Transactional; +import java.util.List; + +/** + * @author Gytis Trikleris + */ +public class QuickstartEntityRepository { + + @PersistenceContext + private EntityManager entityManager; + + @Transactional + public List findAll() { + final Query query = entityManager.createQuery("select qe from QuickstartEntity qe"); + + return (List) query.getResultList(); + } + + @Transactional(Transactional.TxType.MANDATORY) + public Long save(QuickstartEntity quickstartEntity) { + if (quickstartEntity.isTransient()) { + entityManager.persist(quickstartEntity); + } else { + entityManager.merge(quickstartEntity); + } + + return quickstartEntity.getId(); + } +} diff --git a/jta-1_2-in-wildfly/src/main/java/org/jboss/narayana/quickstarts/jta/QuickstartQueue.java b/jta-1_2-in-wildfly/src/main/java/org/jboss/narayana/quickstarts/jta/QuickstartQueue.java new file mode 100644 index 0000000000..5e7f7fb2e8 --- /dev/null +++ b/jta-1_2-in-wildfly/src/main/java/org/jboss/narayana/quickstarts/jta/QuickstartQueue.java @@ -0,0 +1,114 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed 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.jboss.narayana.quickstarts.jta; + +import javax.annotation.Resource; +import javax.ejb.Stateless; +import javax.jms.JMSException; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.jms.XAConnection; +import javax.jms.XAConnectionFactory; +import javax.jms.XASession; +import javax.transaction.Transactional; + +/** + * @author Gytis Trikleris + */ +@Stateless +public class QuickstartQueue { + + @Resource(mappedName = "java:/JmsXA") + private XAConnectionFactory xaConnectionFactory; + + @Resource(mappedName = "java:/queue/test") + private Queue queue; + + @Transactional(Transactional.TxType.MANDATORY) + public void send(final String message) { + XAConnection connection = null; + XASession session = null; + + try { + connection = xaConnectionFactory.createXAConnection(); + session = connection.createXASession(); + MessageProducer messageProducer = session.createProducer(queue); + + connection.start(); + TextMessage textMessage = session.createTextMessage(); + textMessage.setText(message); + + messageProducer.send(textMessage); + messageProducer.close(); + } catch (JMSException e) { + throw new RuntimeException(e.getMessage(), e); + + } finally { + try { + if (connection != null) { + connection.close(); + } + + if (session != null) { + session.close(); + } + } catch (JMSException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + } + + @Transactional + public String get() { + XAConnection connection = null; + Session session = null; + + try { + connection = xaConnectionFactory.createXAConnection(); + session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + final MessageConsumer consumer = session.createConsumer(queue); + + connection.start(); + + final TextMessage message = (TextMessage) consumer.receive(5000); + + if (message != null) { + return message.getText(); + } + + return ""; + + } catch (JMSException e) { + throw new RuntimeException(e.getMessage(), e); + } finally { + try { + if (connection != null) { + connection.close(); + } + + if (session != null) { + session.close(); + } + } catch (JMSException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + } +} diff --git a/jta-1_2-in-wildfly/src/main/java/org/jboss/narayana/quickstarts/jta/TransactionScopedPojo.java b/jta-1_2-in-wildfly/src/main/java/org/jboss/narayana/quickstarts/jta/TransactionScopedPojo.java new file mode 100644 index 0000000000..5531f2e4a3 --- /dev/null +++ b/jta-1_2-in-wildfly/src/main/java/org/jboss/narayana/quickstarts/jta/TransactionScopedPojo.java @@ -0,0 +1,38 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed 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.jboss.narayana.quickstarts.jta; + +import javax.transaction.TransactionScoped; +import java.io.Serializable; + +/** + * @author Gytis Trikleris + */ +@TransactionScoped +public class TransactionScopedPojo implements Serializable { + + private int value = 0; + + public synchronized int getValue() { + return value; + } + + public synchronized void setValue(int value) { + this.value = value; + } + +} diff --git a/jta-1_2-in-wildfly/src/test/java/org/jboss/narayana/quickstarts/jta/TestCase.java b/jta-1_2-in-wildfly/src/test/java/org/jboss/narayana/quickstarts/jta/TestCase.java new file mode 100644 index 0000000000..2f47ecd69b --- /dev/null +++ b/jta-1_2-in-wildfly/src/test/java/org/jboss/narayana/quickstarts/jta/TestCase.java @@ -0,0 +1,131 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed 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.jboss.narayana.quickstarts.jta; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.inject.Inject; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.transaction.Transaction; +import javax.transaction.TransactionManager; +import javax.transaction.TransactionalException; + +/** + * @author Gytis Trikleris + */ +@RunWith(Arquillian.class) +public class TestCase { + + @Inject + private QuickstartQueue quickstartQueue; + + @Inject + private QuickstartEntityRepository quickstartEntityRepository; + + @Inject + private TransactionScopedPojo transactionScopedPojo; + + private TransactionManager transactionManager; + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class, "test.war") + .addPackages(true, QuickstartEntity.class.getPackage().getName()) + .addAsResource("META-INF/test-persistence.xml", "META-INF/persistence.xml") + .addAsWebInfResource("test-ds.xml", "test-ds.xml") + .addAsWebInfResource("test-jms.xml", "test-jms.xml") + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); + } + + @Before + public void before() throws NamingException { + transactionManager = (TransactionManager) new InitialContext().lookup("java:/jboss/TransactionManager"); + } + + @After + public void after() { + try { + transactionManager.rollback(); + } catch (final Throwable t) { + } + } + + @Test + public void testCommit() throws Exception { + final int entitiesCountBefore = quickstartEntityRepository.findAll().size(); + + transactionManager.begin(); + quickstartEntityRepository.save(new QuickstartEntity("test")); + quickstartQueue.send("testCommit"); + transactionManager.commit(); + + Assert.assertEquals(entitiesCountBefore + 1, quickstartEntityRepository.findAll().size()); + Assert.assertEquals("testCommit", quickstartQueue.get()); + } + + @Test + public void testRollback() throws Exception { + final int entitiesCountBefore = quickstartEntityRepository.findAll().size(); + + transactionManager.begin(); + quickstartEntityRepository.save(new QuickstartEntity("test")); + quickstartQueue.send("testRollback"); + transactionManager.rollback(); + + Assert.assertEquals(entitiesCountBefore, quickstartEntityRepository.findAll().size()); + Assert.assertEquals("", quickstartQueue.get()); + } + + @Test(expected = TransactionalException.class) + public void testWithoutTransaction() { + quickstartEntityRepository.save(new QuickstartEntity("test")); + } + + @Test + public void testTransactionScoped() throws Exception { + transactionManager.begin(); + Assert.assertEquals(0, transactionScopedPojo.getValue()); + transactionScopedPojo.setValue(1); + + final Transaction firstTransaction = transactionManager.suspend(); + + transactionManager.begin(); + Assert.assertEquals(0, transactionScopedPojo.getValue()); + transactionScopedPojo.setValue(2); + + final Transaction secondTransaction = transactionManager.suspend(); + + transactionManager.resume(firstTransaction); + Assert.assertEquals(1, transactionScopedPojo.getValue()); + transactionManager.commit(); + + transactionManager.resume(secondTransaction); + Assert.assertEquals(2, transactionScopedPojo.getValue()); + transactionManager.commit(); + } + +} diff --git a/jta-1_2-in-wildfly/src/test/resources/META-INF/test-persistence.xml b/jta-1_2-in-wildfly/src/test/resources/META-INF/test-persistence.xml new file mode 100644 index 0000000000..b0abef9c51 --- /dev/null +++ b/jta-1_2-in-wildfly/src/test/resources/META-INF/test-persistence.xml @@ -0,0 +1,41 @@ + + + + + + + java:jboss/datasources/QuickstartTestDS + + + + + + + \ No newline at end of file diff --git a/jta-1_2-in-wildfly/src/test/resources/arquillian.xml b/jta-1_2-in-wildfly/src/test/resources/arquillian.xml new file mode 100644 index 0000000000..51da38e1de --- /dev/null +++ b/jta-1_2-in-wildfly/src/test/resources/arquillian.xml @@ -0,0 +1,36 @@ + + + + + + + + + standalone-full.xml + + + + diff --git a/jta-1_2-in-wildfly/src/test/resources/test-ds.xml b/jta-1_2-in-wildfly/src/test/resources/test-ds.xml new file mode 100644 index 0000000000..eb1824f207 --- /dev/null +++ b/jta-1_2-in-wildfly/src/test/resources/test-ds.xml @@ -0,0 +1,40 @@ + + + + + + + jdbc:h2:mem:quickstart-test;DB_CLOSE_DELAY=-1 + h2 + + sa + sa + + + \ No newline at end of file diff --git a/jta-1_2-in-wildfly/src/test/resources/test-jms.xml b/jta-1_2-in-wildfly/src/test/resources/test-jms.xml new file mode 100644 index 0000000000..de4a536db7 --- /dev/null +++ b/jta-1_2-in-wildfly/src/test/resources/test-jms.xml @@ -0,0 +1,33 @@ + + + + + + + + + false + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 971c7fd282..fb7c1c58ab 100644 --- a/pom.xml +++ b/pom.xml @@ -127,6 +127,7 @@ jca-and-tomcat jca-and-hibernate jta-and-hibernate + jta-1_2-in-wildfly ArjunaCore ArjunaJTA ArjunaJTS