Spring Boot Java applications for CICS, Part 1: JCICS, Gradle, and Maven

This tutorial is the first in a series on Spring Boot Java applications for CICS.

Learning objectives

Spring Boot provides a fast and simple way of configuring, building, and running Java applications. A Spring Boot application can run in a CICS Liberty Java environment without modification, and can be built as a web application archive (WAR) or a standalone JAR archive. A Spring Boot application can be deployed and managed using CICS bundles in the same way that you would with other CICS Liberty applications.

This tutorial will show you how to perform the following steps:

  1. Create a Spring Boot web application as a WAR and import it into Eclipse.
  2. Add some RESTful services that use the JCICS API to interact with a CICS temporary storage queue (TSQ).
  3. Build the application with Gradle or Maven using the JCICS and Spring Boot libraries deployed on Maven Central.
  4. Deploy the application into a CICS Liberty JVM server.

The application source and build scripts are available in the cicsdev/cics-java-liberty-springboot-jcics repository.

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.

Create a Spring Boot application using the Spring Initializr

Using Spring Initializr, create a WAR packaged project. This example uses group com.ibm.cicsdev.springboot and artifact cics-java-liberty-springboot-jcics with the latest currently available Spring Boot v2.3.0 as shown.

Spring Initializr image

  1. Generate and download the project for either Gradle or Maven.
  2. Unzip the project.
  3. Open the project in your preferred IDE. We will use Eclipse.
    • If you are using Gradle to build your application, you can install the Buildship Eclipse plugin and import the project using the Eclipse menu File > Import > Existing Gradle Project.
    • If you are using Maven, you can install the m2e Eclipse plugin and import the project using the Eclipse menu File > Import > Existing Maven Project.

With the Java source tree expanded in the Eclipse Package Explorer view, the generated Spring Boot Application and ServletInitializer classes should be visible as shown:

Java source tree image

The Application class uses the @SpringBootApplication annotation, which is a convenience annotation that adds all of the following annotations:

  • @Configuration tags the class to indicate that it contains Spring bean definitions.
  • @EnableAutoConfiguration tells Spring Boot to start adding beans based on configuration data (for example, setting up a DispatcherServlet for a web application).
  • @ComponentScan tells Spring to scan for components such as controllers.

The main() method uses Spring Boot’s SpringApplication.run() method to launch the application:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

The generated ServletInitializer class extends the SpringBootServletInitializer and overrides the configure() method, which uses SpringApplicationBuilder to register the class as a configuration class of the Spring Boot application. This allows you to package your application as a WAR and deploy it in the Liberty web container in a traditional way.

public class ServletInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

}

For more information, see the Spring documentation.

Add calls to the JCICS API

JCICS provides a simple object hierarchy for accessing the CICS API from Java, and is similar to the EXEC CICS command API that is supported for other languages such as COBOL or assembler. The example browseTSQ() method shows how the JCICS classes can be used to build an array of records from a TSQ:

    private ArrayList<String> browseTSQ(String tsqName) throws CicsConditionException, UnsupportedEncodingException {        
        ArrayList<String> records = new ArrayList<String>();
        TSQ tsqQ = new TSQ();
        tsqQ.setName(tsqName);
        ItemHolder holder = new ItemHolder();
        int itemPos = 1;
        int totalItems = 0;
        String recordStr = null;
        totalItems = tsqQ.readItem(itemPos, holder);
        recordStr = holder.getStringValue();        
        records.add(recordStr);
        while (itemPos < totalItems) {
            tsqQ.readNextItem(holder);
            recordStr = holder.getStringValue();
            records.add(recordStr);
            itemPos++;
        }
        return records;
    }

The JCICS TSQ class is used to interact with a named queue, and the ItemHolder class is used to hold the byte array that’s read from the queue. The CicsConditionException class represents the response codes that can be returned by the EXEC CICS API. For further information on how to use the JCICS API handle CICS response codes, refer to this CICS developer center article.

Creating the resource controllers

