This content is no longer being updated or maintained. The content is provided “as is.” Given the rapid evolution of technology, some content, steps, or illustrations may have changed.
This tutorial, the third in the "Spring Boot Java applications for CICS" series, describes how to develop a transactional Spring Boot application for use in CICS® Liberty. We'll cover Spring Boot's approach to container-managed transactions using the @Transactional annotation, as well as the Spring TransactionTemplate interface for a Bean Managed Transaction. These approaches are then contrasted with the Java EE approach of using the JTA UserTransaction interface to create a Bean Managed Transaction.
Transaction management in Liberty can be used to coordinate updates across multiple XA resource managers. In our scenarios, the Liberty transaction manager is the coordinator and the CICS unit of work is subordinate to this (as though the transaction had originated outside of the CICS system). CICS recoverable resources include temporary storge queues (TSQs), VSAM files, and JDBC type 2 connections to IBM® Db2®; recoverable resources used by Liberty but not managed by CICS include JDBC type 4 connections and JMS connection factories.
Learning objectives
In this tutorial, we will use a recoverable TSQ to demonstrate the principles of transaction coordination, we'll learn different ways of transactionally managing Spring Boot applications in a CICS Liberty JVM server, and we'll show how to build the application through Gradle or Maven giving access to the various transaction APIs.
The following steps give an overview of the objectives:
Use Spring's TransactionTemplate interface. This also gives automatic integration with the Liberty transaction manager, but is more similar to EJBs Bean Managed Transactions (BMT).
All of the techniques discussed here integrate Spring Boot with Liberty's transaction manager. If you are running in CICS Liberty then the CICS unit of work (UOW) is also automatically integrated with the Liberty transaction, and becomes subordinate to Liberty's global (XA) transaction. The net result is that your Java work and CICS work can be committed or rolled back as one recoverable transaction.
Note: If using any of these JTA-based transactional scenarios in CICS, you cannot use the JCICS methods Task.commit() or Task.rollback() which drive a corresponding EXEC CICS SYNPOINT or ROLLBACK. This is because the CICS recovery manager for the task is subordinate to Liberty's transaction manager and all transaction coordination must be done using JTA.
Prerequisites
CICS TS V5.3 or later
A configured Liberty JVM server in CICS
Java SE 1.8 on the z/OS system
Java SE 1.8 on the workstation
An Eclipse development environment on the workstation
Either Gradle or Apache Maven on the workstation (Buildship or M2Eclipse)
Estimated time
It should take you about 1 hour to complete this tutorial.
If you are following step-by-step, generate and download a Spring Boot web application using the Spring initializr website tool. For further details on how to do this, and how to deploy bundles to CICS, see the first tutorial in this series, Spring Boot Java applications for CICS, Part 1: JCICS, Gradle, and Maven. We use Eclipse as our preferred IDE.
Once your newly generated project has been imported into your IDE, you should have the Application.java and ServletInitializer.java classes which provide the basic framework of a Spring Boot web application.
Next, add the TransactionController.java class as shown below. This class is used as the central coordinator for all the REST requests from your browser. Later, you will adapt and extend it to drive the different transactional approaches, but for now it's just a simple text response to the root REST request.
package com.ibm.cicsdev.springboot.transactions;
@RestController
public classTransactionController{
@GetMapping("/")
public String index()
{
return"Greetings from com.ibm.cicsdev.springboot.transaction servlet";
}
}
Show more
If you are following step-by-step, you can now run this locally as a Java application. Point your browser to http://localhost:8080/ to test the basic function.
2. Build and deploy a Spring Boot web application with Gradle or Maven
Using that knowledge, you should now be able to enhance build.gradle or pom.xml to include the necessary dependencies to compile against a variety of transaction APIs. In particular, we require the libraries that provide the Java Transaction API (JTA) and Spring's Transactional API.
For Gradle, your build file should have the following dependencies:
dependencies
{
// CICS BOM (as of May 2020)
compileOnly enforcedPlatform('com.ibm.cics:com.ibm.cics.ts.bom:5.5-20200519131930-PH25409')// Don't include JCICS in the final build (no need for version because we have BOM)
compileOnly("com.ibm.cics:com.ibm.cics.server")// Spring Boot web support
implementation ("org.springframework.boot:spring-boot-starter-web")// Java Transaction API (this is newer and covers up to jta-1.3) - don't include in the final build
compileOnly ("javax.transaction:javax.transaction-api")// Java Transaction API (this is newer and covers up to jta-1.3)
implementation ("javax.transaction:javax.transaction-api")// Spring's Transactional API
implementation ("org.springframework:spring-tx")
}
Show more
For Maven, you'll need the following dependencies in your pom.xml
<!-- CICS TS V5.5 BOM (as of May 2020) --><dependencyManagement><dependencies><dependency><groupId>com.ibm.cics</groupId><artifactId>com.ibm.cics.ts.bom</artifactId><version>5.5-20200519131930-PH25409</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><!-- Compile against, but don't include JCICS in the final build (version and scope are from BOM) --><dependency><groupId>com.ibm.cics</groupId><artifactId>com.ibm.cics.server</artifactId></dependency><!-- Spring Boot web support --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Compile against, but don't include Tomcat in the runtime build --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope></dependency><!-- Spring's Transactional API --><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId></dependency><!-- Compile against, but don't include Java Transaction API --><dependency><groupId>javax.transaction</groupId><artifactId>javax.transaction-api</artifactId><scope>provided</scope></dependency></dependencies>
Show more
Running the build tool of your choice should produce a WAR file that's ready to deploy. When the time comes (see below), you can deploy it in a CICS bundle, or directly as an <application> element in the Liberty server.xml. Further details on configuring a Liberty JVM server and deploying the sample to CICS can be found in the Git repository README file.
3. Create a TSMODEL
Our next step is to interact with a CICS recoverable resource. We chose a recoverable TSQ for simplicity, the contents of the TSQ can provide a clear indication of the commit/rollback effects.
For transactional recovery to work with TSQs, you need to make the TSQ recoverable. To do this, define a CICS TSMODEL resource with the PRefix attribute set to the name of the TSQ, and a RECovery attribute set to Yes. Our TSQ is called "EXAMPLE." Don't install the TSMODEL yet -- you'll get a better indicator of the transactional intent if you save that for later.
For example:
4. Spring Boot @Transactional
Next, we'll update our code to demonstrate Spring Boot's approach to container-managed transactions. The @Transactional annotation can be used at the class or method level. The advantage of the @Transactional annotation over Bean Managed Transactions is that you do not explicitly have to code begin() and commit() to demark the transaction. Instead, you call a class or method that has the @Transactional annotation on it. Spring Boot, by virtue of its integration with Liberty's transaction manager, then co-ordinates the transaction with both Liberty and the CICS UOW.
So let's create our new class, SpringTransactional.java, to demonstrate Spring Container Managed Transactions:
package com.ibm.cicsdev.springboot.transactions;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.ibm.cics.server.CicsConditionException;
import com.ibm.cics.server.TSQ;
/**
* This component uses @Transactional to manage transactions in
* a container oriented manner.
*/
@Component
publicclass SpringTransactional
{
/**
* Write an input string to a CICS TSQ using the @Transactional annotation.
* If the input text contains 'rollback' then generate a RuntimeException
* which triggers rollback.
*
* @param text
* @return status message
* @throws CicsConditionException
*/
@Transactional (rollbackFor=Exception.class)
public String writeTSQ(String text) throws CicsConditionException
{
// Create JCICS representation of TSQ object
TSQ tsq = new TSQ();
tsq.setName(Application.TSQNAME);
// Write it to the TSQ
tsq.writeString(text);
// If the string contains 'rollback'then throw an exceptiontotriggerrollbackif (text.contains("rollback"))
{
throw new RuntimeException("SpringTransactional.writeTSQ(): Rollback request was detected");
}
returntext;
}
}
Show more
In this example, we write text to the CICS TSQ using the TSQ method writeString(), and then either commit or rollback the transaction. If the text contains the word 'rollback', we throw an unchecked RuntimeException to force rollback; otherwise, the transaction is committed.
Note: By default, the Spring framework transaction infrastructure only marks a transaction for rollback if it detects an unchecked exception. JCICS exceptions, such as a CICSConditionException are checked. In order to rollback for all exceptions (including the CICS checked exceptions), you can override the default behaviour with an explicit setting on the annotation as shown: @Transactional(rollbackFor=Exception.class).
To use the SpringTransactional class, you need to update TransactionController.java with a new method to autowire in an instance of the SpringTransactional class and then to drive it in response to a web request. Add the following code to your TransactionController.java class, which will map requests to the /transactionalCommit URL to the SpringTransactional method writeTSQ():
@Autowired SpringTransactional transactional;
/**
* Demonstrate Transactional annotation commit
* @return status message
*/@GetMapping({"/transactionalCommit", "/transactionalcommit"})public String transactionalCommit()
{
// Commit a TSQ write using Spring's @Transactional annotationtry
{
returnthis.transactional.writeTSQ("hello CICS from transactionalCommit()");
}
catch(Exception e)
{
e.printStackTrace();
return"transactionalCommit: exception: " + e.getMessage() + ". Check dfhjvmerr for further details.";
}
}
Show more
You can now deploy the application to CICS and run the request using the root URL with the new URL mapping, /transactionalCommit. You should see the web browser return hello CICS from transactionalCommit(). Browsing the TSQ called EXAMPLE using the CICS transaction CEBR will show the same string written to the TSQ as shown below.
CEBR TSQ EXAMPLE SYSID Z32A REC 1OF1 COL 1OF38
ENTER COMMAND ===>************************** TOP OF QUEUE *******************************00001 hello CICS from transactionalCommit()
************************* BOTTOM OF QUEUE *****************************
PF1 : HELP PF2 : SWITCH HEX/CHAR PF3 : TERMINATE BROWSE
PF4 : VIEW TOP PF5 : VIEW BOTTOM PF6 : REPEAT LAST FIND
PF7 : SCROLL BACK HALF PF8 : SCROLL FORWARD HALF PF9 : UNDEFINED
PF10: SCROLL BACK FULL PF11: SCROLL FORWARD FULL PF12: UNDEFINED
Show more
Now let's add a second end-point which calls the same SpringTransactional class, but this time with the text "rollback" in the message. Add the following code to TransactionController.java:
/**
* Demonstrate Transactional annotation rollback
* @return status message
*/@GetMapping({"/transactionalRollback", "/transactionalrollback"})public String transactionalRollback()
{
// Attempt to write to a TSQ// ...but when the string 'rollback' is detected in the input, we// intentionally throw a runtime exception which the @Transactional// annotation has been qualified to detect and trigger a rollback.try
{
returnthis.transactional.writeTSQ("rollback from transactionalRollback()");
}
catch(Exception e)
{
e.printStackTrace();
return"transactionalRollback: exception: " + e.getMessage() + ". Rollback triggered - see dfhjvmerr for further details.";
}
}
Show more
This time, if you use your browser to request the /transactionalRollback end-point you will be informed that an exception occurred and that rollback was driven. If you browse the TSQ again and see a second entry, this is because we haven't yet installed the TSMODEL definition into CICS in order to designate the TSQ as recoverable. If you hold off installing the TSMODEL, you can run the rest of this tutorial proving that code is executed and that TSQ entries are written; then install the TSMODEL, purge the TSQ, re-run the examples, and observe the differences when rollback takes effect.
Note: If application security is enabled in the target Liberty server, you also need to enable an authentication method and authorisation roles. To do this, you need to create a Jave EE web.xml file and place it in the src/main/webapp/WEB-INF/ folder. A sample web.xml file that supports basic authentication is provided in the associated Git repository. For further details on enabling security, refer to the previous tutorial in this series, Spring Boot Java applications for CICS, Part 2: Security.
5. Spring TransactionTemplate for Bean Managed Transactions
Now it's time to create a class to use Spring's TransactionTemplate interface for a Bean Managed Transaction. This will use Spring Boot's programmatic approach to managing transactions. The following snippet shows Spring's PlatformTransactionManager and TransactionTemplate classes being set-up and called ready to take the contents of our transactional code:
This allows you to programatically rollback the transaction by calling the method status.setRollbackOnly();.
Now let's create our new class, SpringTransactionTemplate.java, which includes the code snippets above. As we did for the previous SpringTransactional approach, if the keyword "rollback" is detected in the text of the string, after writing to the TSQ, we will issue a rollback.
Add the new class SpringTransactionTemplate.java to your project, which will provide two new endpoints, /STcommit and /STrollback:
package com.ibm.cicsdev.springboot.transactions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.ibm.cics.server.CicsConditionException;
import com.ibm.cics.server.TSQ;
/**
* This component demonstrates use of the Spring PlatformTransactionManager
* and TransactionTemplate to manage transactions in a Bean orientated
* manner.
*/@ComponentpublicclassSpringTransactionTemplate
{
@Autowiredprivate PlatformTransactionManager transactionManager;
/**
* @param text
* @return status message
*/public String writeTSQ(String text)
{
// Create transaction templateTransactionTemplatetranTemplate=newTransactionTemplate(this.transactionManager);
tranTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
// Execute the method to do the CICS update
tranTemplate.execute(newTransactionCallbackWithoutResult()
{
@OverrideprotectedvoiddoInTransactionWithoutResult(TransactionStatus status)
{
if (status.isNewTransaction())
{
System.out.println("SpringTransactionTemplate.writeTSQ(): Starting new transaction");
}
// Force a rollback if the input matches a specific stringif (text.contains("rollback"))
{
status.setRollbackOnly();
}
// Create JCICS TSQ objectTSQtsq=newTSQ();
tsq.setName(Application.TSQNAME);
// Write the string to the TSQtry
{
tsq.writeString(text);
}
catch (CicsConditionException e)
{
// If JCICS command fails// then force a rollback of the transaction (which rolls back the CICS UOW)
System.out.println("SpringTransactionTemplate.writeTSQ(): " + e.getMessage() + ". Unexpected exception, rollback");
status.setRollbackOnly();
e.printStackTrace();
}
}
});
return text;
}
}
Show more
To use this bean, you need to add some more code to your TransactionController to autowire in the SpringTransactionTemplate and to call your bean. Two methods are added -- one forces a rollback and the other a commit. Add the following code to TransactionController.java:
@Autowired SpringTransactionTemplate springTemplateTran;
/**
* Spring Template managed transaction commit web request
* @return message
*/@GetMapping({"/STcommit", "/stcommit"})public String springTemplateCommit()
{
returnthis.springTemplateTran.writeTSQ("hello CICS from springTemplateCommit()");
}
/**
* Spring Template managed transaction rollback web request
* @return message
*/@GetMapping({"/STrollback", "/strollback"})public String springTemplateRollback()
{
returnthis.springTemplateTran.writeTSQ("rollback from springTemplateRollback()");
}
Show more
Go ahead and use Gradle or Maven to rebuild your project now. If you are deploying through a CICS bundle project, update the generated CICS bundle project in zFS and then disable and re-enable the CICS bundle. If you chose to deploy with an <application> element and have <applicationMonitoring> active, when you upload a new version of the WAR, Liberty will stop the application and restart it at the new version; otherwise, you can restart the server to pick up changes.
To drive the two new methods, use a browser as before, but this time request the new /STcommit and /STrollback end-points. You will be greeted by each request, and the TSQ called EXAMPLE will be updated:
CEBR TSQ EXAMPLE SYSID Z32A REC 1OF4 COL 1OF38
ENTER COMMAND ===>************************** TOP OF QUEUE *******************************00001 hello CICS from transactionalCommit()
00002rollbackfrom transactionalRollback()
00003 hello CICS from springTemplateCommit()
00004rollbackfrom springTemplateRollback()
************************* BOTTOM OF QUEUE *****************************
PF1 : HELP PF2 : SWITCH HEX/CHAR PF3 : TERMINATE BROWSE
PF4 : VIEW TOP PF5 : VIEW BOTTOM PF6 : REPEAT LAST FIND
PF7 : SCROLL BACK HALF PF8 : SCROLL FORWARD HALF PF9 : UNDEFINED
PF10: SCROLL BACK FULL PF11: SCROLL FORWARD FULL PF12: UNDEFINED
Show more
6. Java EE UserTransaction approach to Bean Managed Transactions
In this final part of the tutorial, you'll learn how to use Liberty's Transaction manager directly from a Spring Boot application. This can be achieved by looking up the Java EE java:comp/UserTransaction context through JNDI and creating a UserTransaction object to perform a Bean Managed Transactions.
JTA in a CICS Liberty JVM server
In CICS, there is an implicit UOW for every task, so transaction management does not need to be explicitly started. For JTA, however, a container-managed transaction (CMT) annotation is required on a class or method, or a UserTransaction must be coded with the begin() method. A JTA transaction completes at the end of the annotation scope for CMT, or for a UserTransaction if the application reaches a UserTransaction.commit() or rollback(). If no commit or rollback is coded, the Liberty web container completes the transaction when the web request terminates.
To see a UserTransaction in action, let's create a new class called JEEUserTransaction.java as shown here:
package com.ibm.cicsdev.springboot.transactions;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.transaction.UserTransaction;
import org.springframework.stereotype.Component;
import com.ibm.cics.server.TSQ;
/**
* This class demonstrates the use of JNDI to look up a Java EE User Transaction context.
* It then uses the Java Transaction API (JTA) and Liberty's transaction manager to create
* and manage work within a global transaction - to which a CICS UOW is subordinate.
*/@ComponentpublicclassJEEUserTransaction
{
/**
* write to a TSQ from within a Java EE UserTransaction
*
* @param text
* @return status message
*/public String writeTSQ(String text)
{
// Look up the Java EE transaction context from JNDIUserTransactiontranContext= lookupContext();
// Write a message to the TSQtry
{
// Create a JCICS TSQ objectTSQtsq=newTSQ();
tsq.setName(Application.TSQNAME);
// Start a user transaction, write a simple phrase// to the queue and then commit or rollback.
tranContext.begin();
tsq.writeString(text);
if(text.contains("rollback"))
{
tranContext.rollback();
return"JEEUserTransaction.writeTSQ(): TSQ written then 'rollback' issued";
}
tranContext.commit();
return"JEEUserTransaction.writeTSQ(): TSQ written then 'commit' issued";
}
catch (Exception e)
{
e.printStackTrace();
return"JEEUserTransaction.writeTSQ(): unexpected exception: " + e.getMessage() + ". Check dfhjvmerr for further details.";
}
}
private UserTransaction lookupContext()
{
// Use JNDI to find the Java EE (Liberty) transaction manager
InitialContext ctx;
UserTransactiontran=null;
try
{
ctx = newInitialContext();
tran = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
}
catch (NamingException e)
{
e.printStackTrace();
System.out.println("JEEUserTransaction.lookupContext(): lookup failed: " + e.getMessage());
}
// return the UserTransaction contextreturn tran;
}
}
Show more
To use this new class, autowire it into your TransactionController and add two new methods to commit and rollback updates. Add the following code to TransactionController.java:
To complete the demo, let's update the application root to provide usage instructions rather than a simple greeting. Modify the index method in TransactionController.java as shown:
/**
* Provide a root for Usage: information
* @return usage message
*/@GetMapping("/")public String index()
{
return"<h1>Spring Boot Transaction REST sample</h1>"
+ "<h3>Usage:</h3>"
+ "<b>/transactionalCommit</b> - Demo Spring Transactional annotation commit <br>"
+ "<b>/transactionalRollback</b> - Demo Spring Transactional annotation rollback <br>"
+ "<b>/STcommit</b> - Demo Spring Template commit <br>"
+ "<b>/STrollback</b> - Demo Spring Template rollback <br>"
+ "<b>/JEEcommit</b> - Demo Java EE User Transaction commit <br>"
+ "<b>/JEErollback</b> - Demo Java EE User Transaction rollback";
}
Show more
Don't forget to rebuild and re-deploy the modified application. Then use the /JEEcommit and /JEErollback end-points to run the new methods. If you browse the TSQ EXAMPLE, you should now see the following additional lines added to the queue:
CEBR TSQ EXAMPLE SYSID Z32A REC 1OF4 COL 1OF38
ENTER COMMAND ===>************************** TOP OF QUEUE *******************************00001 hello CICS from transactionalCommit()
00002rollbackfrom transactionalRollback()
00003 hello CICS from springTemplateCommit()
00004rollbackfrom springTemplateRollback()
00005 hello CICS from javaEECommit()
00006rollbackfrom javaEERollback()
************************* BOTTOM OF QUEUE *****************************
PF1 : HELP PF2 : SWITCH HEX/CHAR PF3 : TERMINATE BROWSE
PF4 : VIEW TOP PF5 : VIEW BOTTOM PF6 : REPEAT LAST FIND
PF7 : SCROLL BACK HALF PF8 : SCROLL FORWARD HALF PF9 : UNDEFINED
PF10: SCROLL BACK FULL PF11: SCROLL FORWARD FULL PF12: UNDEFINED
Show more
7. Running the sample
To see the full effects of transaction updates on a TSQ in CICS from a Spring Boot application, you can delete the EXAMPLE queue using the PURGE command in the CEBR transaction. Then install the recoverable TSMODEL, which will mark the TSQ recoverable, and then run all six web requests again. With a recoverable TSQ in effect, the rollback-related writes will not be preserved and you should see the following output in the TSQ:
CEBR TSQ EXAMPLE SYSID Z32A REC 1OF4 COL 1OF38
ENTER COMMAND ===>************************** TOP OF QUEUE *******************************00001 hello CICS from transactionalCommit()
00002 hello CICS from springTemplateCommit()
00003 hello CICS from javaEECommit()
************************* BOTTOM OF QUEUE *****************************
PF1 : HELP PF2 : SWITCH HEX/CHAR PF3 : TERMINATE BROWSE
PF4 : VIEW TOP PF5 : VIEW BOTTOM PF6 : REPEAT LAST FIND
PF7 : SCROLL BACK HALF PF8 : SCROLL FORWARD HALF PF9 : UNDEFINED
PF10: SCROLL BACK FULL PF11: SCROLL FORWARD FULL PF12: UNDEFINED
Show more
Summary
This tutorial has demonstrated how to develop a Spring Boot application for CICS using transactional management. We presented three alternative ways to achieve transaction management in Spring Boot with CICS:
Spring's @Transactonal annotation
Spring's TransactionTemplate for Bean Managed transactions
The Java EE UserTransaction interface to directly drive the Java Transaction API (JTA)
About cookies on this siteOur websites require some cookies to function properly (required). In addition, other cookies may be used with your consent to analyze site usage, improve the user experience and for advertising.For more information, please review your cookie preferences options. By visiting our website, you agree to our processing of information as described in IBM’sprivacy statement. To provide a smooth navigation, your cookie preferences will be shared across the IBM web domains listed here.