In Spring’s approach to building RESTful web services, HTTP requests are handled by a controller. These components are identified by the @RestController annotation. Here you will add four controller services to your test application to enable your application to interface with a CICS TSQ:

  • BrowseTSQController — write an item to a TSQ resource
  • DeleteTSQController — delete the TSQ
  • TSQInfoController — query information about the TSQ
  • WriteTSQController — read an item from the TSQ

Each of these classes uses the Spring @GetMapping annotation to define the URL for its service. The example below is for the BrowseTSQController service which handles an HTTP GET request for /browseTSQs by returning the records from a queue specified by the request parameter tsqName.

@RestController
public class BrowseTSQController {

    @GetMapping("/browseTSQs")
    public String browseTSQs(@RequestParam(value = "tsqName", defaultValue = "ANNE") String tsqName) throws IOException {

        ArrayList<String> records = new ArrayList<String>();
        try {        
            records = browseTSQ(tsqName);            
        } catch ( CicsConditionException e) {                        
            e.printStackTrace();            
            return "Oops! Unexpected CICS condition exception: "  + e.getMessage() + ". Please check stderr for details.";
        }        
        return records.toString();
    }
    ...
}

Add the four resource controller classes to the com.ibm.cicsdev.springboot.jcics package, using the samples provided in the GitHub repository. Your project should now look similar to this:

Adding JCICS

The next step is optional, and is only required if application security is enabled in the target Liberty server. To add in security, create a Jave EE web.xml file, and place this in the src/main/webapp/WEB-INF/ folder. A sample web.xml file that supports basic authentication is provided in the associated Git repository.

The last step is to update the build to download the necessary JCICS and Spring Boot JAR files. The JCICS API is provided by CICS in the com.ibm.cics.server.jar library in the $USSHOME/lib install directory on z/OS. However, when developing a Spring Boot application a build tool is typically used to build and package the application. This provides correct dependency resolution and a simple mechanism to package the large number of dependencies in a single runnable WAR.

Next, you’ll learn how to use either Gradle or Maven to download the required libraries from Maven Central into an Eclipse development environment and build the required WAR.

Configuring the Gradle build in Eclipse

If you’re using Gradle within Eclipse, the build.gradle file can be found in the root of the project. Double-click on this to edit the contents.

  1. First, make sure the Spring framework, dependency management, Java, Eclipse, and WAR plugins are all specified as follows. Plugins extend the project’s capabilities, and you will need each of these plugins to build the Spring Boot project in your Eclipse environment.

     plugins
     {
         id 'org.springframework.boot' version '2.3.0.RELEASE'
         id 'io.spring.dependency-management' version '1.0.9.RELEASE'
         id 'java'
         id 'eclipse'    
         id 'war'
     }
    
  2. Add in the following to ensure that Javadoc is available in Eclipse:

     eclipse
     {
         classpath
         {
             downloadJavadoc = true
         }
     }
    
  3. Check the following directives, which define the group name and set the base name and version string for the generated WAR:

     group = 'com.ibm.cicsdev.springboot'
     archivesBaseName='cics-java-liberty-springboot-jcics'
     version = '0.1.0'
    
  4. Ensure that the Maven Central repository for the build is specified correctly. Maven Central is a popular repository that hosts open source libraries for consumption by Java projects.

     {
       mavenCentral()
     }
    
  5. Define the dependencies that need to be resolved from Maven Central.

     dependencies 
     {
         implementation("org.springframework.boot:spring-boot-starter-web")         
         providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
         compileOnly enforcedPlatform("com.ibm.cics:com.ibm.cics.ts.bom:5.5-20200519131930-PH25409")
         compileOnly("com.ibm.cics:com.ibm.cics.server") 
     }
    

    The implementation("org.springframework.boot:spring-boot-starter-web") provides the Spring Boot web starter function for building web applications, including RESTful support using Spring MVC. Spring Boot starters can help to reduce the number of manually added dependencies just by adding one dependency.

    The providedRuntime("org.springframework.boot:spring-boot-starter-tomcat") statement ensures that the Tomcat libraries are packaged in the war file’s WEB-INF/lib-provided directory so that they will not conflict with the Liberty web container’s own classes.

    The compileOnly enforcedPlatform("com.ibm.cics:com.ibm.cics.ts.bom:5.5-20200519131930-PH25409") dependency is used to reference the CICS bill of materials (BOM) on Maven Central. The version specified should match the release and service level of the target CICS TS environment on z/OS; this allows you to set up the dependencies through Maven Central so that you don’t then have to obtain the CICS Java libraries from z/OS. The enforcedPlatform keyword ensures that the version specified overrides any other versions found in the dependency graph.

    In this example, you are referencing CICS TS V5.5, with the latest JCICS APAR PH25409. The full list of all CICS TS BOMs can be found on Maven Central. Make sure that you specify a BOM version that provides the support for the JCICS API you need in your application, and that your target CICS system is at the same or newer CICS TS release and APAR maintenance level.

    The compileOnly directive for the com.ibm.cics.server API package ensures that the JCICS library is not included in the runtime classpath, as the correct library will be provided by the CICS TS runtime itself and should not be packaged with the application. Note that you don’t specify the version of the JCICS package on this statement, as the BOM enforces the correct version.

  6. To build the project, select the Gradle Tasks view, expand the project com.ibm.cicsdev.springboot.jcics -> build folder, and run the bootWar build to create a WAR that contains the web applications. If you have previously built the project, you may also want to run a clean before building.

    bootWar build

    The result should appear in the Gradle Executions view as follows:

    Gradle Executions view

    If there are any problems reported, the Eclipse Console view can be used for further details. If the build was successful, you should see output similar to the following:

     > Task :compileJava
     > Task :processResources
     > Task :classes
     > Task :bootWar
    
     BUILD SUCCESSFUL in 34s
     3 actionable tasks: 3 executed
    

Note: It is also possible to specify more complex build options for a Gradle build by right-clicking on the project, selecting RunAs -> Run Configurations, and creating a Gradle Task run configuration that specifies multiple Gradle Tasks such as clean and bootWar.

If you refresh the view, you should now have a WAR file called cics-java-liberty-springboot-jcics-0.1.0.war in the build/libs folder. If you don’t see this folder in your source tree, it can be viewed using the Eclipse Navigator view as shown. If this view is not available it can be added to the Java perspective using Window -> Show view -> Navigator.

builtWar

Configuring the Maven build in Eclipse

If you’re using Maven within Eclipse, the pom.xml file will be found in the root of the project. Double-click on this to edit the contents and configure the build.

  1. First, make sure that the Spring framework and version are correctly specified in the spring-boot-starter-parent project. This is a special project that provides default configurations for Spring Boot applications along with a dependency tree to quickly build a Spring Boot project.

    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.0.RELEASE</version>
    </parent>
    
  2. Edit the following application properties, which set the group name and artifact ID along with the version and name for the WAR build:

     <groupId>com.ibm.cicsdev.springboot</groupId>
     <artifactId>cics-java-liberty-springboot-jcics</artifactId>
     <version>0.1.0</version>
     <packaging>war</packaging>
     <name>cics-java-liberty-springboot-jcics</name>
     <description>Demo project for Spring Boot with JCICS</description>
    

    Also, check that the build specifies Java 8:

     <properties>
         <java.version>1.8</java.version>
     </properties>
    
  3. Define the dependencies that need to be resolved from Maven Central as follows:

     <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> 
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>     
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-tomcat</artifactId>
             <scope>provided</scope>
         </dependency>    
         <dependency>
             <groupId>com.ibm.cics</groupId>
             <artifactId>com.ibm.cics.server</artifactId>
         </dependency>
     </dependencies>
    

    The dependency for com.ibm.cics.ts.bom is used to reference the CICS bill of materials (BOM) on Maven Central, and specifies the latest APAR maintenance version of CICS TS V5.5 which is currently 5.5-20200519131930-PH25409. (For more details on how to use the BOM, see the note above.)

    The dependency for spring-boot-starter-web provides the Spring Boot web starter function for building web applications, including RESTful support using Spring MVC. Spring Boot starters can help to reduce the number of manually added dependencies just by adding one dependency.

    The dependency for the spring-boot-starter-tomcat should specify <scope>provided</scope> so that the Tomcat libraries are packaged in the WAR file’s WEB-INF/lib-provided directory which means they will not conflict with the Liberty web container’s own classes.

    The dependency for the com.ibm.cics.server is for the JCICS API package and ensures that the JCICS library is not included in the runtime classpath; the correct library will be provided by the CICS TS runtime itself and should not be packaged with the application. Note that you don’t specify the version of the JCICS package on this statement, as the BOM enforces the correct version. Nor do you specify the scope (which should be <scope>provided</scope> to avoid it being packaged into the application) as the BOM sets that too.

  4. Make sure that the following packaging statement is defined to package the application as an executable WAR rather than a JAR:

       <packaging>war</packaging>
       <build>
         <plugins>
           <plugin>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
         </plugins>
       </build>
    
  5. To build the project, right-click the pom.xml file and select Run As -> Maven build. This opens a configuration dialog. Enter clean install for the Goals field, and click Apply and then Run.

    If the build was successful you should see output similar to the following in the Eclipse Console view, and a WAR file called cics-java-liberty-springboot-jcics-0.1.0.war will be created in the target folder:

     [INFO] Building war: C:\Users\IBMUser\Downloads\cics-java-liberty-springboot-jcics-master\target\cics-java-liberty-springboot-jcics-0.1.0.war
    
     [INFO] 
    
     [INFO] --- spring-boot-maven-plugin:2.3.0.RELEASE:repackage (repackage) @ cics-java-liberty-springboot-jcics ---
    
     [INFO] Replacing main artifact with repackaged archive
    
     [INFO] ------------------------------------------------------------------------
    
     [INFO] BUILD SUCCESS
    
     [INFO] ------------------------------------------------------------------------
    
     [INFO] Total time:  8.531 s
    
     [INFO] Finished at: 2020-06-05T14:05:53+01:00
    
     [INFO] ------------------------------------------------------------------------
    

Deploying the sample to CICS

There are a couple of ways to deploy a WAR into a CICS Liberty JVM server:

  • Add an <application> element to the Liberty server.xml that points directly to the WAR
  • Add the WAR to a CICS bundle project, export this to CICS, and install using a CICS BUNDLE resource definition

Further instructions on deploying the sample to CICS and testing the services can be found in the Git repository README.

Running the sample

The following URLs can be used to invoke the services provided in this application:

  • Write to the TSQ SPGJCICS — http://myzos.mycompany.com:httpPort/cics-java-liberty-springboot-jcics-0.1.0/writeTSQs?tsqName=SPGJCICS&tsqContent=ILOVECICS
  • Check the content of the TSQ SPGJCICS — http://myzos.mycompany.com:httpPort/cics-java-liberty-springboot-jcics-0.1.0/browseTSQs?tsqName=SPGJCICS
  • Information about the TSQ SPGJCICS — http://myzos.mycompany.com:httpPort/cics-java-liberty-springboot-jcics-0.1.0/TSQInfos?tsqName=SPGJCICS
  • Delete the TSQ SPGJCICS — http://myzos.mycompany.com:httpPort/cics-java-liberty-springboot-jcics-0.1.0/deleteTSQs?tsqName=SPGJCICS

Summary

This tutorial has demonstrated how to develop a Spring Boot application for CICS using Gradle or Maven, and how to deploy it into a CICS Liberty JVM server. After completing this tutorial you should be able to go on to use further APIs in your CICS Spring Boot applications such as JDBC, JMS, or JPA, and integrate with Spring Boot Transactions or Security. Check out the other tutorials in the Spring Boot Java applications for CICS learning path to take the next steps.