IBM® WebSphere® Front cover z/TPF Application Modernization using Standard and Open Middleware

Understanding extreme transaction rates and availability in SOA

Refacing z/TPF applications

Leveraging z/TPF in an open systems environment

Lisa Banks Bradd Kadlecik Mark Cooper Colette A. Manoni Chris Coughlin David McCreedy Jamie Farmer Carolyn Weiss Chris Filachek Joshua Wisniewski Mark Gambino

.com/redbooks

International Technical Support Organization z/TPF Application Modernization using Standard and Open Middleware

June 2013

SG24-8124-00 Note: Before using this information and the product it supports, read the information in “Notices” on page xi.

First Edition (June 2013)

This edition applies to z/TPF Enterprise Edition 1.1 PUT 9.

© Copyright International Business Machines Corporation 2013. All rights reserved. Note to U.S. Government Users Restricted Rights -- Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. Contents

Notices ...... xi Trademarks ...... xii

Preface ...... xiii Authors...... xiii Now you can become a published author, too! ...... xv Comments welcome...... xvi Stay connected to IBM Redbooks ...... xvi

Part 1. Overview ...... 1

Chapter 1. An introduction to z/TPF and its role in a service-oriented architecture . . 3 1.1 Introduction ...... 4 1.2 z/TPF and service-oriented architecture ...... 4 1.3 z/TPF and WebSphere Application Server ...... 4 1.4 Overview of z/TPF...... 5 1.5 TPF family of products ...... 5 1.6 Brief history of z/TPF ...... 6 1.7 Transaction ...... 6 1.8 Speed and reliability, availability, and scalability ...... 7 1.8.1 Speed and reliability...... 7 1.8.2 Availability ...... 9 1.8.3 Scalability...... 11 1.9 z/TPF features ...... 12 1.10 z/TPF analysis ...... 12 1.10.1 z/TPF core features ...... 12 1.10.2 z/TPF 64-bit support ...... 13 1.10.3 z/TPF open development...... 14 1.10.4 z/TPF application refactoring ...... 14 1.11 z/TPF summary ...... 15

Chapter 2. Technologies...... 17 2.1 Service-oriented architecture ...... 18 2.1.1 SOA and existing applications ...... 19 2.2 Web services ...... 20 2.2.1 XML ...... 21 2.2.2 SOAP ...... 21 2.2.3 Web Services Description Language ...... 22 2.2.4 Web Services Inspection Language ...... 23 2.2.5 Universal Description, Description, and Integration registry ...... 23 2.3 Extensible Markup Language...... 24 2.3.1 Basic XML format...... 24 2.3.2 Special characters ...... 25 2.3.3 Namespace...... 25 2.3.4 XML schema and XSD...... 26 2.4 Service Data Objects ...... 27 2.4.1 Service Data Object components...... 27 2.4.2 Service Data Object architecture ...... 28 2.5 Leveraging zEnterprise BladeCenter Extension (zBX) for web services...... 29

© Copyright IBM Corp. 2013. All rights reserved. iii Part 2. z/TPF as a provider in a service-oriented architecture ...... 31

Chapter 3. z/TPF SOAP processing...... 33 3.1 SOAP handler ...... 34 3.1.1 Web services deployment table ...... 36 3.1.2 SOAP message handler ...... 36 3.1.3 Web service wrapper ...... 37 3.1.4 z/TPF application ...... 37 3.1.5 Utility functions ...... 37 3.1.6 Resource management...... 38 3.2 SOAP fault builder...... 39 3.3 SOAP message encoding ...... 41 3.3.1 Character set translations ...... 41 3.4 SOAP structures ...... 49

Chapter 4. The z/TPF communications bindings ...... 55 4.1 Internet daemon ...... 56 4.1.1 The Internet daemon process models in detail ...... 56 4.2 SOAP over HTTP ...... 68 4.2.1 Apache 2.2...... 68 4.2.2 z/TPF HTTP Server...... 76 4.2.3 z/TPF HTTP server message processing ...... 77 4.2.4 z/TPF HTTP Server SOAP Message Processing ...... 78 4.3 SOAP over WebSphere MQ for z/TPF ...... 83 4.3.1 z/TPF WebSphere MQ overview ...... 84 4.3.2 The SOAP communications binding for WebSphere MQ ...... 86 4.3.3 WebSphere MQ over SSL ...... 93

Chapter 5. XML on z/TPF ...... 95 5.1 B2B XML scanner ...... 96 5.1.1 The infoNodes structure ...... 96 5.2 z/TPF XML APIs ...... 97 5.2.1 Processing XML documents ...... 97 5.2.2 Creating XML documents ...... 99 5.2.3 Creating an XML document fragment ...... 100 5.2.4 Sending binary data as part of an XML document ...... 101 5.2.5 Additional z/TPF XML APIs for append, insert, and modify ...... 102 5.2.6 Packing and unpacking an XML structure...... 104 5.2.7 Restrictions ...... 105 5.3 XML4C ...... 105 5.4 z/TPF XML APIs versus XML4C ...... 106

Part 3. z/TPF as a Web service provider and consumer ...... 107

Chapter 6. z/TPF application as a Web service provider...... 109 6.1 Defining the sample Web service ...... 110 6.2 Creating a SOAP message handler deployment descriptor ...... 113 6.3 Creating a provider Web service deployment descriptor...... 114 6.4 Creating a Web server wrapper ...... 117 6.5 Enabling z/TPF SOAP support ...... 123 6.6 Deploying a SOAP message handler to the z/TPF system...... 124 6.7 Deploying a Web service to the z/TPF system ...... 125 6.8 Writing a Web service wrapper for SOAP bridge support ...... 125 6.9 Deploying a Web service for SOAP bridge support ...... 126 iv z/TPF Application Modernization using Standard and Open Middleware Chapter 7. Accessing z/TPFDF databases through SDO ...... 127 7.1 Value of SDO access to z/TPFDF...... 128 7.2 Enabling SDO access ...... 128 7.2.1 Enabling SDO access for z/TPFDF...... 129 7.2.2 Enabling SDO on the client system...... 129 7.3 SDO examples ...... 130 7.3.1 Example credit database ...... 130 7.3.2 Example 1: Displaying purchases above $100.00 ...... 132 7.3.3 Example 2: Adding and updating security information ...... 135

Chapter 8. z/TPF SOAP consumer processing...... 139 8.1 SOAP consumer support ...... 140 8.2 SOAP consumer support components ...... 140 8.3 SOAP consumer message encoding support ...... 143 8.4 Understanding the z/TPF SOAP consumer APIs ...... 144 8.5 Setting up SOAP consumer communications handlers ...... 144 8.5.1 Using Hypertext Transfer Protocol ...... 144 8.5.2 Using z/TPF WebSphere MQ ...... 145 8.5.3 Using the z/TPF-to-z/TPF transport ...... 146 8.5.4 Using the z/TPF local transport...... 147 8.5.5 Using a user-specific transport ...... 147

Chapter 9. Using a z/TPF application as a Web service SOAP consumer ...... 149 9.1 Creating a consumer Web service ...... 150 9.2 Creating a SOAP message handler deployment descriptor ...... 150 9.3 Creating a consumer Web service deployment descriptor ...... 151 9.4 Creating or changing an application to use SOAP consumer support ...... 157 9.5 Creating a Web service stub ...... 158 9.5.1 Web service stub request processing ...... 166 9.5.2 Web service stub response processing ...... 166 9.5.3 Web service stub fault processing ...... 167 9.6 SOAP message handler response processing for a consumer Web service ...... 167 9.7 SOAP message handler fault processing for a consumer Web service ...... 167 9.8 Deploying a SOAP message handler to the z/TPF system...... 168 9.9 Deploying a consumer Web service to the z/TPF system...... 168

Part 4. SOA consumer ...... 171

Chapter 10. Using WebSphere Operational Decision Management to apply business rules ...... 173 10.1 The sample application ...... 174 10.2 Converting the application to use business rules ...... 174 10.2.1 Step 1. Creating an XML data representations of the parameters ...... 174 10.2.2 Step 2. Generating the programming artifacts from XML ...... 176 10.2.3 Step 3. Creating the Java execution object model (XOM) ...... 176 10.2.4 Step 4. Creating a Ruleset (Rule Project)...... 183 10.2.5 Step 5. Deploy the RuleApp and Rule Request Server ...... 186 10.2.6 Step 6. Create a RuleApp descriptor for z/TPF...... 187 10.2.7 Step 7. Deploy XML descriptors to z/TPF...... 188 10.2.8 Step 8. Update z/TPF application to call the business rule...... 188

Chapter 11. Business event processing ...... 191 11.1 Business event processing ...... 192 11.1.1 Business event processing architecture ...... 192

Contents v 11.1.2 How business event processing can help your business ...... 193 11.2 z/TPF and business event processing ...... 193 11.3 How z/TPF event processing works ...... 194 11.4 Business event deployment descriptors ...... 195 11.4.1 Business event specification...... 195 11.4.2 Business event dispatch adapter specification ...... 197 11.5 Common deployment ...... 198 11.5.1 Common deployment rules and conventions ...... 199 11.6 Enrichment program ...... 199 11.7 Business event dispatch queue ...... 200 11.7.1 Queue depth considerations ...... 200 11.7.2 Message length considerations ...... 201 11.7.3 Loosely coupled considerations ...... 201 11.7.4 Dispatch adapters ...... 201 11.8 Business event data format...... 201 11.8.1 tpf_bev_info ...... 202 11.8.2 Common Base Event format...... 203 11.8.3 Element and attribute details ...... 203 11.8.4 Example ...... 207 11.9 Business event processing monitor ...... 208 11.10 Enabling business event processing...... 208 11.11 Using business event processing ...... 209 11.11.1 Before you begin...... 209 11.11.2 Processing business events ...... 209 11.11.3 Results ...... 216 11.11.4 What to do next...... 216 11.12 Removing a loosely coupled processor ...... 216

Part 5. Security ...... 219

Chapter 12. z/TPF XML encryption ...... 221 12.1 Web services security ...... 222 12.2 Data confidentiality for web services...... 222 12.3 WS-Security ...... 223 12.4 Key aliases and client identification ...... 225 12.5 SOAP message handler extension file ...... 225 12.5.1 SOAP message handler extension program...... 226 12.6 Schema ...... 227 12.7 XML path language expressions supported by the z/TPF system ...... 227

Chapter 13. z/TPF WS-Security wrapper...... 229 13.1 Sample XML files ...... 230 13.1.1 SOAP provider files...... 230 13.1.2 SOAP message handlers ...... 232 13.1.3 SOAP consumer files ...... 233 13.1.4 Sample XML messages ...... 235 13.1.5 CalculatorService provider response before encryption ...... 237 13.1.6 CalculatorService provider response after encryption ...... 237 13.2 Client identification (cwscue.) ...... 238 13.3 Key mapping ...... 239 13.3.1 Decrypting inbound SOAP requests ...... 239 13.3.2 Encrypting outbound SOAP responses ...... 239 13.3.3 Mapping the key alias to real key name ...... 240 13.4 SOAP message handler extension file ...... 240 vi z/TPF Application Modernization using Standard and Open Middleware 13.4.1 Consumer extension file ...... 241 13.4.2 Provider extension file...... 241 13.5 WS-Addressing SOAP message handler ...... 242 13.5.1 Outbound requests ...... 242 13.5.2 Outbound responses ...... 243 13.5.3 Changing the wsa-addressing ...... 243 13.6 SOAP message handler extension program processing for a Web service deploy request 243 13.6.1 SOAP message handler extension program for WS-Security (cwsx.c) ...... 244 13.7 WS-Security Deployment ...... 244 13.7.1 Deploy the WS-Security SOAP message handler ...... 244 13.7.2 Deploying the WS-Addressing.xml SOAP message handler ...... 245 13.7.3 Deploying the web service provider and consumer ...... 245 13.8 Generating keys ...... 246 13.9 Running the application...... 246

Part 6. z/TPF in open systems ...... 249

Chapter 14. Porting open system applications to a z/TPF system...... 251 14.1 Open system Internet protocols support ...... 252 14.1.1 File Transfer Protocol client and server support ...... 252 14.1.2 Trivial File Transfer Protocol server support ...... 256 14.1.3 Hypertext Transfer Protocol server support ...... 257 14.2 Lightweight Directory Access Protocol ...... 258 14.2.1 LDAP directories ...... 258 14.2.2 Benefits of LDAP in a z/TPF environment...... 258 14.3 Structured Query Language ...... 259 14.3.1 LAMP ...... 259 14.3.2 Benefits of SQL on z/TPF ...... 260 14.4 Character conversion ...... 260

Chapter 15. z/TPF Internet mail server ...... 263 15.1 z/TPF Internet mail server overview ...... 264 15.2 z/TPF Internet mail server configuration files...... 266 15.2.1 SMTP server configuration file ...... 266 15.2.2 IMAP and POP server configuration file ...... 267 15.2.3 z/TPF-unique configuration information file...... 268 15.2.4 z/TPF mail server access list configuration file ...... 269 15.2.5 Aliases configuration file ...... 270 15.3 z/TPF Internet mail server administration ...... 270 15.3.1 Controlling the z/TPF Internet mail server...... 270 15.3.2 Managing client mailboxes ...... 273 15.3.3 z/TPF Internet mail server email administration ...... 275 15.4 z/TPF Internet mail server client ...... 277

Chapter 16. z/TPF HTTP client support...... 281 16.1 Support overview ...... 282 16.1.1 Connection modes ...... 282 16.1.2 Response modes ...... 282 16.1.3 HTTP client daemon ...... 282 16.2 Application programming interfaces ...... 283 16.3 Using the APIs ...... 284 16.3.1 Single ECB request mode...... 284 16.3.2 Multiple ECB request mode ...... 284

Contents vii 16.3.3 Shared sessions ...... 285 16.3.4 Asynchronous responses ...... 286 16.4 Examples ...... 287

Chapter 17. Additional examples of z/TPF in an SOA environment ...... 293 17.1 z/TPF, SOA, and existing applications ...... 294 17.2 The value of SOA ...... 294 17.2.1 A word about z/TPF ...... 295 17.3 z/TPF, SOA, and new applications ...... 295 17.3.1 z/TPF value...... 295 17.3.2 z/TPF and new designs ...... 296 17.4 z/TPF and SOA summary ...... 297

Part 7. Appendixes ...... 299

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system ...... 301 Basic work environment ...... 302 Creating a book project ...... 303 Creating the directory and source files using the shell...... 308 Adding content to the files ...... 312 cha0.c ...... 313 gettime.h ...... 314 gettime.cpp ...... 314 chao.mak ...... 317 The outputcatcher.cpp file...... 318 The chai.mak file...... 320 Saving the files ...... 321 Creating the makeTPF configuration and control files ...... 322 Updating the target environment properties ...... 322 Creating the MakeTPF configuration file...... 323 Creating the MakeTPF control file...... 328 Building the programs ...... 333 Loading the programs onto the z/TPF system ...... 334

Appendix B. Using the IBM TPF Toolkit web services tooling to create and deploy a web service ...... 339 Creating the WSDL file...... 340 Creating the provider web service deployment descriptor file ...... 347 Deploying the provider web service ...... 351 Testing the provider web service ...... 355

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools ...... 361 z/TPF debugger registration...... 362 Registering by program...... 362 Registering by function ...... 369 Registering by macro ...... 371 Registering by system error ...... 373 Registering by ctest ...... 375 Registering by user-defined ...... 377 The z/TPF debugger interface ...... 384 z/TPF Debugger problem determination methodology example ...... 388 Using the z/TPF Debugger dump viewer to debug application dumps ...... 394 The ECB Monitor subsystem ...... 400 viii z/TPF Application Modernization using Standard and Open Middleware The ECB Launcher subsystem ...... 404 The IBM TPF Toolkit and the z/TPF Performance Analyzer ...... 409 The IBM TPF Toolkit and the z/TPF Code Coverage Tool...... 414

Appendix D. TPF Toolkit wizards for WebSphere Operational Decision Management and Business Events ...... 427 The IBM TPF Toolkit Common Deployment Wizard ...... 428 IBM TPF Toolkit WebSphere Operational Decision Management Wizards ...... 434 Endpoint group descriptor file wizards ...... 434 RuleApp descriptor file wizard...... 437 IBM TPF Toolkit business events wizards ...... 441

Appendix E. XML file for SDO examples...... 449

Appendix F. Workarounds ...... 457 Invalid heap address ...... 458 Compile errors from c_node.h ...... 459 MakeTPF error MTPF0006E during build ...... 460

Related publications ...... 463 IBM Redbooks ...... 463 Online resources ...... 463 Help from IBM ...... 464

Contents ix x z/TPF Application Modernization using Standard and Open Middleware Notices

This information was developed for products and services offered in the U.S.A.

IBM may not offer the products, services, or features discussed in this document in other countries. Consult your local IBM representative for information on the products and services currently available in your area. Any reference to an IBM product, program, or service is not intended to state or imply that only that IBM product, program, or service may be used. Any functionally equivalent product, program, or service that does not infringe any IBM intellectual property right may be used instead. However, it is the user's responsibility to evaluate and verify the operation of any non-IBM product, program, or service.

IBM may have patents or pending patent applications covering subject matter described in this document. The furnishing of this document does not grant you any license to these patents. You can send license inquiries, in writing, to: IBM Director of Licensing, IBM Corporation, North Castle Drive, Armonk, NY 10504-1785 U.S.A.

The following paragraph does not apply to the United Kingdom or any other country where such provisions are inconsistent with local law: INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS PUBLICATION "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states do not allow disclaimer of express or implied warranties in certain transactions, therefore, this statement may not apply to you.

This information could include technical inaccuracies or typographical errors. Changes are periodically made to the information herein; these changes will be incorporated in new editions of the publication. IBM may make improvements and/or changes in the product(s) and/or the program(s) described in this publication at any time without notice.

Any references in this information to non-IBM websites are provided for convenience only and do not in any manner serve as an endorsement of those websites. The materials at those websites are not part of the materials for this IBM product and use of those websites is at your own risk.

IBM may use or distribute any of the information you supply in any way it believes appropriate without incurring any obligation to you.

Any performance data contained herein was determined in a controlled environment. Therefore, the results obtained in other operating environments may vary significantly. Some measurements may have been made on development-level systems and there is no guarantee that these measurements will be the same on generally available systems. Furthermore, some measurements may have been estimated through extrapolation. Actual results may vary. Users of this document should verify the applicable data for their specific environment.

Information concerning non-IBM products was obtained from the suppliers of those products, their published announcements or other publicly available sources. IBM has not tested those products and cannot confirm the accuracy of performance, compatibility or any other claims related to non-IBM products. Questions on the capabilities of non-IBM products should be addressed to the suppliers of those products.

This information contains examples of data and reports used in daily business operations. To illustrate them as completely as possible, the examples include the names of individuals, companies, brands, and products. All of these names are fictitious and any similarity to the names and addresses used by an actual business enterprise is entirely coincidental.

COPYRIGHT LICENSE:

This information contains sample application programs in source language, which illustrate programming techniques on various operating platforms. You may copy, modify, and distribute these sample programs in any form without payment to IBM, for the purposes of developing, using, marketing or distributing application programs conforming to the application programming interface for the operating platform for which the sample programs are written. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs.

© Copyright IBM Corp. 2013. All rights reserved. xi Trademarks

IBM, the IBM logo, and ibm.com are trademarks or registered trademarks of International Business Machines Corporation in the United States, other countries, or both. These and other IBM trademarked terms are marked on their first occurrence in this information with the appropriate symbol (® or ™), indicating US registered or common law trademarks owned by IBM at the time this information was published. Such trademarks may also be registered or common law trademarks in other countries. A current list of IBM trademarks is available on the Web at http://www.ibm.com/legal/copytrade.shtml

The following terms are trademarks of the International Business Machines Corporation in the United States, other countries, or both:

BladeCenter® OS/390® z/Architecture® CICS® Rational® z/OS® DB2® Redbooks® z/VM® developerWorks® Redbooks (logo) ® zEnterprise® IBM® System z® Orchestrate® WebSphere®

The following terms are trademarks of other companies:

Intel, Intel logo, Intel Inside logo, and Intel Centrino logo are trademarks or registered trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

Linux is a trademark of Linus Torvalds in the United States, other countries, or both.

Microsoft, Windows NT, Windows, and the Windows logo are trademarks of Microsoft Corporation in the United States, other countries, or both.

Java, and all Java-based trademarks and logos are trademarks or registered trademarks of Oracle and/or its affiliates.

UNIX is a registered trademark of The Open Group in the United States and other countries.

Other company, product, or service names may be trademarks or service marks of others.

xii z/TPF Application Modernization using Standard and Open Middleware Preface

In a world where product lifespans are often measured in months, the IBM® Transaction Processing Facility has remained relevant for more than four decades by continuing to process high volumes of transactions quickly and reliably. As the title of this book suggests, the z/TPF system uses open, standard interfaces to create services. Integration of new applications with existing z/TPF functions is a key factor in extending application capabilities. The ability for service data objects (SDO) to access the z/TPF Database Facility (z/TPFDF) provides a framework for data application program development that includes an architecture and application programming interfaces (APIs). SDO access to z/TPFDF provides remote client applications with access to z/TPF traditional data.

In the simplest terms, service-oriented architecture (SOA) is a means by which like, or unlike, systems can communicate with one another despite differences between each system's heritage. SOA can neutralize the differences between systems so that they understand one another. SOA support for z/TPF is a means by which z/TPF can interact with other systems that also support SOA. This book discusses various aspects of SOA in the z/TPF system, including explanations and examples to help z/TPF users implement SOA. IBM WebSphere® Application Server was chosen as the partner system as a means of demonstrating how a world class transaction server and a world class application server can work together. This book shows you how you can exploit z/TPF as a transaction server, participating in a SOA structure alongside WebSphere Application Server.

This IBM Redbooks® publication provides an introduction to z/TPF and the technologies critical to SOA. z/TPF is positioned as a provider or consumer in an SOA by supporting SOAP processing, communication bindings, and Extensible Markup Language (XML). An example is used to show how z/TPF can be used both as a Web service provider and as a consumer. A second example shows how to use WebSphere Operational Decision Management to apply business rules. A third example shows how business event processing can be incorporated in z/TPF applications. An example is also used to discuss security aspects, including z/TPF XML encryption and the z/TPF WS-Security wrapper. The main part of the book concludes with a discussion of z/TPF in an open systems environment, including examples of lightweight implementations to fit z/TPF, such as the HTTP server for the z/TPF system. The appendixes include information and examples using TPF Toolkit, sample code, and workarounds (with yes, more examples).

Authors

This book was produced by a team of specialists from around the world working at the International Technical Support Organization, Raleigh Center.

Lisa Banks is a Software Engineering Manager at IBM. She holds a Bachelor of Science in Engineering with a specialization in microprocessor design and a minor in Applied Mathematics from New Jersey Institute of Technology, where she graduated summa cum laude. She has seven years of experience in transaction processing on IBM z/Transaction Processing Facility (zTPF). Her expertise ranges from Control Program and Storage Devices to web services and service-oriented architecture. Lisa currently works for IBM Corporate Headquarters in the Corporate Technology Evaluation department. Her mission is to identify and shape technology strategy studies for the CEO and Technology Team, which serves as the collective Chief Technology Office (CTO) of IBM.

© Copyright IBM Corp. 2013. All rights reserved. xiii Mark Cooper is an Advisory Software Engineer at IBM in Poughkeepsie, New York. He earned his Bachelor of Science degree and Master of Science degree in Computer Science from SUNY Albany and later earned a Master of Business Administration degree from Marist College. Mark has served in many roles and worked on many projects during his 23 years of experience with the IBM Transaction Processing Facility lab. Areas of expertise include Multi-Processor Interconnect Facility, z/TPF Application Requestor (connecting z/TPF to IBM DB2®), and OpenLDAP, Berkeley DB, MySQL, POSIX threads, and communications.

Chris Coughlin is an Advisory Software Engineer at IBM in Poughkeepsie, New York. He earned his Bachelor of Science degree in Electrical Engineering from Clarkson University and a Master of Science degree in Software Development from Marist College. Chris is a Test Lead for z/TPF. His work focuses primarily on Control Program-related areas of the z/TPF .

Jamie Farmer is a Senior Software Engineer at IBM in Poughkeepsie, New York. He earned his Bachelor of Science degree in Computer Science from Ithaca College and later earned a Master of Science degree in Computer Science from Marist College. Jamie is one of the lead developers for two leading high-volume transaction processing platforms: IBM z/TPF and IBM WebSphere Transaction Cluster Facility (WTCF). Jamie has over 15 years of experience in designing and developing components of these platforms including network communications, cryptography and encryption, database management, and enterprise integration.

Chris Filachek is a Senior Software Engineer at IBM in Poughkeepsie, New York. He earned his Bachelor of Science degree in Computer Science from the University of Scranton and a Master of Science degree in Computer Science from the University of Pittsburgh. Chris is currently one of the lead developers for z/TPF. He has over 15 years of experience in designing and developing several components, including database management, C/C++ runtime environment, locking and synchronization, DASD support, and disaster recovery.

Mark Gambino is a Senior Technical Staff Member (STSM) at IBM in Poughkeepsie, NY. He is a Senior Architect for the z/TPF and WTCF high-end transaction processing product lines. He has over 24 years of experience in designing, developing, and testing numerous components of these platforms including network communications, security and encryption, database management, system performance and optimization, middleware, memory management, operating system task dispatching, application modernization including service-oriented architecture enablement.

Bradd Kadlecik is a Senior Software Engineer at IBM in Poughkeepsie, New York. He earned his Master of Science degree in Computer Science from Rensselaer Polytechnic Institute. Bradd has over 15 years of experience in designing and developing components of z/TPF including remote debugging, DASD support, various system utilities, and customer migrations.

Colette A. Manoni is a Senior Technical Staff Member and Architect for the TPF Family of products in the IBM Software Group. With over 28 years of experience, she is responsible for requirements, functional designs, and overall product solutions. Colette is also a Master Inventor and holds over 20 patents in the U.S., Japan, China, and several other countries. She earned a Bachelor of Science degree in Computer Science from Rensselaer Polytechnic Institute.

David McCreedy is an Advisory Software Engineer at IBM in Denver, Colorado. He earned his Bachelor of Science degree in Computer Information Systems from DeVry Institute of Technology. David has close to three decades of programming and design experience with z/TPF. He spent fourteen years at United working on software for the Apollo (US-based), Gemini (Canadian), and Galileo (European) computer reservation systems. He was the engineer for the group responsible for electronic data interchange between Apollo

xiv z/TPF Application Modernization using Standard and Open Middleware and other air, car, hotel, rail, and cruise systems. For the last fifteen years David has been with IBM, porting and contributing to Open Source Software projects, such as the Apache HTTP server, the XML parser for C++ (XML4C), Perl, and cURL.

Carolyn Weiss is an Advisory Software Engineer at IBM in Denver, Colorado. She earned her Bachelor of Science degree in Computer Information Systems from Regis University. Carolyn has 23 years of program and design experience with z/TPF. Before joining IBM, Carolyn spent several years programming for on the Apollo reservation system. At IBM now for 15 years, her focus is on Open Source Software (Apache HTTP server, XML4C parser, Perl) and standards-based messaging (XML and SOAP).

Josh Wisniewski is Senior Software Engineer at IBM in Poughkeepsie, New York. He has over 12 years of experience designing, developing, and maintaining various features for the high-volume transaction processing platforms IBM z/Transaction Processing Facility (z/TPF) and IBM WebSphere Transaction Cluster Facility. He has served as a technical lead, customer liaison, developer, architect, and project manager for z/TPF debugger technologies, z/TPF Tooling, and WebSphere Transaction Cluster Facility application development. He earned his Bachelor of Science degree from Clarkson University with a major in Computer Engineering.

Thanks to the following people for their contributions to this project:

Carla Sadtler Stephen Smith KaTrina Love International Technical Support Organization, Raleigh Center

Ellen Smyth IBM US

Allan Feldman IBM US

Laura L. Underhill IBM US

Thanks to the authors of the previous editions of this book.  Authors of z/TPF and WebSphere Application Server in a Service Oriented Architecture, SG24-7309, published in April 2007, were: Joe DeCarlo, Barry Baker, Edwin van de Grift, Jason Keenaghan, Dong Jun Lan, Bill Supon, Stuart Waldron, Dan Weber

Now you can become a published author, too!

Here’s an opportunity to spotlight your skills, grow your career, and become a published author—all at the same time! Join an ITSO residency project and help write a book in your area of expertise, while honing your experience using leading-edge technologies. Your efforts will help to increase product acceptance and customer satisfaction, as you expand your network of technical contacts and relationships. Residencies run from two to six weeks in length, and you can participate either in person or as a remote resident working from your home base.

Find out more about the residency program, browse the residency index, and apply online at: ibm.com/redbooks/residencies.html

Preface xv Comments welcome

Your comments are important to us!

We want our books to be as helpful as possible. Send us your comments about this book or other IBM Redbooks publications in one of the following ways:  Use the online Contact us review Redbooks form found at: ibm.com/redbooks  Send your comments in an email to: [email protected]  Mail your comments to: IBM Corporation, International Technical Support Organization Dept. HYTD Mail Station P099 2455 South Road Poughkeepsie, NY 12601-5400

Stay connected to IBM Redbooks

 Find us on Facebook: http://www.facebook.com/IBMRedbooks  Follow us on Twitter: http://twitter.com/ibmredbooks  Look for us on LinkedIn: http://www.linkedin.com/groups?home=&gid=2130806  Explore new Redbooks publications, residencies, and workshops with the IBM Redbooks weekly newsletter: https://www.redbooks.ibm.com/Redbooks.nsf/subscribe?OpenForm  Stay current on recent Redbooks publications with RSS Feeds: http://www.redbooks.ibm.com/rss.html

xvi z/TPF Application Modernization using Standard and Open Middleware Part 1

Part 1 Overview

Part 1of the book provides an introduction to z/TPF, its role in a service-oriented architecture, and the encompassing technologies. This part contains the following chapters:  Chapter 1, “An introduction to z/TPF and its role in a service-oriented architecture” on page 3  Chapter 2, “Technologies” on page 17

© Copyright IBM Corp. 2013. All rights reserved. 1 2 z/TPF Application Modernization using Standard and Open Middleware 1

Chapter 1. An introduction to z/TPF and its role in a service-oriented architecture

This chapter provides an introduction to the goals and objectives of this book. It also introduces you to the characteristics of the product that make it uniquely suited for highly demanding transaction processing requirements. A brief history of the product is also included.

This chapter contains the following topics:  1.1, “Introduction” on page 4  1.2, “z/TPF and service-oriented architecture” on page 4  1.3, “z/TPF and WebSphere Application Server” on page 4  1.4, “Overview of z/TPF” on page 5  1.5, “TPF family of products” on page 5  1.6, “Brief history of z/TPF” on page 6  1.7, “Transaction” on page 6  1.8, “Speed and reliability, availability, and scalability” on page 7  1.9, “z/TPF features” on page 12  1.10, “z/TPF analysis” on page 12  1.11, “z/TPF summary” on page 15

© Copyright IBM Corp. 2013. All rights reserved. 3 1.1 Introduction

z/Transaction Processing Facility, Enterprise Edition V1.1 (z/TPF) is the IBM high-end System z® based operating system designed specifically for the demanding transaction processing industry. z/TPF is based upon TPF 4.1, a platform that today is processing billions of transactions a year throughout the travel and finance industries. z/TPF, along with its co-requisite database facility (z/TPFDF) brings forward an extremely robust solution to the high-volume transaction processing arena, providing users with competitive marketplace advantages. z/TPF sets the standard for transaction processing capabilities.

1.2 z/TPF and service-oriented architecture

The z/TPF mission is the efficient and reliable processing of transactions. This function, however, is only one part of a solution required in any industry. The modern IT solution has to incorporate and integrate many functions, and therefore multiple products, to address the requirements of the business process. Ideally, these systems are integrated seamlessly, to improve the customer experience while maintaining a reasonable level of cost. To this end, z/TPF is expanding upon its ability to participate in a service-oriented architecture (SOA), an architecture designed to allow seamless connectivity across heterogeneous systems.

It can be said that SOA is the computer industry’s response to the changing requirements of business, and z/TPF incorporates SOA while embracing open standards to support current and future development requirements. See Chapter 2, “Technologies” on page 17 for more information about SOA technologies.

Enabled as such, z/TPF is structured to fully protect existing investments while allowing the user to leverage emerging technologies. By enabling standards, such as web services, XML, and Message-Oriented Middleware, z/TPF allows its users to have this most robust of transaction based operating systems participate in an SOA solution.

1.3 z/TPF and WebSphere Application Server

WebSphere Application Server is the implementation by IBM of the Java 2 Enterprise Edition platform. Available for a variety of platforms to meet a wide range of customer requirements, WebSphere Application Server provides an application infrastructure that can help you integrate application services into your services-oriented architecture. For more details about the various WebSphere Application Server options, visit the following website:

http://www.ibm.com/software/webservers/appserv/was/

z/TPF processes transactions well; however, it might not be the platform of choice used to implement application-server based solutions. The business process should drive the selection of I/T platform, and not the other way around. If a reliable high-volume transaction server is required, z/TPF is the best selection. If you have to convert your business processes into application-based solutions, WebSphere Application Server can provide you with a variety of functions to meet your business requirements. The combination of the two can give you the competitive advantages your business requires in an on-demand environment.

This book shows you how you can exploit z/TPF as a transaction server, participating in an SOA structure alongside WebSphere Application Server as a potential solution to provide your IT requirements.

4 z/TPF Application Modernization using Standard and Open Middleware 1.4 Overview of z/TPF

z/TPF is the IBM specialized System z operating system and transaction processor for high-end, high-volume, high-bandwidth computing. Designed to excel in the most demanding operational requirements, z/TPF is optimized for large scale computing, taking every advantage of the outstanding memory and I/O management capabilities of the IBM System z family.

z/TPF and its predecessor, TPF, have been serving the mission-critical requirements of worldwide businesses for over 30 years. Raw power, huge networks, high availability, and speed are the characteristics of z/TPF users’ operating environments today.

Originally the result of a project in the early 1950s between IBM and several airlines, z/TPF has been continually enhanced and remains at the core of a majority of worldwide reservation systems. TPF moved into the finance industry in the 1980s and remains core to the credit and debit card industry.

Setting the standard for performance, z/TPF delivers outstanding:  Speed  Reliability  Availability  Scalability

z/TPF is most appropriate for the enterprise whose business model justifies the investment in a processing complex optimized to operate at the lowest possible cost per transaction.

Today, TPF is installed in various industries including Travel, Finance, and Public Sector. More than 90% of all airline reservations and 90% of all credit card authorizations are processed using z/TPF.

1.5 TPF family of products

Throughout this book, we refer to several products that the TPF Family of Products comprises, and therefore a brief introduction to each product is warranted.

As previously stated, z/TPF is a System z based operating system. Announced in 2004, z/TPF is the successor in a long line of systems whose mission has been to provide a high-end transaction processing platform. z/TPF’s predecessors include TPF and ACP.

z/TPFDF, the z/TPF Database Facility, is co-requisite to z/TPF itself. z/TPFDF provides the z/TPF programmer with a higher level interface to the z/TPF database, maintaining the performance attributes of z/TPF itself while offering both virtualization of the z/TPF data constructs and improved maintainability and accessibility. z/TPFDF is the successor to TPFDF, which in turn is based upon the TPF customer-developed TPFDB and ACPDB.

The IBM TPF Toolkit is an application development platform built on the open and standards-based Eclipse tooling framework. The IBM TPF Toolkit includes a programmable editor, C/C++/Assembler build support, full-featured debugger, performance analyzer, high-performance remote file transfer mechanism, and much more.

The TPF Operations Server is a console automation and enhancement application for the TPF system. This PC-based application provides a tool for the administration and maintenance of your TPF system through TPF operations consoles. The TPF Operations Server runs outside the TPF system complex and allows you to monitor your TPF system,

Chapter 1. An introduction to z/TPF and its role in a service-oriented architecture 5 automate operational tasks, and diagnose problems quickly and accurately, thereby improving the productivity of your operations staff and enhancing system availability.

For more information about any of the TPF Family of Products, see the IBM TPF website at: http://www.ibm.com/tpf

1.6 Brief history of z/TPF

As previously mentioned, z/TPF has a long and respected heritage. The story of the z/TPF origin is reported to begin with a chance meeting in the 1950s between an executive in the travel industry and an executive from IBM. This meeting, which is rumored to have occurred on an airplane, started discussions that led to the exploitation of into the business of airlines reservations. The problem that had to be addressed was the management of the inventory of available seats on available flights. Prior to this chance meeting, there had been some use of the emerging technology of computerization into the airline travel system, however quite rudimentary.

This meeting led to the development of the first computerized reservation systems. During the late 1950s and early 1960s, IBM partnered with each of several airlines (, Delta Airlines, and PanAm) to develop airline-specific solutions. These were the SABRE, the Deltamatic, and the Panamac systems.

The release of the IBM S/360TM series of computers and the concept of a standard reusable platform was the catalyst that took the lessons and skills learned during these individual efforts and resulted in the Programmed Airline Reservation System (PARS) — perhaps the first general purpose solution for managing reservations in the airline industry. PARS, and its world wide version, International Programmed Airline System (IPARS), contain the function of each the operating system component and the applications layer.

It was not until 1969 that IBM split this merged system into two components, and focused on the operating system called the Airline Control Program (ACP).

ACP was enhanced during the 1970s, primarily to take advantage of new hardware and networking technologies. Renamed to TPF in 1980 to reflect, the product continued to see innovative solutions created to meet the availability and scalability demands of the ever expanding transaction-based solution.

This trend continued in the 1990s, with enhancements to the TPF platform being made to meet the requirements for connectivity, availability, scalability, and reliability. Renamed to z/TPF as a result of the implementation of the IBM zArchitecture, this product continues to innovate and evolve to help industries that require high end transaction computing solutions.

1.7 Transaction

To understand some of the details that describe why z/TPF excels as a transaction processor, it is helpful for you to have a basic understanding of the definition of a transaction.

For the purposes of this discussion, a transaction is a relatively small unit of work that represents a portion of, and not necessarily an entire, business process. As an example, a business process might be the act of purchasing a reservation for a seat on an airline. A subcomponent of this business process is a request of the list of flights with the desired origin and destination. This request is an example of a transaction, where an inquiry is formed and

6 z/TPF Application Modernization using Standard and Open Middleware submitted to the reservation system, a lookup is performed to collect the data, and that data is then formatted and returned to the requester.

This example can be compared to a batch job, for example, processing a payroll. It is unlikely that the payroll processing for a corporation would be performed one individual at a time; instead, it is more likely that a request would be made to the system to perform a task on behalf of all employees. The response to the requestor, perhaps in the form of a box full of printed checks, does not occur until processing of all employees has been completed.

Other examples of a transaction include a request to allow authorization of a charge against a specific credit card, sending a single text message from a phone, and logging a transmission about the status of an object containing a radio frequency identifier (RFID) chip.

The key difference between transactions, and batch, is response time. Transaction-based solutions demand that responses be sent to the requestor in real time.

It is this function at which z/TPF excels, processing transactions.

1.8 Speed and reliability, availability, and scalability

z/TPF has all of these characteristics, but what does this really mean? This section provides an explanation.

1.8.1 Speed and reliability

Reliability can be defined as the ability of a system to perform its given mission well and consistently. In more practical terms, this means the efficient processing of each transaction (speed), independently of one another. This allows for consistent results as seen by the requester.

To meet the reliability expectations in a high-demand transaction-based complex, the infrastructure of the system must be efficient. z/TPF has these built in efficiencies. If we look at several of the key architectural components of z/TPF, we can see examples of how this is done.

Disk I/O As technology improves, disk subsystems have become more responsive and intelligent, in an attempt to improve performance and reduce unavailability. Technologies, such as data caching, data striping, and error checking, are becoming more and more prevalent. For example, Redundant Array of Inexpensive Devices (RAID) arrays are readily available for the home user.

Looking at z/TPF and its predecessors, we see that similar technologies have been part of the operating system for decades. While it would be incorrect to imply that TPF invented the concepts behind the various technologies, an examination of z/TPF demonstrates that the same philosophies that are part of several of the RAID definitions are implemented within software with z/TPF.

One of these technologies is data striping. z/TPF (and the user) allocates the data that forms z/TPF’s equivalent of a file, horizontally across a database. The first record of a record type (z/TPF equivalent of a file) is located on the first disk in the database, the second record is on the second disk, and so on. This allows z/TPF to perform multiple concurrent I/O when

Chapter 1. An introduction to z/TPF and its role in a service-oriented architecture 7 retrieving related data from a file, shortening the elapsed time a process has to wait for the data to be available for processing.

z/TPF also has a built-in data caching function, called Virtual File Access (VFA). Managed by the system kernel, VFA allows for the caching of disk I/O within the processor's memory. The efficiencies of z/TPF memory management leave substantial memory available for other purposes. VFA is a processor-based caching function that takes advantage of this “spare” memory.

By permitting the caching of data within the processor, VFA can provide a tremendous boost to the performance of a z/TPF system. Typical z/TPF systems might have anywhere from an 80% to 95% “read hit ratio” within VFA, meaning that 80% to 95% of the read I/O are satisfied without the cost of going to the disk subsystem. By eliminating the actual I/O, the path-length for the transaction is also reduced.

Be aware that VFA caching is in addition to the caching provided in most disk subsystems.

Light-weight process model In the prior section, we spoke about some of the efficiencies provided by z/TPF's I/O architecture. However, a fast I/O mechanism is just one component of the processing of a transaction. z/TPF is also designed around a light-weight process model.

A light-weight process is often defined as a process that is managed at the kernel level, a kernel-level thread — as compared to a process managed by the application, called a heavy-weight process. All else being equal, the fewer instructions that have to be executed to service a transaction, the faster the response can be sent to the requester.

One example of how z/TPF reduces the path-length of a transaction can be seen in the memory management model. z/TPF preallocates memory based upon user-defined configuration tables.

In addition, z/TPF only allows the user to predefine three sizes of memory. The user can select from memory blocks of 381 bytes, 1055 bytes, or 4096 (4K) bytes. z/TPF heap storage is treated slightly differently because the user can define the sizes of the heap memory blocks to be preallocated. The result of having a limited number of memory block types, and by preallocation, is that the z/TPF memory manager can quickly reply to the request.

Networking efficiencies A third area of efficiency within z/TPF is its network management. It would naturally not be enough to implement fast data access and short instruction path-length. An efficient system has to handle traffic coming into, and leaving, the system with the same level of effectiveness.

An example of the efficiencies built into the z/TPF networking component is the Activate On Receipt (AOR) functionality. This philosophy can be seen in the z/TPF TCP/IP and shared SSL components.

The goal of AOR is to permit a large number of active connections (sockets) while having few associated processes actually active. There are several benefits of this philosophy. By having fewer active processes dedicated to the active connection, more processes can exist within the system concurrently, since common resources (such as memory) are not being used unnecessarily. In addition, not having to manage the active processes results in less system overhead.

In a transaction processing system, especially a system designed to handle a large number of concurrent users, a large amount of resources would be tied up waiting to be called upon if the traditional model of having a process “listening” for activity were to be used. It would not

8 z/TPF Application Modernization using Standard and Open Middleware be unusual for a z/TPF system to handle tens of thousands of requests per second. Having tens of thousands of “listeners” is not an efficient use of memory. The AOR concept of z/TPF communications puts the burden of listening on the z/TPF kernel. A function — for example, a web server — would simply indicate that it is available for business, telling the system who to “wake up” when a request comes in. z/TPF records this fact, and rather than having a Web server process listening for input on a specific port, z/TPF itself would listen. When activity is requested, z/TPF would recognize what function is to be called and activate that program on receipt of the input.

1.8.2 Availability

The prior section describes several examples to show how z/TPF can process transactions efficiently.

z/TPF strives to be a 24x7 system. That is to say, it is constantly available. As reported by the International Technology Group (see “Related publications” on page 463), in a study of 14 TPF users, seven of the 14 experienced no significant outage of any kind during 2001 (the year prior to the study), and 12 of the 14 (85%) had no unplanned outages. Eliminating two small users who accounted for a disproportionate number of outages, the remainder achieved availability of more than 99.999 percent — and over 99.9995 percent if planned outages are ignored. This means that the system was available for all but several minutes a year.

z/TPF has incorporated improvements to help reduce this number even further in the years since this study. The next section discusses several of the availability functions within z/TPF.

Database redundancy Perhaps one of the most obvious functions implementing availability within z/TPF is within the disk subsystem. As described previously, z/TPF strips data horizontally across a database. This is similar to the ideas presented in the RAID architecture definition.

z/TPF also has the concept of redundancy built into the nucleus of the system to help eliminate outages that can be caused by the loss of a data subsystem component. z/TPF maintains two copies of all disk-based data (however, there are exceptions that are user controlled). Each time a disk write is performed, the data is written to each of two individual disks in the database. These are commonly known as the primary (prime) and duplicate (dupe) copy of the data.This technology is somewhat similar to the concepts used in RAID architecture, which is called mirroring.

With z/TPF's mirroring, the loss of a single volume has a negligible effect on the performance of the system. A read to a data record is satisfied on the remaining volume, while writes continue to that volume too. A full 50% of the database can be lost, in fact, without causing an outage — granted that both copies of a single logical volume cannot be taken offline without impact to the system. Utilities are provided that allow a lost volume to be brought back online and brought into sync with its primary.

Online maintenance Databases require maintenance, and the maintenance of databases usually requires an outage. This even included TPF; however, ongoing work has focused on reducing and, in many cases, eliminating outages due to maintenance on the z/TPF database. The details of these functions are beyond the scope of this document; however, briefly described, the z/TPF database is an enormous collection of records.

After a record is used, it can be returned to the system for use by another process later on. To help prevent the loss of data, however, the recovery of the record is not immediate. An

Chapter 1. An introduction to z/TPF and its role in a service-oriented architecture 9 application indicates that a data record is no longer required, and then releases the record to the system, but the system simply maintains a list of such records.

The reason for this is data integrity. If the data record were to be re-used, immediately, and accidentally, the existing data would be lost. A delayed return allows for the recovery of the data, if necessary. Eventually, the system would be depleted of records unless these discarded records were returned to the system. This is accomplished through a series of utilities. Relatively recent updates in TPF to this utility to allow recovery without any interrupt to production level processing eliminated one of the key causes of regularly scheduled planned outages in z/TPF.

Entry protection Each transaction flowing into z/TPF causes the creation of a process in z/TPF that acts upon various pieces of data to eventually return the results to the requester. z/TPF design is such that each process has (nearly) no visibility to other processes. Mechanisms are provided to allow processes to communicate when required. In general, each process has its own memory space and cannot access another process, and therefore cannot corrupt it. As such, while the abnormal termination of a single process causes a failure of that transaction, it is nearly impossible for that process to cause other transactions to terminate — thus protecting the other transactions and the system itself. z/TPF does offer the flexibility for a process to create threads that a memory space. When such a thread terminates abnormally, z/TPF allows the process to exit or just the terminating thread to exit. Threads only operate within a single process and cannot affect other processes in the system.

Clustering Called loosely coupled in z/TPF nomenclature, clustering has been a part of the TPF product since the early 1980s. The z/TPF loosely coupled function allows the user to have up to 32 unique images of z/TPF working against a single database. This naturally provides performance capacities, as discussed later, but also provides failover capabilities. The failure of a z/TPF image can be nullified if a second image is already running. Recovery is simply a matter of rerouting traffic to the remaining active images. With functions, such as Virtual IP Addressing (VIPA) within the z/TPF software, this can be virtually instantaneous.

Recovery The previous sections focused on the descriptions of some of the architectures within z/TPF that give it its availability characteristics. This is not to say that a z/TPF system cannot have a catastrophic error. In these cases, z/TPF endeavors to recover as quickly as possible to eliminate the impact to the end-user community.

As an example, when such a failure occurs, z/TPF examines the integrity of the memory of a system. Unless the error that causes the problem is a result of damaged memory data or is thought to have caused it, z/TPF recycles, but without clearing the data areas. As such, after recovered, z/TPF can get back to full speed quickly. The best example of this is the aforementioned VFA. Any cache is only effective after it has been populated. If z/TPF were to clear VFA during a catastrophic error, that memory would have to be repopulated with data records following recovery. Performance would suffer until the standard I/O process was able to fill up VFA memory such that this component can provide the system with the caching efficiencies.

Another example of functions added to z/TPF to improve both availability and recovery characteristics is dump buffering. Unfortunately, errors can still occur within a z/TPF system, either in the application, or in the system itself. TPF takes a memory dump when such situations occur, allowing processing to continue while the data required to debug the problem is later made available to the programming staff.

10 z/TPF Application Modernization using Standard and Open Middleware Prior to z/TPF, this typically meant short delays to processing transactions as the state of the system was saved to a device (typically a tape) for offline processing. The system would have to pause other processing such that the data within the system can be captured without being altered by a subsequent transaction. z/TPF takes advantage of the extended memory available in the IBM 64-bit z/Architecture® and captures this data to memory that is reserved for this function. By eliminating the I/O to tape drives during the actual state save, processing continues in substantially less time than with prior versions of TPF.

1.8.3 Scalability

z/TPF customers include those who have the largest demands for transaction processing solutions: airline and rail reservation systems, banking transfer, and credit card authorization systems. As such, TPF always had a requirement to grow large. The following topics include examples of some of the capacity levels of a z/TPF system.

Processors As previously mentioned, z/TPF has clustering capabilities. With z/TPF, up to 32 unique z/TPF images can be joined together to act against a single database. This provides a backup, but also capacity. In System z terms, this means that you can have up to 32 individual z/TPF logical partitions (LPARs) running in a cluster, and those LPARs can be on a single or multiple CPUs.

CPUs The z/TPF system supports up to 86 engines, or I-streams, per image. This means that in a 32-way loosely-coupled z/TPF complex, 2752 System z-class engines can act upon a single database. The capacity to have multiple engines in a single z/TPF image is typically referred to as tightly coupled. A tightly coupled z/TPF image allows two or more engines to share a single memory.

Millions of Instructions Per Second (MIPS) are frequently used as a measurement of mainframe processor speed. Performance experts tell you that MIPS can be misleading because they fail to take into account workload profiles. This is true. The actual number of instructions processed in a second depends on many factors. For an interesting discussion about this topic, review the following file: http://zjournalarchives.com/PDF/deitchoct.pdf

Utilizing some of the standard metrics used to define the MIPS of a System z processor, this 2752- engine system would contain over 4 BIPS (billions of instructions per second) of processing power. Note that you should not use this figure for any planning purposes. Consult with your IBM support team to learn more about how to perform capacity planning for a z/TPF system.

Memory The z in z/TPF stands for z/Architecture, meaning 64-bit memory addressing capacity. If you do the math, 2**64 bytes of memory — that is to say, 16 exabytes — works out to be 18,446,744,073,709,551,616 bytes. This represents the possible addressing capability of the z/TPF system, which well exceeds the amount of memory currently available on any IBM System z system; however, by supporting 64-bit addressing, z/TPF can take advantage of all of the memory available on the system. This can be compared to TPF4, z/TPF’s immediate predecessor, which had 31-bit addressing capability. Very large TPF4 users found that they might be memory-bound by only being able to address 2 gigabytes of memory.

Chapter 1. An introduction to z/TPF and its role in a service-oriented architecture 11 Disks z/TPF allows connectivity of up to 40,000 disks — each with up to 32K cylinders. z/TPF disk systems are, like its memory, formatted to preallocate record sizes. If using the most efficient of these (4K records), z/TPF can address up to about 1 petabyte of usable data.

1.9 z/TPF features

The remainder of this chapter focuses on z/TPF, as it compares to prior versions of the TPF Family of Products.

As the next generation of on-demand transaction processing, z/TPF has been developed on the architecture of IBM TPF V4.1, which is currently in use globally. z/TPF expanded on this success in the following areas:  Quality of service: This includes preserving all of the quality of service attributes described (speed, scale, reliability, and more).  Higher efficiency and scalability: z/TPF supports the IBM 64-bit architecture with the use of 64-bit addressing, enabling large-scale memory spaces for applications, memory tables, and increased caching and diagnostics.  Open development environment: z/TPF uses the GNU tool chain. z/TPF can share applications, tooling, and development infrastructure (including C/C++) with the only truly open system, Linux.  Assembler program refactoring: The users can take multiples of their current individual assembler programs and combine them into a single large library, which can be called as a shared object. This protects the client’s investment because existing assets now find a new life as reusable business functions.  Variable pricing: z/TPF supports the IBM subcapacity pricing models so that customers using a relatively small amount of z/TPF on a larger machine only pay for the capacity they actually require.  SOA technology dividend: z/TPF also allows the client to exploit such SOA-based technologies as Apache, XML, and SOAP (and others) while taking advantage of the previously mentioned variable pricing mode. As a result of this pricing, model users might see only a minimal price impact due to the overhead that these technologies introduce. For more information about this, contact your IBM support team.

The implications of these advances in technology are many and represent a significant step forward in large-scale online transaction processing (OLTP).

1.10 z/TPF analysis

This section reviews the components of core features, 64-bit support, open development, and application refactoring.

1.10.1 z/TPF core features

z/TPF inherited the core features of TPF 4.1, which itself was built on a history of success in large scale online transaction processing. z/TPF is not a general-purpose operating system but rather a specialized one focused on rapid and reliable processing of message traffic. It

12 z/TPF Application Modernization using Standard and Open Middleware uses real-time concepts and structures designed specifically to process large amounts of message traffic that, in turn, make frequent updates to the database.

Compare this feature to the batch or daemon mode processing model of popular common purpose servers, such as UNIX. These processing modes were not designed for OLTP workloads. UNIX systems often have to focus on providing support for interactive users’ activities. The focus on individual user spaces is a great handicap to large-scale OLTP. Hence, z/TPF is substantially efficient at OLTP.

As previously described, z/TPF was designed for reliability by avoiding planned and unplanned outages. There are many fault tolerant features in z/TPF, such as duplicated data stores and the ability to remove and reintegrate entire strings of disks. UNIX is particularly plagued by memory leaks that often cause users to recycle servers to recover that memory. The z/TPF lightweight processing model, which provides true processes in the POSIX sense, makes memory leaks a non-issue. Generally, processes are created and destroyed extremely quickly in z/TPF, which is the equivalent of recycling a server thousands of times a second. z/TPF provides these process spaces for the cost of thread creation in UNIX, but is many times more secure because memory between process is protected (unlike threads). However, z/TPF also provides the flexibility to create threads that share memory. This flexibility allows for easy porting of packages that contain threads to z/TPF and allows programmers with thread expertise the ability to exploit such a memory sharing model when desired.

Also unlike UNIX or nearly any other system, a user can reload entire application packages (and fall them back) while the system is processing message traffic. Coordination of in-flight messages ensures that the correct package is used (all new or all old). This and many other features lead to the highest levels of availability. The lightweight process model also contributes to extremely low latencies compared to other solutions.

TPF pioneered many scalability features that are now used by other systems. TPF was the first operating system to cluster multiple mainframes to a single database. TPF also pioneered many locking techniques that allow for greater vertical growth in a single box. There are numerous patents held by the TPF team in the area of scalability. The result is that today, TPF is supporting some of the highest volume (message rate) single image (single copy) databases in the world. However, even the largest current customer is not even a quarter of the way through the available processing capacity of z/TPF.

1.10.2 z/TPF 64-bit support

The primary effort of delivering z/TPF as the next generation of TPF was the additional of 64-bit. While 64-bit can be directly credited with the expansion of some scalability features, it should be primarily looked at as a technology enabler for customers both large and small.

First and foremost, it should be understood that z/TPF (and TPF) differs from other systems in that there is no paging of user spaces. Every message processed in a z/TPF system is directly backed up by real memory. This is the area where 64-bit directly increases the ability to process messages concurrently to immense scales. Where this becomes a technology enabler is in the adoption of newer technologies, such as those used to support SOA.

The per-message memory footprint increases rapidly as these technologies are introduced. Hence, even the small TPF users would have found themselves constrained in their ability to adopt high-value technologies without the ability to move to 64-bit. This increased availability of memory also allows larger in-memory tables and more in-memory diagnostics. The former allows for an increase in efficiency (less I/O), and the latter for an increase in stability.

Chapter 1. An introduction to z/TPF and its role in a service-oriented architecture 13 1.10.3 z/TPF open development

TPF and z/TPF are unique from most systems in that they are target systems only. You do not develop on z/TPF, but rather, you do all your development and build on another platform and move the result to z/TPF for production. In TPF and its predecessors, that build environment was MVSTM (later IBM OS/390® now IBM z/OS®). That meant TPF shared with z/OS the complier, language libraries, and programming model. It also meant that development tooling was confined to what can work with z/OS and be customized for the target system approach.

z/TPF is significantly different from the prior version of TPF in that the build environment is Linux, not z/OS. This can be any Linux. Except for building the z/TPF operating system itself, the development and build can be on any Linux server on any platform (Intel or Power for example).

z/TPF depends on the GNU tool chain, which includes the GCC complier and the common open language libraries, such as glibc. Since GCC is a true cross complier, it can itself run anywhere and build for the target z/TPF system.

Assembler programs are handled because the IBM HLASM (program assembler) has been modified to produce output that matches the Linux linkage model, ELF (which z/TPF uses). The term for shared libraries in Linux is shared objects; hence, all applications (assembler, C or C++) get loaded as shared objects. This, and the presence of POSIX API structures in z/TPF, means that the runtime environment and the build environment for the application programmer is extremely similar to Linux.

As a result, most packages built for Linux and programming skills are portable to z/TPF. The importance and impact of this cannot be understated. One can write an entire book on the implications of a robust kernel, such as z/TPF, that provides the stability and qualities of service it does while supporting a Linux-like environment to the application programmer. Saying “Linux-like” is being conservative because z/TPF and Linux shared the same complier, libraries, tooling, and linkage model. What is different is the memory model and database model, which supports the ability to do high-volume OLTP.

Even the unique z/TPF database model only has to be used for data with the highest requirements. To give examples of compatibility, and as we discuss in more depth later in this book, Apache, Open_SSL, OpenLDAP, MySQL and hundreds of thousands of lines of other open source code, are running on z/TPF with few modifications.

1.10.4 z/TPF application refactoring

The ability to refactor or repackage existing applications is closely tied to the adoption of the GNU tool chain. As stated, z/TPF uses the ELF linkage model from Linux, which supports shared objects. To support assembler programs, IBM implemented the concept of binary shared objects, or BSOs.

BSOs make it also possible to combine multiple existing assembler programs into a single library or BSO. The current calls (called “enters” in TPF) between assembler programs in the same BSO simply become online code, and the BSO itself can support multiple entry points. Initially this helps performance because it is more efficient to make these in-line calls between sections than to make a system services call.

For most TPF customers, the current set of heritage applications can be looked at as one monolithic application. Customers have found it extremely difficult to pull this mass of applications apart for the purpose of relocating function, or even just to make modifications. For many customers, there might be as many as 20,000 individual application programs, all with intricate relationships to the programs around them. This ability to repackage the many

14 z/TPF Application Modernization using Standard and Open Middleware parts into fewer (but larger) parts is a huge step toward efficiently managing all of these applications.

The BSOs now have clean, identifiable features and calling requirements. This can reduce the number of “moving parts” to a manageable number without massively affecting the current system performance and stability. When it is completed or at least advanced enough, the customer can now begin to either leave the BSO as is (as a reusable object), re-code it for increased function inside z/TPF, or remove it to another platform better suited for the type of work required (like moving presentation logic to a portal). If you attempt to do this in TPF 4.1, you end up re-creating the infrastructure already provided in z/TPF to have any chance of success.

The decision on which programs to repackage together can also be coordinated with SOA. The key to SOA is deciding which existing functions you want to expose as services (through SOAP, for example). Making the new library structure (shared object) align with the services model would greatly simplify both efforts and ongoing maintenance of the system. For example, having many of the services exposed has a more or less one-to-one association with an SO (or BSO) in z/TPF to be called to provide that service.

1.11 z/TPF summary

z/TPF is a key technology in large scale OLTP. Its use can greatly expand the scalability and quality of service on any enterprise venture requiring high end message processing. SOA and the technologies used to implement it can provide higher flexibility and faster time to market. The combination of z/TPF and SOA can lead to a highly flexible and highly scalable solution with excellent qualities of service. The purpose of this book is to give you a few examples of how to do exactly that.

Chapter 1. An introduction to z/TPF and its role in a service-oriented architecture 15 16 z/TPF Application Modernization using Standard and Open Middleware 2

Chapter 2. Technologies

This chapter provides brief descriptions of the technologies being used in subsequent chapters of this book. This chapter is not intended to be an exhaustive and detailed learning guide, and for this reason, in many places the chapter refers to corresponding websites where the specific details can be found.

This chapter contains the following topics:  2.1, “Service-oriented architecture” on page 18  2.2, “Web services” on page 20  2.3, “Extensible Markup Language” on page 24  2.4, “Service Data Objects” on page 27  2.5, “Leveraging zEnterprise BladeCenter Extension (zBX) for web services” on page 29

© Copyright IBM Corp. 2013. All rights reserved. 17 2.1 Service-oriented architecture

Service-oriented architecture (SOA) is quickly becoming the de-facto industry standard for building enterprise grade applications. SOA is based on the principle that functions, complex or simple in nature, can be utilized in a standardized fashion that is independent of a particular network protocol or operating system.

The preferred approach for implementing an SOA in an enterprise environment is to create individual services that are well defined in their provided function and are designed with reusability and ease-of-use in mind. Instead of creating monster services that execute complex business functions, design more modular services that implement parts of the overall business function and are more likely to be reused elsewhere. The overall business function can then be assembled by combining multiple smaller services into a more complex compound service.

Breaking a complex business function into smaller, individual services creates a more flexible application that can react more quickly to changing market conditions. For example, an individual service can be moved to another platform to support better scalability and performance, without having to change the application that utilizes the service.

Breaking a business function into too many small services can result in a performance degradation because the communication between service components is based on messages that have to be created and parsed. Good judgment is paramount when designing an overall solution and the proper trade-off between reusability and performance has to be evaluated. With ever increasing processing power, the reusability and time to market aspects might have greater importance in the decision process.

The diagram shown in Figure 2-1 is an example of a shipping service that is implemented without any modularization.

Shipping System

Ship package Handle shipping

Figure 2-1 Example service without modularization

A much better implementation is shown in Figure 2-2 on page 19. Now the shipping service is made up of several smaller services and provides modularization. Because of the modularization, it is now possible to reuse service components, such as Address Validation or Verify Credit Card in other services.

18 z/TPF Application Modernization using Standard and Open Middleware Shipping System

Address validation Ship package Handle shipping Determine shipping options

Process payment

Verify credit card

Figure 2-2 Example service composed of smaller service modules

Many modern development environments provide easy-to-use graphical editors that allow you to connect individual services together with just a mouse-click and create more complex services as a result. As your library of service components increases, it becomes easier and faster to create new combined services to solve business requirements.

By now you might be asking yourself what the revolutionary concept behind SOA is. After all, writing modular, reusable applications has been a best practice for many years, and SOA is simply an evolutionary improvement that emphasizes on standardized interfaces and data exchange between services. Several technology standards, such as web services, XML, and so on, go hand-in-hand with SOA and provide the fundamentals that allow the implementation of reusable services. Today’s key factors are time to market and cost, both of which can be drastically improved by reusing existing service components that were built based on open standards.

2.1.1 SOA and existing applications

Obviously, it is easier to adhere to the SOA principles when designing new services and applications, but even existing applications can usually be converted without too much effort as part of the regular application maintenance.

The key is to break monolithic applications into independent modules and to add a good public interface to them. Usually, the existing, private interfaces can remain intact, which allows the existing application to utilize the functionality of the module without much change.

Because the newly created module is now also being used as a public service, additional parameter validation has to take place to ensure the correct behavior. Prior to exposing the module externally, parameter validation was not necessarily required because it was safe to assume that the proper validation had already taken place elsewhere in the application.

Another item that has to be verified is concurrency. It is quite possible, if not likely, that a public service would be called multiple times in parallel. In such a scenario, you have to make sure any resource lock and synchronization techniques do not create resource leaks and dead locks or produce unpredictable and incorrect operating behavior.

Chapter 2. Technologies 19 2.2 Web services

Today, web services is one of the major foundation building blocks of the service-oriented architecture implementation. Many people refer to web services as the service-oriented architecture, even though there are other technologies and specifications that belong under the SOA umbrella too.

Web services is an overall standard that encompasses several technologies and specifications:  XML (Extensible Markup Language) XML is at the core of almost every other specification used in web services and SOA. It is a markup language that can describe almost any type of data. A properly written XML document follows strict rules and guarantees interoperability between many different platforms and programming languages.  SOAP (Simple Object Access Protocol) SOAP is used in conjunction with HTTP (Hypertext Transfer Protocol) to invoke web services across a TCP/IP network, such as the Internet or intranet. The utilization of HTTP as a transportation protocol makes it compatible with today’s web infrastructure.  WSDL (Web Services Description Language) An XML document based on the WSDL specification is used to describe a Web Service. The document describes the available service functions and the input and output messages. The WSDL document provides all the information a service consumer requires to invoke a service.  WSIL (Web Services Inspection Language) The Web Services Inspection Language is a document definition based on XML. A WSIL document contains a list of web services along with a brief description and a reference to the corresponding WSDL document. It works similar to a registry but does not provide any query interface as such. Because of its lack of a query interface it is more applicable for a single business entity or department, whereas UDDI is more powerful and suitable on a global scope.  UDDI (Universal Description, Discovery, and Integration) UDDI is the basis for the formal web services registration services. An UDDI based registry allows business entities to list themselves along with the web services that they provide. It provides a query interface to discover business entities and web services based on various criteria and functions similar to White Pages and Yellow Pages. The search result points to a WSDL that describes the found Web Service.

No discussion about web services is complete without talking about the ever present web services pyramid diagram. A common version of the diagram is shown in Figure 2-3 on page 21.

20 z/TPF Application Modernization using Standard and Open Middleware UDDI Registry

WSDL WSDL

Find Publish

Service SOAP Service Consumer Provider Invoke

Figure 2-3 The web services pyramid

The Service Provider creates a WSDL document to describe a business function that is available for use. The Service Provider publishes the WSDL document in a UDDI registry. The UDDI registry can be one of the global UDDI registry on the Internet or it can be a company or department internal registry.

Publishing a WSDL document in the UDDI registry allows a Service Consumer to query the registry and to find the published service. The Service Consumer retrieves a copy of the WSDL document, which provides all the necessary information to invoke the service itself. The communication between the Service Consumer and the Service Provider is facilitated through SOAP, which makes the invocation of the service and the data exchange platform independent.

2.2.1 XML

Because of the importance of the Extensible Markup Language (XML) and the complexity of it, there is an entire chapter dedicated to it later in this book. See Chapter 5, “XML on z/TPF” on page 95.

2.2.2 SOAP

As stated earlier, SOAP is a message format definition based on XML that allows two endpoints — a service consumer and a service provider — to exchange data in a platform independent manner. While this seems rather trivial at first, it is something quite powerful and necessary. Different computer systems use a different character encoding, native data types, endianess (the ordering of bits for multibyte data types), and other characteristics that can make it difficult to communicate with one another.

SOAP was originally an acronym for Simple Object Access Protocol, but over time the use of the acronym has changed and it is now used as its own independent term to describe the message exchange based on the SOAP specification.

Traditional SOAP messages were exchanged over TCP/IP connections and encapsulated in the Hyper Text Transfer Protocol (HTTP) protocol. This still holds true for most of its use, but SOAP is now also used within the context of other transmission protocols, such as messaging (JMS, WebSphere MQ, and so on) and email (SMTP, IMAP, POP3, and so on).

Chapter 2. Technologies 21 You can find the complete detailed specification of SOAP at the World Wide Web Consortium’s website: http://www.w3.org/

Example 2-1 and Example 2-2 show examples of a SOAP message sent to a service provider (SOAP request) and the corresponding result sent back (SOAP response).

Example 2-1 Sample SOAP request

Example 2-2 Sample SOAP response 09 06 12

2.2.3 Web Services Description Language

Web Services Description Language (WSDL) is a standard based on XML, and as the name implies, it describes a Web Service. A WSDL document contains everything that is required to invoke a Web Service and to exchange messages with it. As part of this book, we focus on the WSDL Version 1.1 specification, which has not been formally endorsed by the World Wide Web Consortium. It is, however, the most predominantly used version of the specification today, while Version 2.0, from the World Wide Web Consortium, is being ratified.

A WSDL document is divided into several sections, and each section describes a different aspect of the Web Service.

The types section defines data types that are being used in either the input or output messages of the Web Service. The type definitions are formatted according to XML schema definitions XSD.

A message section defines the input, output, and fault messages that are being exchanged. The message can contain zero or more parts, which essentially are data fields. The referenced data types can be the ones defined in the types section of the same document or they can be standard XML schema data types.

22 z/TPF Application Modernization using Standard and Open Middleware The actual functions provided by the Web Service, along with the corresponding input, output, and fault messages, are specified in the portType section.

Along with the portType goes the binding section. While the portType has already specified the abstract functions and associated messages, the binding section specifies details about the transmission protocol. One example would be the specification of SOAP over HTTP.

The service section is usually the last section. It provides the name of the Web Service and lists one or more endpoints on which the described Web Service can be found. You can also look at this section as the top-most section; from here you can work your way down to the definition of custom data types.

There are a few other, less frequently used, sections and many attributes that go along with the various sections. A full explanation of a WSDL document is outside of the scope of this book, but you can look at the official specification at the World Wide Web Consortium’s website:

http://www.w3.org/

2.2.4 Web Services Inspection Language

The Web Services Inspection Language (WSIL) is another XML-based document. It assists a client in inspecting a site for available web services. On a high level, it can be considered as a directory of available web services and a link to their corresponding WSDL documents. Because of the simplicity of the document itself, it is easy to implement and in a limited sense can replace a much more complex UDDI (Universal Description, Description, and Integration) registry.

Even though most of the web services specifications are maintained by the World Wide Web Consortium, the WSIL specification is not yet fully integrated. There are some bits and pieces scattered among the various web services pages, but for a good reference of the WSIL specification V1.0, visit the IBM developerWorks® website:

http://www.ibm.com/developerworks/library/specification/ws-wsilspec/

2.2.5 Universal Description, Description, and Integration registry

A popular way to publicly publish a Web Service is through a UDDI registry. A UDDI registry can be compared to the yellow pages in a phone book. It can be queried for company names and industry categories or technical information. The messages between the UDDI registry and the client are in XML format, which should not come as a surprise anymore.

In the past, IBM, Microsoft, and SAP each provided public UDDI registries that were replicated among each other. You were able to use the registries to publish your available web services and make them public to a large audience. However, recently these so-called UDDI Business Registries were discontinued and no longer exist.

Other companies might want to implement UDDI registries for the general public, or an industry organization might want to create UDDI registries for their particular membership or trade. A company can also implement a UDDI registry internally to publish enterprise web services for consumption throughout the organization.

Chapter 2. Technologies 23 The UDDI standard is being maintained by the OASIS consortium. Detailed specifications about UDDI can be found either at the UDDI specific domain or at the OASIS website: http://www.uddi.org/ http://www.oasis-open.org/

2.3 Extensible Markup Language

XML stands for Extensible Markup Language and it has become one of the most important standards of modern times. As we have seen earlier, most documents in the service-oriented architecture world are based on the XML definition. This is possible because it is so versatile and extensible. Because it is text based, humans and machines can read it, and it makes cross platform data exchange effortlessly possible.

There are some drawbacks to XML as well. The two most prevalent drawbacks are the processing power necessary and the communications bandwidth requirements. XML documents are well structured and are easy to parse and consume, but complex documents can take considerable computing effort to process and possibly convert into native data structures for further processing.

It is also recommended that a received XML document be validated first to make sure its integrity is acceptable and that it conforms to the specification. While data validation is also recommended for proprietary data structures, it can be more expensive for XML. Because XML documents are based on clear text, they consume more communications overhead than a binary equivalent does. With the continual increase in available bandwidth, this limitation becomes less of an issue now, and applying some compression algorithms can also help for large documents.

It certainly is not within the scope of this book to go into all of the details of the XML specification. However, the following sections briefly touch upon some of the more important parts of the specification. The entire specification is at the website of the World Wide Web Consortium:

http://www.w3.org/

2.3.1 Basic XML format

Each well formed XML document starts with an XML declaration that indicates the XML version and character encoding, as shown in Example 2-3.

Example 2-3 XML declaration

The rest of an XML document is made up of elements, which can be nested to create a tree-like structure. Example 2-4 shows various notations for an element. The first and second lines are basically the same, an empty element, but the notation in the first line is preferred.

Example 2-4 Basic XML elements content content

24 z/TPF Application Modernization using Standard and Open Middleware There are two basic rules that you must follow:  Each opening tag must have a corresponding closing tag .  If elements are nested, the closing tags have to appear in reverse order of the opening tags.

To make a document more readable to humans, the elements are usually indented according to the nesting level, as shown in Example 2-5.

Example 2-5 Correct nesting of elements Smith John XYZ 555-1212

Important: Element names and attribute names in XML documents are case-sensitive. An opening and closing element tag must be in the same case to be matched.

2.3.2 Special characters

An XML document is a text-based document that defines a special meaning for a handful of characters to create a document structure. XML parsers can use these special characters to navigate the document and understand its structure. However, using any of these special characters outside of its special purpose — as part of a data element, for instance — can confuse an XML parser and cause errors. To avoid this problem, use a special notation or encoding when using these characters outside of their special purpose.

Table 2-1 lists the characters that have a special meaning in the scope of an XML document and their related encoding that is to be used in data elements and attributes, as shown in Example 2-6.

Table 2-1 Special XML character encoding Character Encoding

<<

>>

‘ '

“ "

& &

Example 2-6 Using predefined XML character encoding Action & Adventure

2.3.3 Namespace

Element names are usually self explanatory, such as , , or . This of course means that many companies or organizations are using the same element names but with slightly different meanings or syntax.

Chapter 2. Technologies 25 To resolve this problem, the XML specification supports namespaces. A namespace is a qualifier or prefix to element names and attribute names and makes them unique.

The reserved attribute xmlns is used to declare a namespace, and its attribute value is a Uniform Resource Identifier (URI). Even though the URI looks similar to a website address, an XML parser does not attempt to get the resource, but rather uses it internally to support namespaces.

In Example 2-7, there are two employee records and they come from different companies. To indicate that these two employee records are not really the same, even though some elements have the same name, they are qualified with their separate namespace. A child element inherits its namespace from its parent.

Example 2-7 Namespace example John Smith 555-1212 Doe John 555-3113

A namespace can also be declared with a prefix, which can then be used for element names and attribute names of children. This is useful when multiple namespace declarations are being used simultaneously.

In Example 2-8, there are two namespaces declared for the employee record. The employee record itself is associated with the myns namespace because its name tag is prefixed with that namespace prefix. The element is specifically prefixed with the myns namespace again and the tag is not. Both elements are associated with the myns namespace because not specifying a prefix automatically forces the element to inherit its parents namespace, which is myns. Finally, the element is associated with the irsns. Even though inherited namespaces do not have to be prefixed, it is a good practice to use prefixes on all names when multiple namespaces are being used. This practice avoids any potential confusion and usually improves readability.

Example 2-8 Namespace with prefix John Doe 45000 123-34-4567

When you look at the various XML-based documents that are used for web services (WSDL, WSIL, and so on) notice that they make extensive use of namespaces and namespace prefixes.

2.3.4 XML schema and XSD

An XML schema is a document that defines constraints for the structure and content of an XML document. This is in addition to the rules imposed by XML itself and must be viewed as a higher level of organizational restriction.

26 z/TPF Application Modernization using Standard and Open Middleware One of the first XML schema definition languages is the Document Type Definition (DTD) language. Because of its complexity, it is largely replaced by the XML Schema Definition (XSD) specification. There are many other specifications and languages available that define XML schemas, but XSD has become the most prevalent one for web services and service-oriented architecture.

XSD allows you to define what elements and attributes can appear in a document, which ones are optional or required, and their relationship to each other. It also defines the type of data that can occur in elements and helps define complex data types. Having an XSD document allows us to verify an XML document for validity.

Notice that WSDL documents usually reference the XSD namespace in their section and utilize the XSD specification therein to define the input and output messages of the Web Service.

2.4 Service Data Objects

Service-oriented architecture (SOA) can be considered as a means to connect to or communicate between heterogeneous systems. While web services allows heterogeneous systems to easily share common services, Service Data Objects (SDOs) provide a mechanism to easily share data among heterogeneous systems.

In simple terms, a SDO provides a framework to allow one system to request data from another system or systems, without the requestor having knowledge of the precise structure of the data as it is stored on the target systems. The requestors and data providers only need knowledge of the SDO.

2.4.1 Service Data Object components

The three basic components within an SDO are the data object, the data graph, and the data access service:  The data object is the component in SDO that contains the data. In the data object, data is held in a set of properties. Each property can hold a data value, such as a date, string, number, and so on, and can be associated with simple or complex data types. Properties can also contain references, which are links to other data objects and create relationships between objects in a data graph.  The data graph is a collection of tree-structured or graph-structured objects. Data objects within the data graph are accessed through a root and references connecting the objects in the data graph. The SDO client retrieves and updates the pertinent data by manipulating the data graph, as such the client is disconnected from the format in which the data is stored on the SDO host.  The data access service (DAS) is the function that connects the client application with the data. As an example, the data graph would be requested, through DAS APIs, by the client. The data access service would manage the formulation and retrieval of the data graph from the host. The client updates the datagraph using standard SDO APIs and then calls the DAS to update the host using the new datagraph.

Figure 2-4 on page 28 is an example data graph showing a credit card purchase history for a single credit card holder. The boxes represent data objects and their properties and the arrows are references between data objects. By starting at the root and traversing the references, an SDO client can access customer information and purchase history for this customer.

Chapter 2. Technologies 27 The PurchaseList data object contains a many-valued property that contains a list of references to two Purchase data objects. The CustomerInfo and Purchase data objects contain multiple properties using a variety of data types.

Root

CustomerInfo PurchaseList

Name="John Doe" CardNumber=1234 SSN=xxx-xx-xxxx DOB=Aug. 13, 1965 Purchase Purchase Vendor="Grocery Store" Vendor="Gas Station" Date=Oct. 12, 2012 Date=Oct. 14, 2012 Time=14:02 Time=17.30 Amount=23.91 Amount=45.00

Figure 2-4 Example data graph showing a credit card purchase history

2.4.2 Service Data Object architecture

Service data objects (SDO) are designed to simplify and unify the way in which application programs handle data. Using SDO, application programmers can use SDO data graphs and data objects to uniformly access and manipulate data from a wide variety of data sources. As shown in Figure 2-5, a client application can read and manipulate data from several different sources including z/TPFDF, relational databases, web services, XML, and other data sources.

Client Application z/TPFDF

Read and update data graphs Relational DB

Data Access Services Web Services

SDO APIs

XML SDO Components

Figure 2-5 Basic SDO architecture and components

Access to the various data sources is provided through the Data Access Service (DAS) for each data source. The DAS is responsible for querying data sources, creating graphs of data containing data objects, and applying changes to data graphs back to data sources. The

28 z/TPF Application Modernization using Standard and Open Middleware client is typically disconnected from the data service and only connects to retrieve or update a data graph.

After using the DAS to read a data graph from a data source, the client application uses a common set of SDO APIs to traverse and manipulate the data graph. If the data source needs to be updated to reflect the changed data graph, the client application simply calls the DAS to perform the update using the change summary contained in the data graph.

The advantage of SDO is that the client application does not have to understand that data format, layout, or persistence technology used by any of the data sources. That is all handled by the DAS.

2.5 Leveraging zEnterprise BladeCenter Extension (zBX) for web services

With the introduction of the z196, a user can optionally set up a IBM zEnterprise® IBM BladeCenter® Extension zBX. The zBX contains racks of accelerators and application server blades (ASBs) that can help process System z workloads. The z196 processor and the zBX are connected through a secure, high speed internal network called the Intraensemble Data Network, or IEDN.

The IEDN is one physical network that can be subdivided into multiple logical networks using virtual LAN (VLAN) technologies. From the zEnterprise Unified Resource Manager, (zManager) you define each VLAN along with what LPARs and blades are in that VLAN.

Using the zBX, a user can consolidate their heterogeneous platforms into one unified, centrally managed system. Applications running in the zBX can consume web services provided on the System z platform, and applications running on System z can consume web services provided in the zBX. Because the IEDN is a private network used for communications between System z and the zBX, encryption might not be needed, reducing the associated overhead.

Chapter 2. Technologies 29 30 z/TPF Application Modernization using Standard and Open Middleware Part 2

Part 2 z/TPF as a provider in a service-oriented architecture

Part 2 of the book describes z/TPF SOAP processing, z/TPF communications bindings, and XML on z/TPF. This part contains the following chapters:  Chapter 3, “z/TPF SOAP processing” on page 33  Chapter 4, “The z/TPF communications bindings” on page 55  Chapter 5, “XML on z/TPF” on page 95

© Copyright IBM Corp. 2013. All rights reserved. 31 32 z/TPF Application Modernization using Standard and Open Middleware 3

Chapter 3. z/TPF SOAP processing

SOAP messages can essentially travel on any communications protocol. This chapter discusses the communications protocols and their link to the SOAP support on z/TPF (the SOAP communications bindings) discussed in Chapter 4, “The z/TPF communications bindings” on page 55. The communications protocol hands off the SOAP messages to the z/TPF SOAP support software, and we discuss this z/TPF component in detail in this chapter.

The z/TPF system today supports SOAP versions 1.1 and 1.2.

This chapter contains the following topics:  3.1, “SOAP handler” on page 34  3.2, “SOAP fault builder” on page 39  3.3, “SOAP message encoding” on page 41  3.4, “SOAP structures” on page 49

© Copyright IBM Corp. 2013. All rights reserved. 33 3.1 SOAP handler

When a SOAP message arrives on the z/TPF system, it triggers a specified path to get executed, as shown in Figure 3-1.

Req Req SOAP request user exit Msg Msg tpf_soap_handler_exit() Web service resource Translation functions deploy and undeploy (optional) user exits Apache HTTP CA2M / CA2S Web services deployment mod_tpf_soap ZWSAT command table (WSDT)

B2B XML scanner CSOA Utility functions: SOAP handler: translation functions, tpf_soap_ SOAP message handler tpf_soap_build_fault_ext() handler() Web service wrapper z/TPF application CSOI SOAP handler SOAP response user exit extended: tpf_soap_handler_ tpf_soap_ response_exit() handler_ext()

Figure 3-1 Sample flow of a SOAP message in z/TPF using the Apache HTTP Server

The input message has to be handed to the SOAP handler by the communications protocol software. The SOAP handler receives three pieces of input1:  An input message structure: A soapMsg structure containing the SOAP input message.  An output message structure: A soapMsg structure in which the application has to build its SOAP output message.  Communications binding information: A commsBinding structure that contains information about the communications protocol and the application routing information.

The SOAP handler performs the following tasks:  Invokes the SOAP handler user exit. The z/TPF SOAP handler user exit is the shared object CSO2. It allows you to specify translation of a SOAP message, log messages, or any other user specific processing your system requires to process the input SOAP message. The SOAP handler handles the following predefined return codes from the z/TPF SOAP handler user exit: – TPF_CONTINUE_DO_NOT_TRANSLATE Translation was completed by the user exit, so processing continues.

1 The detailed contents of these structures are discussed in 3.4, “SOAP structures” on page 49.

34 z/TPF Application Modernization using Standard and Open Middleware – TPF_CONTINUE_DO_TRANSLATE Translation was not completed by the user exit, so the SOAP handler attempts to translate the SOAP message. – TPF_TRANS_FAILED_RECEIVER: The SOAP handler user exit determined that an error occurred that was caused by the receiver, which is the z/TPF system. The SOAP fault builder2 is called, and a fault message is built and returned to the client. – TPF_TRANS_FAILED_SENDER The SOAP handler user exit determined that an error occurred that was created by the sender. The SOAP fault builder3 is called, and a fault message is built and returned to the sending client. The SOAP handler also handles the ErrorReplyNeeded return code, which indicates that the SOAP application encountered an error but did not create the fault message. The SOAP handler calls the SOAP fault builder2 to create the fault message using the tpf_soap_build_fault_ext C function. When the SOAP handler receives any other return codes from another component, it simply returns to the communications binding. By default, the SOAP handler user exit is empty and returns the value TPF_CONTINUE_DO_TRANSLATE. Example 3-1 shows the way the SOAP handler user exit is shipped with z/TPF.

Example 3-1 SOAP handler user exit cso2.c 1 #include 2 int CSO2(soapMsg* inputMsg, soapMsg* outputMsg, commsBinding* binding) { 3 return(TPF_CONTINUE_DO_TRANSLATE); 4}

 Translates the input message, if necessary. Depending on the return code from the SOAP handler user exit, the input message is translated to the host encoding of the z/TPF system.  Performs a lookup operation against the web services deployment table (WSDT) and based on the result of that operation, the SOAP handler might route the request to multiple SOAP message handlers to process any SOAP headers and then to the Web Service wrapper program.  Invokes the B2B XML scanner. For more information about the B2B XML scanner, see Chapter 5, “XML on z/TPF” on page 95.  Checks the SOAP syntax. The SOAP handler performs the following syntax checks: – The document must not contain a Document Type Definition (DTD) or any processing instructions. – The document must not have a standalone=no value in the docSwitches field of the infoNodes structure. – The document must contain a SOAP envelope. – The SOAP envelope must be namespace-qualified. – If the document contains a header element, it must follow immediately after the envelope element. – If the document contains a header element, it must be namespace-qualified.

2 See 3.2, “SOAP fault builder” on page 39. 3 See 3.2, “SOAP fault builder” on page 39.

Chapter 3. z/TPF SOAP processing 35 – The document must contain a body element. The body element must follow the header element if one is present or follow immediately after the envelope element. For SOAP version 1.1, if the document contains a mustUnderstand element, the value must be 0 or 1. For SOAP version 1.2, the following additional checks are performed: – The document must not contain an attribute of encodingStyle in the envelope element. – If the document contains a mustUnderstand element, the value must be true or false. In addition, the z/TPF system supports the following Web Services-Interoperability Organization (WS-I) profiles: – Basic Profile Version 1.1: (http://www.ws-i.org/Profiles/BasicProfile-1.1.html) – Simple SOAP Binding Profile Version 1.0: (http://www.ws-i.org/Profiles/SimpleSoapBindingProfile-1.0.html)  Transfers control to the Web service wrapper program. If at any point in this process an error occurs, the SOAP handler invokes the SOAP fault builder ext 4 to communicate the error information back to the SOAP client (Example 3-1 on page 35).  Invokes the SOAP handler response user exit. This user exit allows you to log response messages or do any other user-specific processing your system requires on outbound SOAP messages. This function is called in all cases after the response document or fault response is built and translated.

3.1.1 Web services deployment table

The web services deployment table (WSDT) is a subsystem-unique system table in memory that contains information about Web service resources, such as which provider web services and SOAP message handlers are deployed or undeployed. It is built from the deployment descriptors in the z/TPF file system and is referenced during runtime while processing a SOAP request.

A deployment descriptor is an XML document that resides in the file system and must conform to the z/TPF base/tpf-ws/schema/tpf_ws_dd_vn.xsd XML Schema file (where n is the version number).

Each Web service resource, that is, each provider Web service and SOAP message handler, must have a deployment descriptor, which defines their attributes and controls their deployment and undeployment to the SOAP runtime.

3.1.2 SOAP message handler

A SOAP message handler is a program or collection of programs that is used to implement SOAP features, which can be standard extensions to the SOAP protocol that rely on SOAP message headers (such as WS-Addressing) or customized user-specific extensions, which might not rely on SOAP message headers. A SOAP message handler provides a single, reusable interface for extending one or more provider web services and is described by a SOAP message handler deployment descriptor.

In addition to the standard extensions to the SOAP protocol, you can develop and deploy customized SOAP message handlers to perform processing that is specific to your installation

4 See 3.2, “SOAP fault builder” on page 39

36 z/TPF Application Modernization using Standard and Open Middleware or environment. For example, if a set of deployed web services requires that every SOAP request for the web services be logged to a logging facility, you can develop a logging message handler and deploy it to the SOAP support.

Each provider Web service deployment descriptor specifies a chain of SOAP message handlers that must be called each time a SOAP request is received for the Web service. SOAP support calls the program that corresponds to each listed SOAP message handler in the order that they are listed in the provider Web service deployment descriptor. As SOAP responses are being prepared to return to the communications binding, the same SOAP message handlers are called, in the reverse order that they were called when processing the request. This creates a virtual pipeline through which input and output SOAP messages flow.

3.1.3 Web service wrapper

A Web service wrapper is a four-character z/TPF program that logically sits between the SOAP support and a z/TPF application that implements a provider Web service. After calling the SOAP message handler chain for a Web service (if one is defined), the SOAP handler passes control to the Web service wrapper that is listed in the deployment descriptor. There is one Web service wrapper for each Web service that is deployed in the z/TPF system. The main tasks of the Web service wrapper are to deserialize the SOAP message data (parsed XML) so that it is usable by the application, call the correct application based on the requested operation, serialize the return information from the application, and build the SOAP response message. This architecture permits existing applications to be deployed as web services without having to change the applications to handle request data in SOAP/XML format.

SOAP support uses the TPF_CALL_BY_NAME API to call the four-character z/TPF program name that is specified in the wrapper element in the Web service deployment descriptor for a particular Web service. The intfn pointer is a pointer to function type and is passed to the TPF_CALL_BY_NAME macro. With this parameter and the four-character program name that implements the Web service wrapper, TPF_CALL_BY_NAME returns a pointer to function value that when executed, calls enter with return linkage (that is, ENTRC linkage) to the specified program.

3.1.4 z/TPF application

This is an application that you supply on your z/TPF system to handle SOAP requests. It might or might not call translation functions, the tpf_soap_build_fault C function, the z/TPF XML APIs, or any other supported z/TPF functions. See z/TPF XML API support for more information about the z/TPF XML APIs.

3.1.5 Utility functions

The following list summarizes the utility functions that are available with z/TPF SOAP support:  Fault builder The tpf_soap_build_fault_ext C function builds an XML-based fault message when an error occurs along the SOAP message path. This fault message is returned to the SOAP client. The tpf_soap_build_fault_ext C function can be also called to build a fault message by other components or applications at any time.

Chapter 3. z/TPF SOAP processing 37  Translation functions Translation functions allow you to translate a message from one character set to another. Generally, a SOAP message must be in the host encoding before being processed by a z/TPF application. If a SOAP message is sent to the client in response, it also must be encoded in the preferred character set of the client before being sent. See SOAP provider message encoding support in the z/TPF Information Center for more information about encoding support on the z/TPF system. http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztp fdf.doc_put.cur/gtps6/s6spcen.html When the input message is encoded in a Unicode character set but contains characters that cannot be translated, a substitute character is used. For example, a euro symbol (U+20AC, which is represented as 0xE282AC in UTF-8) in an input message encoded in Unicode format UTF-8 will be replaced by the 0x3F EBCDIC substitute character during translation. The converted message will instead have the 0x3F EBCDIC substitute character.  SOAP bridge support SOAP bridge support enables you to leverage existing business logic on your z/TPF system and externalize it as a callable service by other systems in a distributed environment. With this support, you can expose heritage applications as web services without making changes to the actual applications. Traditional z/TPF applications are activated by the z/TPF message router (segment COA4) and expect input to be in application message (AMSG) format on ECB data level 0. When it completes processing, an application typically issues one or more ROUTC macros to send the response, in output message (OMSG) format, back to the originator. Without SOAP bridge support, application changes are required to interface with modern web services technologies, such as SOAP, XML, WSDL, HTTP, and so on. With SOAP bridge support, web services can be easily deployed to activate existing applications. This support consists of a set of tpf_SOAPBridge* functions, which are used in Web service wrapper programs to interface with the SOAP bridge. Deploying an existing z/TPF application as a Web service is the same as deploying any other application as a Web service, which includes the ability to use SOAP message handlers. In addition to the tpf_SOAPBridge* functions, two utility functions can be used in a Web service wrapper program to convert input and output messages to and from AMSG and OMSG format, respectively: tpf_convertToAMSG and tpf_convertFromOMSG. See z/TPF C/C++ Language Support User's Guide for more information about the tpf_SOAPBridge* functions and the tpf_convert* functions. You can find this document at: http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom .ibm.ztpf-ztpfdf.doc_put.cur%2Fgtpc2mst.toc.html

3.1.6 Resource management

The following list summarizes tools that you can use to manage web services resources:  Web services administration tool (ZWSAT command) The ZWSAT command provides the operator interface for managing web services and SOAP message handlers. The ZWSAT command permits an operator to deploy and undeploy an individual Web service resource or all Web service resources. Operators can also add, remove, or display Web service resource with this command. See z/TPF

38 z/TPF Application Modernization using Standard and Open Middleware Operations for more information about the ZWSAT command and several examples of the command: http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom .ibm.ztpf-ztpfdf.doc_put.cur%2Fgtpo1mst.toc.html  Web service resource deploy user exit The tpf_soap_deploy_exit user exit is called as part of ZWSAT command processing to permit user-specific actions to be performed in response to a Web service resource being deployed on the z/TPF system. An operator enters the ZWSAT command with the DEPLOY parameter to deploy or redeploy a Web service resource to the SOAP runtime. When a resource is deployed, the corresponding program is available to be called as needed by the SOAP runtime processing.  Web service resource undeploy user exit The tpf_soap_undeploy_exit user exit is called as part of ZWSAT command processing to permit user-specific actions to be performed in response to a Web service resource being undeployed on the z/TPF system. An operator enters the ZWSAT command with the UNDEPLOY and REMOVE parameters to undeploy a Web service resource from the SOAP runtime. When a resource is undeployed, it is no longer available to be called by the SOAP runtime processing.

3.2 SOAP fault builder

The SOAP fault builder (tpf_soap_build_fault_ext() in shared object CWSA) builds an XML-based fault message when an error occurs along the SOAP message path. This fault message is returned to the SOAP client.

The SOAP fault builder can also be called to build a fault message by other components or applications at any time.

Example 3-2 shows the API for the SOAP fault builder.

Example 3-2 SOAP fault builder API LIBS := CWSA #include int tpf_soap_build_fault_ext (struct soapFault *soapFault, PXMLHandle xmlapiPtr);

This coding in Example 3-2 contains the following parameters:  soapFault A pointer to a fully initialized soapFault structure. See 3.4, “SOAP structures” on page 49 for more information about the soapFault structure and the fields that it contains.  xmlapiPtr A pointer to the location to store the XML API handle that is associated with the SOAP fault message that is created.

The return code of this function is one of the following values:  TPF_FAULT_BUILT The XML structure for the SOAP fault output message was created successfully and the xmlapiPtr parameter is initialized with the value of the XML API handle.

Chapter 3. z/TPF SOAP processing 39  TPF_FAULT_FAILED The XML structure for the SOAP fault output message was not created and the value of the xmlapiPtr parameter remains unchanged.

Example 3-3 shows an example of building a SOAP fault output message.

Example 3-3 Using the SOAP fault builder 1 #include /* included for calloc */ 2 #include /* included for tpf_soap_build_fault */ 3 soapFault* f = calloc(1, sizeof(soapFault)); 4 XMLHandle api_handle; 5 f->xmlVersion = XML1_0; 6 f->version = SOAP1_1; 7 f->code = Sender; 8 f->reason = "Namespace URI mismatch"; 9 f->detail = "The namespace URI in the header element was missing"; 10 f->encoding = "iso-8859-1"; 11 f->language = "en-US"; 12 int rc = tpf_soap_build_fault_ext(f, &api_handle);

In Example 3-3:  Lines 1-2 show the necessary header files that are required to allocate some heap storage and to generate a SOAP fault output message.  Line 3 shows the definition and initialization of the soapFault structure.  Line 4 shows the definition and initialization of the XML API handle.  Lines 5-10 show how the various fields in the soapFault structure are filled with the appropriate values.  Line 12 shows the call to the SOAP fault builder. The variable api_handle will be initialized with the value of the XML API handle that is created. In the case of an error, the api_handle is unchanged.

Example 3-4 shows what the soapFault output message contains for SOAP version 1.1.

Example 3-4 Version 1.1 soapFault output message env:Sender Namespace URI mismatch The namespace URI in the header element was missing

40 z/TPF Application Modernization using Standard and Open Middleware 3.3 SOAP message encoding

Data can be encoded in different character sets. The character set in which a SOAP message is encoded is critical in the processing of that information and, generally, the SOAP message is in the host encoding of your z/TPF system.

To ensure that SOAP messages are translated correctly, you must identify the host encoding of your z/TPF system in the c_soap.h header file. By default, this header file defines the host encoding as TPF_CCSID_IBM1047 or Latin Open Systems EBCDIC.

How the encoding of a SOAP message that arrives on the z/TPF system is identified depends on the transport layer the SOAP message travels on. For example, when HTTP is used, the encoding is in the HTTP header. When that SOAP message is sent to the SOAP handler, it might be necessary to translate the message to the host encoding of your z/TPF system. Translation is handled by one of the following components:  SOAP handler: The SOAP handler can translate a SOAP message from Unicode or Latin 1 (ISO-8859-1) to EBCDIC (either Latin Open Systems EBCDIC (IBM1047) or International EBCDIC (IBM500)). The specific type of EBCDIC used is determined by the host encoding definition in the c_soap.h header file.  SOAP handler user exit: You can modify the SOAP handler user exit to handle any translation that cannot be handled by the SOAP Handler. You are responsible for writing any translation routines that you require in this user exit.

After a SOAP message has been processed by the z/TPF system, there might be a SOAP message to return to the client in response. For this condition, the information in that SOAP message must be encoded in the appropriate client character set. You are responsible for writing any translation routines that are necessary to ensure that the output message is in the appropriate character set. These routines must be handled by the application or by the SOAP application handler user exit.

3.3.1 Character set translations

Depending on the origin and destination character sets, z/TPF offers a few ways to translate data between character sets. These options are summarized in Figure 3-2 on page 42 and discussed in some detail in the following sections:  Using z/TPF unique character set conversion functions  Using iconv() character set conversion  Using iconv() character set conversion with user-defined character sets

Chapter 3. z/TPF SOAP processing 41 z/TPF unique If X=EBCDIC and Y=LATIN1 or Unicode conversion If X=LATIN1 or Unicode and Y=EBCDIC functions Data Data encoded encoded in If X and Y are z/TPF supported in iconv functions character character sets character set set X Y iconv functions Create with Else user-defined user-defined conversion conversions

Figure 3-2 Character set translation options supported on z/TPF

Using z/TPF unique character set conversion functions The following translation functions are supported on the z/TPF system:  tpf_convert_ebcdic_to_latin1()  tpf_convert_ebcdic_to_unicode()  tpf_convert_latin1_to_ebcdic()  tpf_convert_unicode_to_ebcdic()

Example 3-5 shows the APIs for these functions.

Example 3-5 z/TPF unique character set conversion APIs #include int tpf_convert_ebcdic_to_latin1(char** inBuf, size_t* inBytesLeft, char**outBuf, size_t* outBytesLeft, tpf_ccsid_t whichEBCDIC, int flags); int tpf_convert_ebcdic_to_unicode(char** inBuf, size_t* inBytesLeft, char** outBuf, size_t* outBytesLeft, tpf_ccsid_t whichEBCDIC, tpf_ccsid_t whichUnicode, int flags); int tpf_convert_latin1_to_ebcdic(char** inBuf, size_t* inBytesLeft, char** outBuf, size_t* outBytesLeft, tpf_ccsid_t whichEBCDIC, int flags); int tpf_convert_unicode_to_ebcdic(char** inBuf, size_t* inBytesLeft, char** outBuf, size_t* outBytesLeft, tpf_ccsid_t whichUnicode, tpf_ccsid_t whichEBCDIC, int flags);

This coding contains the following parameters:  inBuf A pointer to a variable that points to the first character of the input buffer, which contains the string to convert.  inBytesLeft A pointer to the number of bytes before the end of the input buffer.

42 z/TPF Application Modernization using Standard and Open Middleware  outBuf A pointer to a variable that points to the first character of the output buffer where the converted string is placed.  outBytesLeft A pointer to the number of available bytes before the end of the output buffer.  whichUnicode Specifies the specific Unicode format that you are converting from. Specify one of the following values to indicate the appropriate format: – TPF_CCSID_UTF8: UTF-8 format. – TPF_CCSID_UTF16BE: UTF-16 Big Endian format – TPF_CCSID_UTF16LE: UTF-16 Little Endian format  whichEBCDIC Specifies the specific single-byte EBCDIC character set that you are converting to. Specify one of the following values. The output is encoded as indicated: – TPF_CCSID_IBM1047: Latin Open Systems EBCDIC – TPF_CCSID_IBM500: International EBCDIC  flags Specifies one of the following conversion options: – 0: Default conversion – TPF_DISCARD_BOM The conversion ignores the U+FEFF Unicode character at the beginning of the input buffer (if present) because it is a byte order mark (BOM). A BOM indicates a Unicode format and typically is used with plaintext information, where it is unknown if the Unicode format is Big Endian or Little Endian. When the U+FEFF Unicode character is in any other position, it is interpreted as a zero-width, nonbreaking space. For more information about using a BOM, see the following website: http://www.unicode.org/

The return codes for these functions will be one of the following values:  TPF_OK The following actions occur with this normal return: – The variable pointed to by inBuf is updated to point to the byte that follows the last byte of the original input buffer. – The value pointed to by inBytesLeft is set to zero. – The variable pointed to by outBuf is updated to point to the byte that follows the last byte of the converted output. – The value pointed to by outBytesLeft is decremented to reflect the number of bytes that are still available in the output buffer.  TPF_NOT_OK The following actions occur with this error return: – The variable pointed to by inBuf is updated to point to the byte that follows the last byte of the characters that are converted successfully. – The value pointed to by inBytesLeft is decremented to reflect the number of bytes in the input buffer that were not converted.

Chapter 3. z/TPF SOAP processing 43 – The variable pointed to by outBuf is updated to point to the byte that follows the last byte of the converted output. – The value pointed to by outBytesLeft is decremented to reflect the number of bytes that are still available in the output buffer. – tpf_convert_unicode_to_ebcdic() identifies the specific error by setting errno.

Example 3-6 shows an example of using a z/TPF API for character set conversion.

Example 3-6 Using a z/TPF unique API for character set conversion 1 #include 2 #include 3 #include 4 #include 5 int main(void) { 6 char* inBufPtr; 7 char* outBufPtr; 8 size_t inBytesLeft; 9 size_t outBytesLeft; 10 int rc; 11 char buffer[26]; 12 outBytesLeft = inBytesLeft = 26; 13 /* set buffer to "123 Main St" in UTF-16BE with a byte order mark */ 14 memcpy(buffer, 15 "\xfe\xff\x00\x31\x00\x32\x00\x33\x00\x20\x00\x4d\x00\x61" 16 "\x00\x69\x00\x6e\x00\x20\x00\x53\x00\x74\x00\x00", 17 inBytesLeft); 18 inBufPtr = outBufPtr = buffer; 19 rc = tpf_convert_unicode_to_ebcdic(&inBufPtr, &inBytesLeft, 20 &outBufPtr, &outBytesLeft, 21 TPF_CCSID_UTF16BE, 22 TPF_CCSID_IBM1047, 23 TPF_DISCARD_BOM); 24 if (rc < 0) { 25 printf("conversion failed: rc=%i, errno=%i\n", rc, errno); 26 } else { 27 printf("conversion worked: \"%s\"\n", buffer); 28 } 29 return 0; 30 }

Table 3-1 on page 45 summarizes how translation is handled for the different combinations of incoming SOAP message encoding and host encoding.

44 z/TPF Application Modernization using Standard and Open Middleware Table 3-1 SOAP message translation summary SOAP message encoding

IBM1047 IBM500 Unicode, Latin 1 Other UTF-8 ISO-8859-1

z/TPF host IBM1047 N/A SOAP SOAP SOAP SOAP encoding handler handler handler handler user exit user exit

IBM500 SOAP N/A SOAP SOAP SOAP handler handler handler handler user exit user exit

Latin 1 SOAP SOAP SOAP N/A SOAP ISO-8859-1 handler handler handler handler user exit user exit user exit user exit

Other SOAP SOAP SOAP SOAP SOAP handler handler handler handler handler user exit user exit user exit user exit user exit Using iconv() character set conversion The z/TPF system supports translations using iconv() among the following character sets listed in Table 3-2. These character sets are supported by glibc and are single-byte character sets (SBCSs) unless otherwise noted.

Table 3-2 Supported character sets on z/TPF Character set Description Encoding

ANSI_X3.4-1968 Standard 7-bit ASCII ASCII (X'00'-X'7F')

CP1250 MS Windows Latin 2 ASCII

CP1252 MS Windows Latin 1 ASCII

EUC-JP Japanese characters ASCII

GB18030 Chinese multibyte ASCII

IBM037 US/Canada Latin 1 EBCDIC

IBM290 Japanese Katakana EBCDIC

IBM500 Multinational EBCDIC

IBM819 Alias for ISO8859-1 ASCII

IBM850 Latin 1 PC Data ASCII

IBM875 Greek EBCDIC

IBM924 IBM50, /IBM1047 with euro EBCDIC

IBM930 Japanese Katakana/Kanji multibyte character set EBCDIC

IBM932 Japanese PC Data ASCII

IBM939 Japanese Latin, Kanji multibyte character set EBCDIC

IBM1026 Turkey Latin 5 EBCDIC

IBM1047 Open Systems Latin 1 EBCDIC

Chapter 3. z/TPF SOAP processing 45 IBM1140 Latin 1; IBM037 with euro for US EBCDIC

IBM1141 Latin 1; IBM273 with euro for Austria, Germany EBCDIC

IBM1142 Latin 1; IBM277 with euro for Denmark, Norway EBCDIC

IBM1143 Latin 1; IBM278 with euro for Finland, Sweden EBCDIC

IBM1144 Latin 1; IBM280 with euro for Italy EBCDIC

IBM1145 Latin 1; IBM284 with euro for Spain EBCDIC

IBM1146 Latin 1; IBM285 with euro for UK EBCDIC

IBM1147 Latin 1; IBM297 with euro for France EBCDIC

IBM1148 Latin 1; IBM500 with euro for Belgium, Canada, EBCDIC

IBM1149 Latin 1; IBM871 with euro for Iceland EBCDIC

ISO8859-1 Latin 1, Standard 8-bit ASCII

ISO8859-2 Latin 2 ASCII

ISO8859-3 Latin 3 ASCII

ISO8859-4 Latin 4 ASCII

ISO8859-9 Latin 5, Turkey/Western Europe ASCII

ISO8859-10 Latin 6, Baltic/Scandanavian ASCII

ISO8859-15 Latin 9, ISO8859-1 with euro ASCII

UCS-2 2-byte normalized Unicode Unicode

UCS-4 4-byte normalized Unicode Unicode

UTF-8 Multibyte Unicode (a range of 1-6 bytes per character) Unicode

UTF-16 Multibyte Unicode (a range of 1-6 bytes per character) Unicode

UTF-32 Multibyte Unicode (a range of 1-6 bytes per character) Unicode

Standard C iconv() is also supported on the z/TPF system. The iconv() can translate among any of the character sets listed in “Table 3-2 on page 45” because the GNU C library (glibc)-based character sets use the UCS-4 wide character set between translations. This allows iconv() to use the UCS-4 wide character set as an intermediate set. For example, when you use iconv() to translate from IBM500 to ISO-8859-1, iconv() actually translates from IBM500 to UCS-4, and from UCS-4 to ISO-8859-1. Example 3-7 shows an example of using iconv() to convert from ISO8859-1 to the current host character set.

Example 3-7 Using iconv() to translate between character sets 1 #include 2 #include 3 #include 4 iconv_t d = iconv_open(“ISO8859-1”, nl_langinfo(CODESET)); 5 if(d != (iconv_t)-1) { 6 char inBuffer = “ABCDEF”; 7 size_t inSize = sizeof inBuffer; 8 char outBuffer[80]; 9 size_t outSize = sizeof outBuffer;

46 z/TPF Application Modernization using Standard and Open Middleware 10 char* in = inBuffer; 11 char* out = outBuffer; 12 iconv(d, &in, &inSize, &out, &outSize); 13 iconv_close(d); 14 }

Using iconv() character set conversion with user-defined character sets In addition to the two methods of character set conversion discussed, z/TPF also offers the possibility for users to add their own character set translations to the z/TPF system. Use the following steps to add new characters set translations on the z/TPF system: 1. Specify a character set translation: The z/TPF system supports all character set translations supported by the GNU C library (glibc). The translation source files are located in the directory, opensource/glibc/iconvdata. Specify the translation source file by using the name of the character set in lowercase. For example, the ibm1026.c source file translates between the IBM1026 and UCS-4 character sets. 2. Use a maketpf makefile to create a shared object that contains the character set translation: You must specify the following information in the makefile: – APP := modulename Specifies the shared object, where modulename is a valid 4-character module name. – APP_ENTRY := gconv_entry_point Specifies the entry point for iconv translation files. – maketpf_env := iconv Specifies the build environment for the iconv translation files. – maketpf_env += base_rt Specifies the build environment for the iconv translation files. – CC_SRC :=translationsourcefile Specifies the C source code, where translationsourcefile is the name of the translation source file. – CC_SRC += gconv_stub.c Specifies the stub source code for iconv translation files. Example 3-8 shows a maketpf makefile that creates the ABCD shared object for the IBM1026 character set translation.

Example 3-8 Makefile to create a shared object for character set translation 1 APP := abcd 2 APP_ENTRY := gconv_entry_point 3 ########################################################################## 4 # Define the envs needed to build this module, in the order of precedence 5 ########################################################################## 6 maketpf_env := iconv 7 maketpf_env += base_rt 8 ########################################################################## 9 # Segments to be compiled with gcc compiler 10 ########################################################################## 11 CC_SRC := ibm1026.c

Chapter 3. z/TPF SOAP processing 47 12 CC_SRC += gconv_stub.c 12 ########################################################################## 13 # Include the maketpf.rules 14 ########################################################################## 15 include maketpf.rules

3. Add the character set translation and any aliases to the iconv name table. The base/rt/civ1.c source file contains the iconv name table and aliases for the translations. Two translation entries are required for glibc-based translations. One translation entry is required to translate from the specified character set to INTERNAL (the internal wide character set, or UCS-4). The other translation entry is required to translate from INTERNAL to the specified character set. Example 3-9 shows the translations for the IBM1026 character set added to an iconv name table. Character set conversions are between the IBM1026 and INTERNAL character sets.

Example 3-9 Adding a character set translation to the iconv table 1 /* Defining the IBM1026 translation to/from INTERNAL */ 2 "IBM1026//", "INTERNAL", "ABCD", MODULE, 1 3 "INTERNAL", "IBM1026//", "ABCD", MODULE, 1 4 /*Defining IBM-1026 as an alias for IBM1026 */ 5 "IBM-1026//", "IBM1026//", "", ALIAS, 0

The following information is displayed in Example 3-9: – IBM1026// Specifies the character set. The double slash (//) suffix is a required convention for character set names and aliases. – INTERNAL Specifies the internally used wide character set, which is UCS-4 for the glibc. The double slash (//) suffix convention is not used for the INTERNAL character set. – ABCD Specifies the shared object module name, which must be the uppercase format of the shared object module name specified in the makefile. –MODULE Specifies that a module is being added. –1 Specifies a numeric value relative to the estimated processing cost to the z/TPF system. The greater the number, the greater the processing cost. – IBM-1026// Specifies the alias for the IBM1026 translation source file. –ALIAS Specifies that an alias is being added. –0 Specifies a place holder for the processing cost to the z/TPF system. A processing cost is not used for aliases. 4. Rebuild the CIV1 shared object. Load the CIV1 shared object and the new shared object containing the character set translation to the z/TPF system.

48 z/TPF Application Modernization using Standard and Open Middleware To add a new coded character set identifier (CCSID) to the z/TPF system: 1. Add a valid entry to the CCSID table that is located in the base/rt/civ2.c source file. Example 3-10 shows a CCSID entry for the IBM1026 character set.

Example 3-10 Adding a coded character set identifier 1 /* Add a CCSID for the IBM1026 character set */ 2 /* Name 2-char ID CCSIDStyle Single Double */ 3 { "IBM1026", "EW", 1026, ‘S’, 0, 0 },

The following information is displayed in Example 3-10: – IBM1026 Specifies the character set. The character set must exist in the iconv name table in the base/rt/civ1.c source file. –EW Specifies a 2-character identifier for the character set. The identifier must be a valid alias in the iconv name table that maps to the character set. – 1026 Specifies the CCSID for the character set. –S Specifies the single-character style of the character set. The following styles of a character set also are valid: D to specify a double-byte character set style, or M to specify a multibyte character set style. –0 Does not specify a CCSID, which must be compatible with the single or double-byte portion of a multibyte character set. If you specify a CCSID that is not compatible with the single or double-byte portion of a multibyte character set, results that are not predictable can occur. 2. Rebuild the CIV1 shared object and load it to the z/TPF system.

3.4 SOAP structures

While the z/TPF system is processing a SOAP message, several structures are used to hold values and information that might be used again later in the process. These structures are defined in the c_soap.h header file. They are used throughout the SOAP message flow process. The structures contain fields that have values that change to reflect appropriate processing success or failure.

Next we describe these structures and fields:  soapFault structure The soapFault structure contains information about an error that occurred on z/TPF while processing a SOAP message. This structure is completed by the caller and then used by the SOAP fault builder. The fault message ultimately is returned to the client.

Chapter 3. z/TPF SOAP processing 49 The soapFault structure contains the following fields: – XML_VERSION xmlVersion Specifies the version of XML, where xmlVersion is the version number. This field is optional. The default version is 1.0. – SOAP_VERSION version Specifies the version of SOAP, where version is the version number. This field is optional. If the field is not completed by the application, the SOAP version is determined by the value of the DEFAULT_SOAP_VERSION field in the c_soap.h header file, which is version 1.2 unless you have changed it. – encoding Identifies the encoding of the output message in human-readable character data. This field is optional. If set, this value is used in the fault message as the value of the encoding field. – detail Explains the detailed error, in human-readable character data, that is contained in child element message. This field is optional. For SOAP version 1.1, the soapFault structure contains the following additional fields: – FAULTCODE faultCode Identifies the fault code of the error, where faultCode is a predefined fault code. This field is required. Fault codes are predefined in the c_soap.h header file3. – faultString Explains the error in human-readable character data. This field is required. – faultActor Identifies who caused the error: the sender or the receiver. This field is optional. For SOAP version 1.2, the soapFault structure contains the following additional fields: – FAULTCODE code Identifies the fault code of the error, where faultCode is a predefined fault code5. This field is required. – subcodeValue Identifies a sub-category code in human-readable character data3. This field is optional. – reason Explains the error in human-readable character data. This field is required. – node Identifies which SOAP node caused the error, in human-readable character data. This field is optional. –role Identifies the role of the node that caused the error at the time of the error in human-readable character data. This field is optional.

5 See the SOAP specification on the World Wide Web Consortium (W3C) web site (http://www.w3.org/) for more information about these codes.

50 z/TPF Application Modernization using Standard and Open Middleware – language langcode Identifies the string used for the xml:lang attribute of the SOAP fault, where langcode is the language code, as defined by RFC 1766. If this field is not included, the xml:lang attribute is not included in the SOAP fault.

Tip: Any human-readable character data in this structure must be encoded in the host character set.

Example 3-11 shows the definitions for the soapFault structure. All of these are in the c_soap.h header file:  Lines 1-5 contain the macro definition for the XML version that z/TPF supports.  Lines 6-13 contain the macro definitions for the SOAP versions that z/TPF supports: 1.1 and 1.2.  Lines 14-24 show the definitions of the different SOAP fault codes.  Lines 25-39 finally shows the actual contents of the soapFault structure.

Notice that the fields that are enumerated types are declared with a Machine Mode attribute of the value SI. This forces these fields to be 4-byte integer fields.

Example 3-11 The soapFault structure 1 typedef enum { 2 XML_DEFAULT_VERSION = 0, /* legitimate default version */ 3 XML1_0 = 1, 4 XML_VERSION_NOT_USED = 0xFFFFFFFF 5 } XML_VERSION;

6 typedef enum { 7 UNKNOWN = 0, 8 SOAP1_1 = 1, 9 SOAP1_2 = 2, 10 TPF_SOAPBP11_SSBP10 = 4, 11 TPF_SOAP_DEFAULT = 8, 12 SOAP_VERSION_NOT_USED = 0xFFFFFFFF 13 } SOAP_VERSION;

14 typedef enum { 15 VersionMismatch = 1, 16 MustUnderstand = 2, 17 DataEncodingUnknown = 3, 18 Sender = 4, 19 Receiver = 5, 20 Client = 6, 21 Server = 7, 22 InvalidSecurity = 8, 23 FAULTCODE_NOT_USED = 0xFFFFFFFF 24 } FAULTCODE;

25 typedef struct { 26 XML_VERSION xmlVersion __attribute__((__mode__(SI))); 27 SOAP_VERSION version __attribute__((__mode__(SI))); 28 char *encoding; 29 char *detail;

Chapter 3. z/TPF SOAP processing 51 30 FAULTCODE faultCode __attribute__((__mode__(SI))); 31 char *faultString; 32 char *faultActor; 33 FAULTCODE code __attribute__((__mode__(SI))); 34 char *subcodeValue; 35 char *reason; 36 char *language; 37 char *node; 38 char *role; 39 } soapFault;

 soapMsg structure The soapMsg structure contains a pointer to the SOAP message itself and information about the message. There are two instances of this structure: an input instance and an output instance. The soapMsg structure contains the following fields: –XMLptr A pointer to the first byte of the XML message being passed. – msgLength Specifies the length of the XML message being passed. – options Specifies any appropriate option flags. The value of this field is 0. – SOAP_VERSION version Identifies the version of SOAP being used: • UNKNOWN SOAP version is not known; also used if the communications binding cannot determine the version without reading the actual XML document. • SOAP1_1 SOAP version is 1.1. This value and the BP1.1_SSBP1.1 value cannot both be specified for the same Web service. • SOAP1_2 SOAP version is 1.2. • TPF_SOAPBP11_SSBP10 Indicates that a SOAP request for this Web service is acceptable if it is in SOAP 1.1 format. Also, this instructs the z/TPF SOAP runtime to perform checks on the message to ensure that it is compliant with the Organization for the Advancement of Structured Information Standards (OASIS) Web Services Interoperability (WS-I) Basic Profile 1.1 and the OASIS WS-I Simple Soap Binding Profile 1.1. When a SOAP request is found to be non-compliant, the z/TPF SOAP runtime generates a SOAP fault message to be returned to the originator. This value and the SOAP1.1 value cannot both be specified for the same Web service. • TPF_SOAP_DEFAULT Indicates that SOAP requests are expected to be in the format corresponding to the SOAP version that is specified in the version field of the inputMsg parameter passed to the tpf_soap_handler function. When this value is specified, the SOAPVersion element cannot appear more than once.

52 z/TPF Application Modernization using Standard and Open Middleware – tpf_ccsid_t serverEncoding Identifies the host encoding of the z/TPF system, where serverEncoding is initially set to TPF_CCSID_NOT_SET. – tpf_ccsid_t clientEncoding Identifies the encoding of the XML message being passed, where clientEncoding is the coded character set identifier (CCSID) of the XML message.

Example 3-12 shows the definitions for the soapMsg structure. Most of these are in the c_soap.h header file:  Lines 1-8 contain the macro definitions for the SOAP versions that z/TPF supports: 1.1 and 1.2.  Line 9 is in header file tpfapi.h and contains the type definition for character code set identifiers.  Lines 10-17 contains the definition of the soapMsg structure itself.

Example 3-12 The soapMsg structure 1 typedef enum { 2 UNKNOWN = 0, 3 SOAP1_1 = 1, 4 SOAP1_2 = 2, 5 TPF_SOAPBP11_SSBP10 = 4, 6 TPF_SOAP_DEFAULT = 8, 7 SOAP_VERSION_NOT_USED = 0xFFFFFFFF 8 } SOAP_VERSION;

9 typedef unsigned short tpf_ccsid_t;

10 typedef struct { 11 char *XMLptr; 12 int msgLength; 13 int options; 14 SOAP_VERSION version __attribute__((__mode__(SI))); 15 tpf_ccsid_t serverEncoding; 16 tpf_ccsid_t clientEncoding; 17 } soapMsg;

 commsBinding structure The commsBinding structure contains information about the communication binding that received and began the processing of a SOAP message. This communication binding also is used to return a response to the client. The commsBinding structure contains the following fields: – bindingnessINDING bindingType Specifies the communication method used, where bindingType is one of the following: • HTTPthruApache Apache HTTP server is the communications binding. •MQ WebSphere MQ is used as the transport method.

Chapter 3. z/TPF SOAP processing 53 • tpf_HTTP The z/TPF HTTP server is the communications binding • Async_MQ MQ using asynchronous SOAP message processing • otherbinding A communications binding other than the Apache HTTP server or the z/TPF HTTP server is the communications binding. See the BINDING enumeration in the c_soap.h header file for acceptable values. The communications binding must be able to take a message from the network and pass the appropriate information to the SOAP handler. – applRoutingInfo Specifies appropriate application routing information. This field is initialized with a pointer to the requested URI, which is represented as a null-terminated EBCDIC string. –ECBctl Specifies options for use during communications processing: •DEFAULT Use default processing. • termAfterCxn Exit the entry control block (ECB) when the connection ends. • termAfterReply Exit the ECB after the reply has been sent. The ECBctl field is extendable. Example 3-13 shows the definitions for the commsBinding structure. All of these are in the c_soap.h header file: – Lines 1-8 define the bindings that are currently available on the z/TPF system. Values higher than 128 can be used for user defined bindings. – Lines 9-16 show the definition of the commsBinding structure.

Example 3-13 The commsBinding structure 1 typedef enum { 2 HTTPthruApache = 1, 3MQ= 2, 4 LocalTPFFULL = 3, 5 LocalTPFParsed = 4, 6 tpf_HTTP = 5, 7 MQ_Async = 6 8 } BINDING;

9 typedef struct { 10 BINDING bindingType; 11 char *applRoutingInfo; 12 int ECBctl; 13 #define DEFAULT0x00000000 14 #define termAfterCxn0x00000001 15 #define termAfterReply 0x00000002 16 } commsBinding;

54 z/TPF Application Modernization using Standard and Open Middleware 4

Chapter 4. The z/TPF communications bindings

This chapter discusses the ways SOAP messages arrive on the z/TPF system and how the z/TPF system can be customized to receive SOAP messages through various communications channels. There is also a discussion on the various components on TPF that are involved in the various communications layers and how they can be configured and used.

This chapter contains the following topics:  4.1, “Internet daemon” on page 56  4.2, “SOAP over HTTP” on page 68  4.3, “SOAP over WebSphere MQ for z/TPF” on page 83

© Copyright IBM Corp. 2013. All rights reserved. 55 4.1 Internet daemon

The Internet daemon is a socket application that creates and monitors sockets with remote nodes on the Internet and then starts Internet server applications that process the specific communications protocol used with the remote nodes. When a connection is made, the Internet server application communicates with the remote node on the Internet directly.

Internet server applications are also socket applications. For example, a Trivial File Transfer Protocol (TFTP) server, a File Transfer Protocol (FTP) server, and a Hypertext Transfer Protocol (HTTP) server are socket applications.

The Internet daemon is a long-running process that consists of two major components:  The Internet daemon monitor, which is responsible for starting and stopping the Internet daemon listeners for Internet server applications and for error recovery when an Internet daemon listener fails.  An Internet daemon listener, which monitors the Internet server applications and, with some process models, creates and monitors a socket for the Internet server application.

There are process models that define the interface to the Internet daemon based on the level of control required by an Internet server application. There are subtle differences in the functions used by the Internet daemon, which relate to the level of control that results.

The WAIT, NOWAIT, or DAEMON process model provides synchronous control because tpf_fork() is used to create a child process for which the z/TPF system sends a SIGCHLD signal to the parent process when the child process ends. The DAEMON process model differs from the WAIT and NOWAIT process models in that the Internet daemon does not create or monitor sockets. We do not discuss the DAEMON process in the remainder of this chapter.

The AOA process model offers asynchronous control for TCP servers by using activate_on_accept(). The Internet daemon issues the first activate_on_accept() call. When the first remote client connects, your TCP server application is activated in a new ECB. Your server application must issue the next activate_on_accept() call. The Internet daemon continues to monitor the server application and listener socket. As a variation hereof, a model called AOA2 was lastly added to the Internet daemon, which is mostly like the AOA model. The only difference is that in the AOA2 model, the Internet daemon issues the activate_on_accept() on behalf of the server application before it activates the server application.

The AOR process model provides asynchronous control because activate_on_receipt() or activate_on_receipt_with_length() is used. When a remote client connects, the Internet daemon issues an activate_on_receipt() or activate_on_receipt_with_length() to pass control of the new socket to your TCP server application when the first message is received from the remote client.

The NOLISTEN process model does not provide any control, and swisc_create() is used to create an independent ECB. For this reason, the NOLISTEN model is not discussed in the remainder of this chapter.

4.1.1 The Internet daemon process models in detail

There are seven process models that define the interface to the Internet daemon based on the level of control required by an Internet server application. There are subtle differences in the functions used by the Internet daemon, which relate to the level of control that results.

56 z/TPF Application Modernization using Standard and Open Middleware This section discusses the relevant ones in the context of this book (WAIT, NOWAIT, AOR, and AOA) in more detail. Figure 4-1 presents a brief overview of the most simple example of TCP/IP communication between a client and a server.

Server Client

socket s socket s

bind s bind s

listen s

accept s connect s

read and write ns write and read s

close ns close s

Figure 4-1 TCP/IP communications between client and server

A TCP/IP server must establish a communications endpoint for TCP/IP clients to connect to, and monitor, that endpoint so that action can be taken when it is contacted or data arrives. Establishing the communications endpoint (socket) consists of these basic steps: 1. socket: socket() creates an endpoint for communication and returns a socket descriptor representing the endpoint. 2. bind: bind() binds a unique local name to the socket. 3. listen: listen() completes the binding necessary for a socket and creates a connection request queue for incoming requests. 4. accept: accept() is used by a server to accept a connection request from a client. accept() creates a new socket descriptor (ns) with the same properties as the existing one (s). Do not use the new socket to accept new connections. The original socket (s) remains available to accept more connection requests.

The server is now in a state where clients can access it. The basic steps on the client are these: 1. socket: socket() creates an endpoint for communication and returns a socket descriptor representing the endpoint.

Chapter 4. The z/TPF communications bindings 57 2. bind: bind() binds a unique local name to the socket. 3. connect: connect() requests a connection to a remote host. When a connect completes successfully, the result is a fully established client-server connection that data can be exchanged over. 4. write and read: A typical client sends some type of request message, after the connection was established, using a write-type function1, and waits for some type of response message from the server using a read-type function2. This process of exchanging data can continue as long as the client decides to. 5. close: close() shuts down a socket and frees resources allocated to that socket. The close on the client side also triggers a close on the server side.

The Internet daemon process models are variations upon this theme that exist with the purpose to meet specific application model requirements. The previously shown TCP/IP functions are shown again, as the Internet daemon uses some of these, depending on the process model and a number of z/TPF specific functions.

The WAIT process model The Internet daemon WAIT process is shown in Figure 4-2.

Server Child Server Client

socket s socket s

bind s bind s

listen s

accept s connect s

New ECB tpf_fork ns

read and write ns write and read s

...waiting close ns close s

Figure 4-2 The internet daemon WAIT process model

1 Such as write(), send(), or sendto(). 2 Such as read(), recv(), or recvfrom().

58 z/TPF Application Modernization using Standard and Open Middleware The WAIT process model is for an Internet server application that is an iterative or single-thread program. The Internet daemon starts the Internet server application as a child process using tpf_fork() and does not start any more occurrences of the Internet server application until the one that is running ends.

As is shown in Figure 4-2 on page 58, the Internet daemon creates and monitors the listener socket using the following steps: 1. socket: socket() creates an endpoint for communication and returns a socket descriptor representing the endpoint. 2. bind: bind() binds a unique local name to the socket. 3. listen: listen() completes the binding necessary for a socket and creates a connection request queue for incoming requests. 4. accept: accept() is used by a server to accept a connection request from a client. accept() creates a new socket descriptor (ns) with the same properties as the existing one (s). Do not use the new socket to accept new connections. The original socket (s) remains available to accept more connection requests.

The server is now in a state where clients can access it. The basic steps on the client are: 1. socket: socket() creates an endpoint for communication and returns a socket descriptor representing the endpoint. 2. bind: bind() binds a unique local name to the socket. The bind by a TCP/IP client is optional. 3. connect: connect() requests a connection to a remote host. When a connect completes successfully, the result is a fully established client-server connection that data can be exchanged over. When a remote client connects, the Internet daemon uses tpf_fork() to start the server application as a child process. The new socket (ns) that was created by accept() is passed on to the child process, so that the actual connection exists between the client and the child server ECB. The Internet daemon does not start any more occurrences of the Internet server application until the one that is running ends. Instead it waits for the child server to end, and after that loops back to the accept phase to be ready to process another client connection request. After the connection is established between the client and the child server ECB, the actual conversation between them can take place, as follows. 4. write and read: A typical client sends some type of request message, after the connection was established, using a write-type function3, and waits for some type of response message from the server using a read-type function4. This process of exchanging data can continue as long as the client decides to.

3 Like write(), send(), or sendto(). 4 Like read(), recv(), or recvfrom().

Chapter 4. The z/TPF communications bindings 59 5. close: close() shuts down a socket and frees resources allocated to that socket. The close on the client side also triggers a close on the server side.

The NOWAIT process model The Internet daemon NOWAIT process model is shown in Figure 4-3.

Server Child Server Client

socket s socket s

bind s bind s

listen s

accept s connect s

New ECB tpf_fork ns

read and write ns write and read s

close ns close s

Figure 4-3 The internet daemon NOWAIT process model

The NOWAIT process model is for an Internet server application that is a concurrent or multi-thread program. The Internet daemon starts the Internet server application as a child process using tpf_fork() and continues to start more occurrences of the Internet server application until a predefined limit is reached. When the limit is reached, no more occurrences are started until an occurrence that was previously started ends.

As is shown in Figure 4-3, the Internet daemon creates and monitors the listener socket using the following steps: 1. socket: socket() creates an endpoint for communication and returns a socket descriptor representing the endpoint. 2. bind: bind() binds a unique local name to the socket. 3. listen: listen() completes the binding necessary for a socket and creates a connection request queue for incoming requests. 4. accept: accept() is used by a server to accept a connection request from a client. accept() creates a new socket descriptor (ns) with the same properties as the existing one (s). Do not use

60 z/TPF Application Modernization using Standard and Open Middleware the new socket to accept new connections. The original socket (s) remains available to accept more connection requests.

The server is now in a state where clients can access it. The basic steps on the client are: 1. socket: socket() creates an endpoint for communication and returns a socket descriptor representing the endpoint. 2. bind: bind() binds a unique local name to the socket. The bind by a TCP/IP client is optional. 3. connect: connect() requests a connection to a remote host. When a connect completes successfully, the result is a fully established client-server connection that data can be exchanged over. When a remote client connects, the Internet daemon uses tpf_fork() to start the server application as a child process. The new socket (ns) that was created by accept() is passed on to the child process, so that the actual connection exists between the client and the child server ECB. The Internet daemon does then loops back immediately after to the accept to be ready to accept more client connection requests. After the connection is established between the client and the child server ECB, the actual conversation between them can take place, as follows: 4. write and read: A typical client sends some type of request message, after the connection was established, using a write-type function5, and waits for some type of response message from the server using a read-type function6. This process of exchanging data can continue as long as the client decides to. 5. close: close() shuts down a socket and frees resources allocated to that socket. The close on the client side also triggers a close on the server side.

The AOA process model The Internet daemon AOA process model is shown in Figure 4-4 on page 62.

5 Like write(), send(), or sendto(). 6 Like read(), recv(), or recvfrom().

Chapter 4. The z/TPF communications bindings 61 Server Server N Client

socket s socket s

bind s bind s

listen s

ns=activate_on_accept s connect s s ns

New ECB

ns2=activate_on_accept s

read and write ns write and read s

close ns close s

Figure 4-4 The internet daemon AOA process model

The AOA process model is for an Internet server application that is a concurrent or multi-thread program. The Internet daemon creates the listener socket and issues a first activate_on_accept() call.

As is shown in Figure 4-4, the Internet daemon creates and monitors the listener socket using the following steps: 1. socket: socket() creates an endpoint for communication and returns a socket descriptor representing the endpoint. 2. bind: bind() binds a unique local name to the socket. 3. listen: listen() completes the binding necessary for a socket and creates a connection request queue for incoming requests. 4. activate_on_accept: activate_on_accept() allows the issuing entry control block (ECB) to exit and activate a different ECB in the program specified when a remote client is connected. Like accept() activate_on_accept() creates the new socket ns with the same properties as the existing one (s). Do not use the new socket to accept new connections. The original socket (s) remains available to accept more connection requests.

62 z/TPF Application Modernization using Standard and Open Middleware The server is now in a state where clients can access it. The basic steps on the client are: 1. socket: socket() creates an endpoint for communication and returns a socket descriptor representing the endpoint. 2. bind: bind() binds a unique local name to the socket. The bind by a TCP/IP client is optional. 3. connect: connect() requests a connection to a remote host. When a connect completes successfully, the result is a fully established client-server connection that data can be exchanged over. When a remote client connects, a child server ECB is created because of the server’s call to activate_on_accept(). The child server receives both sockets s and ns, and must first issue the next activate_on_accept() call to accept another connection from the remote client, before doing anything else to ensure continuous server availability. After the connection is established between the client and the child server ECB, the actual conversation between them can take place, as follows. 4. write and read: A typical client sends some type of request message, after the connection was established, using a write-type function7, and wait for some type of response message from the server using a read-type function8. This process of exchanging data can continue as long as the client decides to. 5. close: close() shuts down a socket and frees resources allocated to that socket. The close on the client side also triggers a close on the server side.

7 Like write(), send(), or sendto(). 8 Like read(), recv(), or recvfrom().

Chapter 4. The z/TPF communications bindings 63 The AOA2 process model The AOA2 process model is shown in Figure 4-5.

INETD Server Server N Client

socket s socket s

bind s bind s

listen s

ns=activate_on_accept s connect s

New ECB (s, ns)

ns2=activate_on_accept s

Enter server program read and write ns write and read s ns

close ns close s

Figure 4-5 The internet daemon AOA2 process model

The AOA2 process model is for an Internet server application that is a concurrent or multi-thread program. With the AOA2 process model, the Internet daemon creates the listener socket and issues all activate_on_accept() calls on behalf of the application.

As is shown in Figure 4-5, the Internet daemon creates and monitors the listener socket using the following steps: 1. socket: socket() creates an endpoint for communication and returns a socket descriptor representing the endpoint. 2. bind: bind() binds a unique local name to the socket. 3. listen: listen() completes the binding necessary for a socket and creates a connection request queue for incoming requests. 4. activate_on_accept: activate_on_accept() allows the issuing entry control block (ECB) to exit and activate a different ECB when a remote client is connected. Like accept() activate_on_accept() creates the new socket (ns) with the same properties as the existing one (s). In the AOA2 model, the subsequent activate_on_accept calls are issued by the internet daemon.

64 z/TPF Application Modernization using Standard and Open Middleware The server is now in a state where clients can access it. The basic steps on the client are these: 1. socket: socket() creates an endpoint for communication and returns a socket descriptor representing the endpoint. 2. bind: bind() binds a unique local name to the socket. The bind by a TCP/IP client is optional. 3. connect: connect() requests a connection to a remote host. When a connect completes successfully, the result is a fully established client-server connection that data can be exchanged over. In the AOA2 process model, when the remote client connects, a new ECB is created because of the server’s call to activate_on_accept(). The new ECB enters an internet daemon program that issues the next activate_on_accept() call to accept subsequent connection requests. The newly created ECB then enters the child server passing the connected socket ns. After the child server is invoked, the actual conversation between the client and the child server can take place, as described in the following steps. 4. write and read: A typical client sends some type of request message, after the connection was established, using a write-type function9, and waits for some type of response message from the server using a read-type function10. This process of exchanging data can continue as long as the client decides to. 5. close: close() shuts down a socket and frees resources allocated to that socket. The close on the client side also triggers a close on the server side.

9 Like write(), send(), or sendto() 10 Like read(), recv(), or recvfrom()

Chapter 4. The z/TPF communications bindings 65 The AOR process model The AOR process model is shown in Figure 4-6.

Server Child Server Client

socket s socket s

bind s bind s

listen s

accept s connect s

New ECB activate_on_receipt ns write s ns

read and write ns write and read s

close ns close s

Figure 4-6 The internet daemon AOR process model

The AOR process model is for an Internet server application that is a concurrent or multi-thread program. The Internet daemon creates and monitors the listener socket and uses activate_on_receipt() to spawn off child servers.

As is shown in Figure 4-6, the Internet daemon creates and monitors the listener socket using the following steps: 1. socket: socket() creates an endpoint for communication and returns a socket descriptor representing the endpoint. 2. bind: bind() binds a unique local name to the socket. 3. listen: listen() completes the binding necessary for a socket and creates a connection request queue for incoming requests. 4. accept: accept() is used by a server to accept a connection request from a client. accept() creates a new socket descriptor (ns) with the same properties as the existing one (s). Do not use the new socket to accept new connections. The original socket (s) remains available to accept more connection requests. 5. activate_on_receipt: activate_on_receipt() allows the issuing ECB to exit and activate a different ECB at the program specified after information has been received.

66 z/TPF Application Modernization using Standard and Open Middleware The server is now in a state where clients can access it. The basic steps on the client are: 1. socket: socket() creates an endpoint for communication and returns a socket descriptor representing the endpoint. 2. bind: bind() binds a unique local name to the socket. The bind by a TCP/IP client is optional. 3. connect: connect() requests a connection to a remote host. When a connect completes successfully, the result is a fully established client-server connection that data can be exchanged over. After the connection is established between the client and the child server ECB, the actual conversation between them can take place, as described in the following steps. 4. write and read: A typical client sends some type of request message, after the connection was established, using a write-type function11. This is when the child server ECB is created: at the receipt of the first data from the TCP/IP client. The child server is passed the new socket 1(ns), which was created by the accept at connection time, so that the conversation can continue between the client and the child server ECB. The client then typically waits for some type of response message from the server using a read-type function12. This process of exchanging data can continue as long as the client decides to. 5. close close() shuts down a socket and frees resources allocated to that socket. The close on the client side also triggers a close on the server side.

Because these process models provide different levels of control, the overhead of system resource can be affected. The AOA and AOR process models have the potential to use system resources more effectively than the WAIT and NOWAIT process models. The AOR process model uses activate_on_receipt() or activate_on_receipt_with_length() to create the entry control block (ECB) for the Internet server application only after data is received on a connected socket, whereas the WAIT and NOWAIT process models use tpf_fork() to create an ECB for immediate processing, which requires the Internet server application to request data and then wait for the data to arrive. The AOA process model uses activate_on_accept() to create the entry control block (ECB) for the Internet server application only after a connection request is received from the remote client.

In general, a ported Internet server application uses the WAIT or NOWAIT process model and an Internet server application designed specifically for z/TPF architecture uses the AOA or AOR process model.

When the Internet daemon is running, there is one long-running ECB for the Internet daemon monitor program and one long-running ECB for each server application that the Internet daemon is monitoring. Some E-type loader operations are not completed until all old ECBs exit in the system. When the Internet daemon detects that the system activation number has changed, the Internet daemon recycles itself. A new instance of the Internet daemon is immediately created in new ECBs, and the old Internet daemon ECBs exit when all their child processes end.

11 Like write(), send(), or sendto() 12 Like read(), recv(), or recvfrom().

Chapter 4. The z/TPF communications bindings 67 When the Internet daemon recycles, the effect on the server application and sockets is based on the process model:  For the WAIT, NOWAIT, AOA, and AOR process models, there is no disruption to the sockets. The fact that the Internet daemon has recycled itself is completely transparent to the server and remote client applications.  For the NOLISTEN process model, no action is taken when the Internet daemon recycles. Servers using these models are activated when the Internet daemon first starts and, after that, the Internet daemon does not monitor those applications.  For the DAEMON process model, the Internet daemon issues a call to kill() to stop the old application server instance. The new instance of the Internet daemon starts a new server application instance as soon as the old server instance ends. The Internet daemon does not create or monitor sockets for this process model; therefore, your application must take the appropriate actions regarding any sockets that it created. A common implementation is for the old server application to close the sockets and have the new server application instance start new sockets. Another method is to keep the sockets active by having the old server application instance save the socket descriptors in a user table that the new server application instance picks up and uses.

When you enter the ZINET STOP command to stop a server application, the actions that are taken are based on the process model:  For a TCP server using the WAIT, NOWAIT, AOA, or AOR process models, the listener socket is closed and no new connections can be started with this server. Existing connections (sockets) between remote clients and this server are allowed to continue their normal processing. If you want to break the existing connections that use TCP/IP native stack support, enter ZSOCK INACT LPORT-lport, where lport is the port number of the TCP server application.  For a UDP server using the WAIT or NOWAIT process models, the socket is closed.  For the NOLISTEN process model, no action is taken because the Internet daemon does not monitor these process models.  For the DAEMON process model, the Internet daemon issues kill() to stop the application server. When using this process model, ensure that your Internet server application uses signal() to enable the SIGTERM signal.

4.2 SOAP over HTTP

The Hypertext Transfer Protocol (HTTP) is a popular communications layer to transport SOAP messages. Since SOAP is transport protocol independent, SOAP messages by no means have to travel on HTTP, but HTTP is a widely used protocol to have SOAP messages transported on. The Apache HTTP server or z/TPF HTTP server can be used to transport SOAP messages from remote clients into z/TPF.

4.2.1 Apache 2.2

The Apache HTTP Server is a fully functional web server developed and maintained by an open community of developers. Using z/TPF Internet server support, the Apache server can be installed so that Web pages can be retrieved and z/TPF applications can be started from the Internet.

Apache HTTP is able to recognize and process SOAP messages only after you have installed the mod_tpf_soap module piece of the Apache program.

68 z/TPF Application Modernization using Standard and Open Middleware For information about how to install the Apache HTTP server on the z/TPF system, go to: http://tpf.ncsa.illinois.edu/download/readme-ztpfapache2.html

For more information about using the Apache HTTP server, see the Apache Web page at: http://httpd.apache.org/

Apache on z/TPF supports SSL.

Figure 4-7 shows which software components are used to manage which parts of the protocol stack when Apache is used as the HTTP server on z/TPF.

Application Data Application

SOAP Application XML Handler

SOAP Handler SOAP mod_tpf_soap

HTTP Apache

TCP

Internet Daemon IP

Figure 4-7 Software and protocol components for SOAP using the Apache Web server

The core of SOAP message processing in program mod_tpf_soap.c takes place in soap_handler(), which is shown in Example 4-1 and discussed in some detail in the following paragraphs.

Example 4-1 Apache mod_tpf_soap function soap_handler() 1 static int soap_handler(request_rec *r) 2 { 3 /* soap_handler is called once per request */ 4 5 char error_text[100]; 6 const char *data; 7 const char *lenp = NULL; 8 const char *charset = NULL; 9 apr_bucket_brigade *bb = NULL; 10 apr_bucket *bucket = NULL; 11 apr_size_t len_read = 0; 12 apr_off_t total = 0; 13 conn_rec *c = r->connection; 14 int retval = 0; 15 int len_max = 0; 16 int seen_eos = 0; 17 int child_stopped_reading = 0; 18 int len_from_contentLength = 0; 19 char *soap_buffer = NULL;

Chapter 4. The z/TPF communications bindings 69 20 21 22 #ifdef TPF_SOAP_MIXED_TRAFFIC 23 if (strcmp(r->handler, "soap-script")) { 24 return DECLINED; 25 } 26 #endif 27 /***************************************************************/ 28 /* This check determines which HTTP methods mod_tpf_soap will */ 29 /* handle. This sample mod_tpf_soap handles GET and POST. */ 30 /***************************************************************/ 31 if (strcmp(r->method, "GET") && strcmp(r->method, "POST")) { 32 return DECLINED; 33 /* Returning DECLINED causes Apache to look for another 34 handler to process the request. 35 Return HTTP_NOT_IMPLEMENTED instead of DECLINED 36 if you want to prohibit certain methods, rather than 37 deferring them to Apache. HTTP_NOT_IMPLEMENTED will cause 38 an HTTP 501 to be returned to the requestor. */ 39 } 40 41 /* decline requests without a URI */ 42 if (strcmp(r->uri, "/") == 0) { 43 return DECLINED; 44 } 45 46 /* len_max limits the size of incoming messages to prevent 47 unreasonably large requests. The nbr used here is arbitrary. 48 Setting len_max could be done at startup time by adding a 49 run-time configuration directive to mod_tpf_soap. */ 50 51 len_max = 69999; 52 ap_add_common_vars(r); 53 54 bb = apr_brigade_create(r->pool, c->bucket_alloc); 55 56 /*********************************************/ 57 /* WSI conformance checks for http */ 58 /*********************************************/ 59 #ifdef WSI_VALIDATION 60 const char *SOAPAction = NULL; 61 62 /* R1140/R1141 */ 63 /* Apache is an http 1.1 server with optional 1.0 proxy. */ 64 if (r->proto_num != 1001) { /* 1.1 = 1001 */ 65 r->status = 400; 66 r->status_line = "400 Bad Request"; 67 ap_pass_brigade(r->output_filters, bb); 68 return OK; 69 } 70 71 /* R1108 */ 72 /* Example: http extension framework 73 HTTP/1.1 200 OK 74 Date: Sun, 25 Oct 1998 08:12:31 GMT

70 z/TPF Application Modernization using Standard and Open Middleware 75 Expires: Sun, 25 Oct 1998 08:12:31 GMT 76 Ext: 77 Cache-Control: no-cache="Ext", max-age=3600 */ 78 79 if (apr_table_get(r->headers_in, "Ext")) { 80 r->status = 400; 81 r->status_line = "400 Bad Request"; 82 ap_pass_brigade(r->output_filters, bb); 83 return OK; 84 } 85 86 /* R1109/R1119 */ 87 /* no checks today for anything SOAP in main line Apache */ 88 89 /* Examples: 90 SOAPAction: "http://electrocommerce.org/abc#MyMessage" 91 SOAPAction: "myapp.sdl" 92 SOAPAction: "" 93 SOAPAction: 94 */ 95 96 if (SOAPAction = apr_table_get(r->headers_in, "SOAPAction")) { 97 if (SOAPAction[0] != '"' || 98 SOAPAction[strlen(SOAPAction)-1] != '"') { 99 r->status = 400; 100 r->status_line = "400 Bad Request"; 101 ap_pass_brigade(r->output_filters, bb); 102 return OK; 103 } 104 } 105 106 /* R1132/R1114: */ 107 if (strcmp(r->method, "GET") == 0) { 108 r->status = 405; 109 r->status_line = "405 Method Not Allowed"; 110 ap_pass_brigade(r->output_filters, bb); 111 return OK; 112 } 113 #endif 114 115 116 lenp = apr_table_get(r->headers_in, "Content-Length"); 117 if (lenp) { 118 len_from_contentLength = apr_atoi64(lenp); 119 } 120 121 /* get a buffer for the incoming message - note that this must 122 be a calloc and not an apr_pcalloc since the memory may be 123 released outside of Apache. */ 124 soap_buffer = calloc(1, len_from_contentLength+1); 125 126 if (soap_buffer == NULL) { 127 sprintf(error_text, "mod_tpf_soap: Memory allocation error on %i bytes", 128 len_from_contentLength+1);

Chapter 4. The z/TPF communications bindings 71 129 apr_table_merge(r->notes, "error-notes", error_text+14); 130 /* this next line is required if you want the client to see this 131 "error-notes" for HTTP_INTERNAL_SERVER_ERROR responses */ 132 apr_table_setn(r->notes, 103 "verbose-error-to", 134 apr_pstrdup(r->pool, "*")); 135 ap_log_rerror(APLOG_MARK, APLOG_CRIT|APLOG_NOERRNO, 0, 136 r, error_text); 137 return HTTP_INTERNAL_SERVER_ERROR; 138 } 139 140 do { 141 /* return from ap_get_brigade is a status */ 142 retval = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, 143 APR_BLOCK_READ, HUGE_STRING_LEN); 144 145 if (retval != APR_SUCCESS) { 146 if (APR_STATUS_IS_TIMEUP(retval)) { 147 ap_log_rerror(APLOG_MARK, APLOG_ERR, retval, r, 148 "Timeout during reading request entity data"); 149 return HTTP_REQUEST_TIME_OUT; 150 } 151 ap_log_rerror(APLOG_MARK, APLOG_ERR, retval, r, 152 "Error reading request entity data"); 153 return HTTP_INTERNAL_SERVER_ERROR; 154 } 155 156 for (bucket = APR_BRIGADE_FIRST(bb); 157 bucket != APR_BRIGADE_SENTINEL(bb); 158 bucket = APR_BUCKET_NEXT(bucket)) { 159 160 if (APR_BUCKET_IS_EOS(bucket)) { 161 seen_eos = 1; 162 break; 163 } 164 165 /* We can't do much with this. */ 166 if (APR_BUCKET_IS_FLUSH(bucket)) { 167 continue; 168 } 169 170 /* If the child stopped, we still must read to EOS. */ 171 if (child_stopped_reading) { 172 continue; 173 } 174 175 /* read */ 176 177 apr_bucket_read(bucket, &data, &len_read, APR_BLOCK_READ); 178 179 memcpy(((uintptr_t) soap_buffer)+total, data, len_read); 180 total += len_read; 181 182 apr_brigade_cleanup(bb); 183

72 z/TPF Application Modernization using Standard and Open Middleware 184 } 185 } 186 while (!seen_eos); 187 188 apr_brigade_cleanup(bb); 189 190 if (total == 0) { 191 sprintf(error_text, 192 "mod_tpf_soap: Posted data was %i bytes", total); 193 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, 194 r, error_text); 195 /* no need to set error-notes since HTTP_BAD_REQUEST doesn't */ 196 /* call them */ 197 return HTTP_BAD_REQUEST; 198 } 199 200 if (total > len_max) { 201 sprintf(error_text, "Content-length of %i exceeded %i byte limit", 202 total, len_max); 203 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, 204 r, error_text); 205 /* HTTP_REQUEST_ENTITY_TOO_LARGE */ 206 /* creates it's own 'notes' message back to the client */ 207 return HTTP_REQUEST_ENTITY_TOO_LARGE; 208 } 209 210 if (len_from_contentLength != total) { 211 /* data read didn't match Content-Length from http header */ 212 if (total > len_from_contentLength) { 213 sprintf(error_text, 214 "mod_tpf_soap: Posted data exceeds initial" 215 " Content-length of %i bytes", 216 len_from_contentLength); 217 } else { 218 sprintf(error_text, 219 "mod_tpf_soap: Posted data was %i bytes" 220 " but initial Content-length was %i", 221 total, len_from_contentLength); 222 } 223 /* no need to set error-notes since HTTP_BAD_REQUEST */ 224 /* doesn't call them */ 225 ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 226 0, r, error_text); 227 return HTTP_BAD_REQUEST; 228 } 229 230 memset(inputMsg, 0, sizeof(soapMsg)); 231 memset(outputMsg, 0, sizeof(soapMsg)); 232 memset(binding, 0, sizeof(commsBinding)); 233 234 inputMsg->version = SOAP1_2; 235 236 inputMsg->msgLength = total; 237 inputMsg->XMLptr = soap_buffer; 238

Chapter 4. The z/TPF communications bindings 73 239 inputMsg->clientEncoding = ccsid_lookup(r); 240 if (inputMsg->clientEncoding == 0) { 241 if (inputMsg->XMLptr) { 242 free (inputMsg->XMLptr); 243 } 244 return HTTP_BAD_REQUEST; 245 } 246 247 binding->bindingType = HTTPthruApache; 248 binding->applRoutingInfo = r->uri; 249 250 retval = tpf_soap_handler(inputMsg, outputMsg, binding); 251 252 if (binding->ECBctl == termAfterReply) { 253 r->connection->keepalive = AP_CONN_CLOSE; 254 ap_max_requests_per_child = 1; 255 } else 256 if (binding->ECBctl == termAfterCxn) { 257 ap_max_requests_per_child = 1; 258 } 259 260 /* build the content type line: "text/xml; charset=foobar" */ 261 switch (outputMsg->clientEncoding) { 262 case TPF_CCSID_LATIN1: 263 charset = TPF_CSNAME_LATIN1; 264 break; 265 case TPF_CCSID_UTF8: 266 charset = TPF_CSNAME_UTF8; 267 break; 268 case TPF_MY_HOST_CCSID: 269 charset = TPF_MY_HOST_CSNAME; 270 break; 271 case TPF_CCSID_UTF16BE: 272 charset = TPF_CSNAME_UTF16BE; 273 break; 274 default: 275 /* if charset is "none of the above" just skip it */ 276 break; 277 } 278 279 ap_set_content_length(r, outputMsg->msgLength); 280 281 r->content_type = CONTENT_TYPE; 282 ap_set_content_type(r, 283 apr_pstrcat(r->pool, 284 r->content_type, 285 "; charset=", 286 charset, 287 NULL)); 288 289 /* set status code and status line text (taken from httpd.h) */ 290 switch (retval) { 291 case SendReply: 292 r->status = 200; 293 r->status_line = "200 OK";

74 z/TPF Application Modernization using Standard and Open Middleware 294 if (outputMsg->XMLptr) { 295 if (r->header_only) { 296 /* HEAD, skip sending reply text */ 297 free(outputMsg->XMLptr); 298 outputMsg->XMLptr = NULL; 299 } 300 } 301 break; 302 case SendErrorReplySender: 303 r->status = 400; 304 r->status_line = "400 Bad Request"; 305 break; 306 default: 307 /* covers SendErrorReplyReceiver, ErrorReplyNeeded, 308 and anything else we end up getting */ 309 r->status = 500; 310 r->status_line = "500 Internal Server Error"; 311 break; 312 } 313 314 /* send the reply */ 315 if (outputMsg->XMLptr) { 316 ap_rwrite(outputMsg->XMLptr, outputMsg->msgLength, r); 317 free(outputMsg->XMLptr); 318 outputMsg->XMLptr = NULL; 319 } 320 return OK; 321 }

Note the following explanations for Example 4-1 on page 69:  Line 1 is the start of soap_handler(). The function is called once for every SOAP request. The input to the function is a data structure request_rec, which is defined in the Apache header file httpd.h and contains all data that is related to an HTTP request message.  Lines 22-26 are used if mod_tpf_soap was compiled with the TPF_SOAP_MIXED_TRAFFIC flag indicating that both SOAP and non-SOAP traffic is handled by this server. If the handler name is not "soap-script" the request is considered non-SOAP traffic and DECLINED is returned which causes Apache to look for another handler to process the request. The handler name for a given request can be controlled by the AddHandler and SetHandler Apache directives. See the following website for more details: http://httpd.apache.org/docs/current/mod/directives.html  Lines 27-39 determine which HTTP methods mod_tpf_soap will handle. This mod_tpf_soap handles both GET and POST HTTP methods. All other HTTP methods return DECLINED which causes Apache to look for another handler to process the request. Return HTTP_NOT_IMPLEMENTED instead of DECLINED if you want to prohibit certain methods, rather than deferring them to Apache. HTTP_NOT_IMPLEMENTED causes an HTTP 501 to be returned to the requestor.  Lines 41-44 cause requests arriving without a Uniform Resource Identifier13 (URI) to be declined.

Chapter 4. The z/TPF communications bindings 75  Lines 59-113 perform some web services Interoperability validation if mod_tpf_soap was compiled with the WSI_VALIDATION flag defined. For example, the HTTP method is restricted to GET so a PUT will return 405 Method Not Allowed.  Lines 140-228 handle the reading of additional data from the requesting client, if necessary.  Lines 230-248 set up the SOAP handler input data, and specifically the input soapMsg structure and the commsBinding structure.  Line 250 contains the call to the z/TPF SOAP handler.  Lines 252-258 allow the called SOAP handler to cause the Apache child process to exit earlier than it normally would. This is helpful if the handler ties up resources that are not returned until the ECB exits.  Lines 260-319 wrap the output message in HTTP format, set HTTP return values, and send the output message to the requesting client.

4.2.2 z/TPF HTTP Server

z/TPF HTTP server support provides a simple network transport HTTP server to receive and forward SOAP messages to SOAP applications. Although the z/TPF HTTP server does not fully conform with the published HTTP standard in RFC 2616, the features supported (such as POST and GET methods and persistent connections) are compliant with the standard to ensure platform interoperability.

In addition, unlike the Apache HTTP Server, the z/TPF HTTP Server provides a mechanism for asynchronous message processing. For example, if a SOAP over HTTP request is received to the Apache HTTP Server and that service invoked must call another service located on a remote system. During the life of this processing, the original ECB that received the request from the Apache Web Server is waiting on a response from the remote system.

With the z/TPF HTTP Server, if the server application needs to send a request to another system, the original server ECB can exit, releasing system resources.

The z/TPF HTTP server is controlled by the z/TPF Internet Server support. When a client connection is established on the server, a client connection token is created and a new entry is added to the client connection table. The connection token can be passed to the ECB that will be sending the response.

Defining a z/TPF HTTP server To define the z/TPF HTTP server to the z/TPF system, an Internet Server definition must be created. For example, the Internet Server command to define the z/TPF HTTP Server may look like the following:

ZINET ADD S-ZTPFSOAP MODEL-NOLISTEN PGM-CHT1 STATE-CRAS IP-ANY PORT-82

Before the z/TPF HTTP Server can be started, two configuration files need to be created and FTP’s to the z/TPF system. Use the following steps: 1. Define the z/TPF HTTP Server configuration file to define various server capabilities, as shown in Example 4-2.

13 URIs are defined by RFC3986, “Uniform Resource Identifier (URI): Generic Syntax,” and consist of three parts: a scheme, a domain name, and a path. For example, in the URI http://www.redbooks.ibm.com/redbooks.nsf/redbooks/ the scheme is http, the domain name is www.redbooks.ibm.com, and the path is /redbooks.nsf/redbooks.

76 z/TPF Application Modernization using Standard and Open Middleware Example 4-2 Sample z/TPF HTTP Server configuration file PERSIST-YES PERSIST_TIMEOUT-60 MAXCONN-50 BACKLOG-15 WSI_CONFORM-YES MAXMSGSIZ-4096

2. Transfer the file to /etc/tpf_httpserver with the following naming convention: INETD-SERVER-NAMEhttp.conf Where INETD-SERVER-NAME is the uppercase server name defined to the z/TPF system using ZINET ADD (see http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztp fdf.doc_put.cur/gtpo1/cmd_zinetadd.html). 3. Define the z/TPF HTTP Server URL-mapping file. This file associates URLs with z/TPF applications. Example 4-3 shows a sample URL mapping file with each service having a timeout of 30 seconds (30,000 milliseconds).

Example 4-3 Sample URL mapping file /mywebservices/webservice1 COSH 30000 <- /mywebservices/webservice2 CSOH 30000 /mywebservices/webservice3 WEB3 30000

4. Transfer the file to the z/TPF system as follows: /etc/tpf_httpserver/url_program_map.conf

After the required configuration files are transferred to the z/TPF system, the z/TPF HTTP Server can be started using the ZINET START command.

4.2.3 z/TPF HTTP server message processing

z/TPF HTTP server support allows an HTTP request from a client to be received by one ECB and have the subsequent HTTP response sent to the client by another ECB. When information is needed from a remote system before the HTTP response can be sent, this asynchronous message flow allows the initial ECB to exit rather than suspend and wait.

Asynchronous message processing is enabled because z/TPF HTTP server support creates a unique connection token for each client HTTP request. When a client connection to a z/TPF HTTP server is established, an entry from the server connection table is allocated for that connection. When an HTTP request is received over that client connection, the HTTP request information is parsed and saved in a tpf_httpsvr_req structure. A unique token is then created for this HTTP request and saved in the client connection table entry.

After the HTTP request has been parsed, the z/TPF HTTP server URL-program mapping file is searched, looking for an entry that matches the URL specified in the HTTP request. The matching entry identifies the z/TPF application program that handles the HTTP request. That program is then invoked, passing a pointer to the tpf_httpsvr_req structure and the token (defined as a tpf_httpsvr_token structure) as input parameters.

The token identifies the HTTP request and its associated client connection. It can be passed as data to a subsequent ECB that will send the HTTP response to the client. The HTTP response is sent using tpf_httpSendResponse, which passes a pointer to the tpf_httpsvr_resp structure (which holds information needed to build the desired HTTP response) and the

Chapter 4. The z/TPF communications bindings 77 tpf_httpsvr_token structure (which identifies the associated client connection on which the HTTP response is sent).

For more information, see:  server connection table at http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztp fdf.doc_put.cur/gtpc1/ztpf_http_server_connection_table.html  z/TPF HTTP server URL-program mapping file at http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztp fdf.doc_put.cur/gtpc1/ztpf_url_mapping.html  tpf_httpSendResponse at http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztp fdf.doc_put.cur/gtpc2/cpp_tpf_httpsendresponse.html

4.2.4 z/TPF HTTP Server SOAP Message Processing

When using SOAP over HTTP, the target program in the z/TPF HTTP Server URL mapping file must be CSOH. CSOH will build a SOAP context (CTX) and will pass the SOAP CTX to the associated web service for this URL. The web service can then respond to the web service request using the tpf_soapSendResponse() function call passing the SOAP CTX structure. Alternatively, this ECB can save the SOAP CTX by issuing the tpf_soapSaveCtx() which returns a token identifying this SOAP CTX structure. The application can then pass this token to another ECB which will be responsible for sending the response.

When the ECB is invoked to send back the response, the SOAP CTX token must be passed to it. Using the token, the application can obtain the original SOAP CTX using the tpf_soapRetrieveCtx() function call. This allows the new ECB to send the response using the tpf_soapSendResponse passing the SOAP CTX returned by the tpf_soapRetrieveCtx() function.

Example 4-4 shows a web service request wrapper that will asynchronously call the web service application passing the required parameters. The asynchronous call means the web service will be executed in a new ECB and the ECB that processed the request can exit. In this example, the SOAP CTX is saved using the tpf_soapSaveCtx() function and saves the token referring to this SOAP CTX in system heap for use by the web service response wrapper.

Example 4-4 Web service wrapper request #include /* tpfSoapMsgCtx structure */ #include /* SOAP Consumer */ #define SYSH_OWNER "ASYNC HTTP WRAPPER" typedef struct { char token[ITOKENLEN]; // ITOKENLEN defined as 9 int ecbrout; } t_asyncHeapData; void ABCD(tpfSoapMsgCtx *ctx) {

t_soapHandle soapHandle = {0}; t_soapInv invokeParms = {0}; t_soapParms *parmData = NULL; tpfSoapMsgCtxTokenPtr ctxToken; t_asyncHeapData *sysHeapPtr = NULL; t_soapOpts *curTransport = NULL; // pt to current transport

78 z/TPF Application Modernization using Standard and Open Middleware int *transportCount = NULL; // count of transports obtained int transportSet = 0; int i, rc = 0; int number1 = 123, number2 = 456; int soapRspStatus, soapSendResponseRC; char async_operation[] = "asyncOperation"; // Initialize SOAP handle soapHandle = tpf_soapInitHandle("/asyncWebService"); if (soapHandle == TPF_SOAP_ERROR) { // . . . error processing soapRspStatus = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &soapRspStatus); exit(0); } // Change transport type to TRANSPORT_HTTP // Determine how many transports are defined for this service. rc = tpf_soapGetOpts(soapHandle, SOAP_NUM_TRANSPORT, 0, (void **) (char *) &transportCount); if (rc == TPF_SOAP_ERROR) { // . . . error processing tpf_soapEnd (soapHandle); soapRspStatus = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &soapRspStatus); exit(0); } // Loop through all of the transports looking for the requested one. for (i = 0; i < *transportCount; i++) { rc = tpf_soapGetOpts(soapHandle, SOAP_TRANSPORT, i, (void **) (char *) &curTransport); if (rc == TPF_SOAP_ERROR) { // . . . error processing free(transportCount); tpf_soapEnd (soapHandle); soapRspStatus = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &soapRspStatus); exit(0); } // If we found a match, call tpf_soapSetOpts to make it the active transport. if (curTransport->transportPtr->transportType == TRANSPORT_HTTP) { rc = tpf_soapSetOpts (soapHandle, SOAP_ACTIVE_INDEX, 0, &i); if (rc == TPF_SOAP_ERROR) { // . . . error processing free(transportCount); free(curTransport); tpf_soapEnd (soapHandle); soapRspStatus = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &soapRspStatus); exit(0); }

Chapter 4. The z/TPF communications bindings 79 // Indicate that the transport was successfully set. transportSet = 1; free(curTransport); break; } // end if we found a matching transport type // Free the curTransport storage obtained by the call to tpf_soapGetOpts. free (curTransport); } // end for loop through transports // Free the transportCount storage obtained by the call to tpf_soapGetOpts. free (transportCount); // If we didn't find the requested transport, then return an error message. if (!transportSet) { // . . . error processing tpf_soapEnd (soapHandle); soapRspStatus = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &soapRspStatus); exit(0); } // Get system heap to save data to be passed to the response program. sysHeapPtr = (t_asyncHeapData *)tpf_gsysc(1, "ASYNCW", SYSH_OWNER, 0); if (sysHeapPtr == NULL) { // . . . error processing tpf_soapEnd(soapHandle); soapRspStatus = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &soapRspStatus); exit(0); } // Save ctx in system heap prior to async invocation of web service ctxToken = tpf_soapSaveCtx (ctx); if (ctxToken == NULL) { // . . . error processing tpf_soapEnd(soapHandle); soapRspStatus = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &soapRspStatus); exit(0); } tpf_stpoc(TPF_STPOC_ON, NULL); // Save ctx token in system heap prior to async invocation of web service memcpy(&sysHeapPtr->token, ctxToken, ITOKENLEN-1); sysHeapPtr->ecbrout = ecbptr()->ebrout; keyrc_okey(); // Set up parameters for invokeService invokeParms.timeout = 5; invokeParms.timeoutInterval = SOAP_SECOND; invokeParms.messageExchangePattern = SOAP_CONSUMER_ASYNC; strcpy(invokeParms.operation, async_operation); memcpy(invokeParms.asyncProgram, "WXYZ", sizeof(invokeParms.asyncProgram)); memset(invokeParms.asyncParm, 0, sizeof(invokeParms.asyncParm)); memcpy(invokeParms.asyncParm, &sysHeapPtr, sizeof(invokeParms.asyncParm)); invokeParms.dataFormat = SOAP_PARMS; parmData = (t_soapParms*) calloc(1, (sizeof(t_soapParms) + (sizeof(t_soapParmValues) * 2))); parmData->numParms = 2;

80 z/TPF Application Modernization using Standard and Open Middleware parmData->parmArray[0].parmLength = sizeof(number1); parmData->parmArray[0].parmPtr = &number1; parmData->parmArray[1].parmLength = sizeof(number2); parmData->parmArray[1].parmPtr = &number2; invokeParms.data = parmData; // Invoke the web service. rc = tpf_soapInvokeService(soapHandle, &invokeParms, (void**) NULL); if (rc == TPF_SOAP_ERROR) { // . . . error processing tpf_rsysc(sysHeapPtr, 1, "ASYNCW"); tpf_soapEnd(soapHandle); soapRspStatus = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &soapRspStatus); exit(0); } exit(0); }

The web service response handler is invoked in another ECB. Using the SOAP CTX token saved in system heap, the web service can retrieve the SOAP CTX using the tpf_soapRetrieveCtx() function call and can then send the response passing the SOAP CTX structure for this SOAP service to the tpf_soapSendResponse() function call. For more information about the tpf_soapRetrieveCtx() function call, see: http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztpfdf .doc_put.cur/gtpc2/cpp_tpf_soapretrievectx.html

Example 4-5 shows a web service response wrapper that will retrieve the SOAP CTX token from system heap and issue the tpf_soapRetrieveCtx(). Using the SOAP CTX returned the response is sent using the tpf_soapSendResponse() function call.

Example 4-5 Web service wrapper response #include /* soapMsg, commsBinding */ #include #include /* XML APIs */ typedef struct { char token[ITOKENLEN]; // ITOKENLEN defined at 9 int ecbrout; } t_asyncHeapData; void QWSR(t_soapAsyncParms *asyncPtr) { tpfSoapMsgCtxTokenPtr ctxToken = NULL; tpfSoapMsgCtx *ctx = NULL; t_soapHandle soapHandle = {0}; t_asyncHeapData *sysHeapPtr = NULL; char *returnMsg = "asyncWebServiceResponse"; int retCode = 0; int rc = 0; int soapSendResponseRC = 0; int statusReturnCode = SendReply; /***************************************************************/ /* Retrieve ctx data that was saved in system heap prior to */ /* sending the Web Service request asynchronously. */ /***************************************************************/ soapHandle = asyncPtr->soapHandle;

Chapter 4. The z/TPF communications bindings 81 sysHeapPtr = asyncPtr->asyncParm; ctxToken = (char *)sysHeapPtr->token; ecbptr()->ebrout = sysHeapPtr->ecbrout; // retrieve previously saved SOAP ctx retCode = tpf_soapRetrieveCtx(&ctx, ctxToken); if (retCode) { // . . . error processing tpf_soapEnd(asyncPtr->soapHandle); statusReturnCode = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &statusReturnCode); exit(0); } if (asyncPtr->soapReturnCode == TPF_SOAP_ERROR) { // . . . error processing statusReturnCode = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &statusReturnCode); tpf_soapEnd(soapHandle); exit(0); } /***************************************************************/ /* Create Response Message */ /***************************************************************/ retCode = tpf_xml_initialize_handle (&(ctx->response_handle.xml_handle), NO_PARSER, NULL); if (retCode != 0) { // . . . error processing tpf_soapEnd(soapHandle); statusReturnCode = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &statusReturnCode); exit(0); } /* create an XML structure to be used for the response */ retCode = tpf_xml_createXMLstructure(ctx->response_handle.xml_handle, "1.0", 819, "ISO-8859-1", STANDALONE_YES, 2, "Web Service Wrapper Sample", returnMsg); if (retCode != 0) { // . . . error processing tpf_soapEnd(soapHandle); statusReturnCode = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &statusReturnCode); exit(0); } /* add the first required element of the SOAP response - Envelope */ retCode = tpf_xml_appendElement(ctx->response_handle.xml_handle, NULL, "Envelope", NULL, "SOAP-ENV",

82 z/TPF Application Modernization using Standard and Open Middleware "http://schemas.xmlsoap.org/soap/envelope/", 0); /* if error, return a SOAP fault response */ if (retCode != 0) { // . . . error processing tpf_soapEnd(soapHandle); statusReturnCode = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &statusReturnCode); exit(0); } /* add the next required element of the SOAP response - Body */ retCode = tpf_xml_appendElement(ctx->response_handle.xml_handle, "Envelope", "Body", NULL, "SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", 0); if (retCode != 0) { // . . . error processing tpf_soapEnd(soapHandle); statusReturnCode = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &statusReturnCode); exit(0); } /* add the element for the result of the calculator function */ retCode = tpf_xml_appendElement(ctx->response_handle.xml_handle, "Body", "asyncResponse", NULL, "ns1", "http://www.mycompany.com/sample/calculator", 0); if (retCode != 0) { // . . . error processing tpf_soapEnd(soapHandle); statusReturnCode = SendErrorReplyReceiver; soapSendResponseRC = tpf_soapSendResponse(ctx, &statusReturnCode); exit(0); } tpf_soapEnd(soapHandle); /* Good response */ ctx->response_handle.type = TPF_HDL_RESP; tpf_soapSendResponseRC = tpf_soapSendResponse(ctx, &statusReturnCode); // . . .evaluate soapSendResponseRC exit(0); }

4.3 SOAP over WebSphere MQ for z/TPF

The IBM WebSphere MQ product allows applications to communicate with each other on the same or different platforms asynchronously. The following topic provides a brief overview of z/TPF WebSphere MQ.

Chapter 4. The z/TPF communications bindings 83 4.3.1 z/TPF WebSphere MQ overview

To allow z/TPF systems to communicate among themselves and with other platforms asynchronously, the z/TPF system is supported as an WebSphere MQ client, server, and local queue manager:  A z/TPF WebSphere MQ client provides applications with the ability to issue WebSphere MQ application programming interfaces (APIs) even though no physical queues exist on the system. The WebSphere MQ client allows the application to connect to a server (on a z/TPF system or other platform) over a connection channel named CLNTCONN. (The channel is sometimes called a message queue interface (MQI) channel because the WebSphere MQ APIs are sent over them.) The APIs get sent over the channels to a remote WebSphere MQ server, which processes the API on behalf of the client.  A z/TPF WebSphere MQ server is a queue manager that can accept MQI requests from WebSphere MQ clients. The server has a corresponding server connection channel named SVRCONN to which the client channel connects. APIs are processed for the client by the server.  A z/TPF WebSphere MQ local queue manager is a system that physically manages queues and can accept and make MQI calls. It can also connect to other remote queue managers using channels. When applications put messages on local queues, message delivery is guaranteed by the local queue manager. Messages remain on the local queue until an application or channel removes the message. Applications can send messages to the local queue manager or use a communication link to send a message to a remote queue manager.

Applications residing on the z/TPF system can perform any of the following functions:  Access a server on a remote queue manager by using the WebSphere MQ client interface of the system on which they reside.  Access local queues by using the local queue manager.

As a whole, you can use your z/TPF system as a WebSphere MQ server to accept connections from clients residing on another z/TPF system or another platform, or you can use your system as a WebSphere MQ local queue manager to send and receive messages from other remote queue managers.

z/TPF WebSphere MQ support allows the z/TPF system to participate in the following two types of communication:  Client to server communication As shown in Figure 4-8 on page 85, a WebSphere MQ client communicates to a server, which contains the WebSphere MQ API (MQI) and can complete requests on behalf of the client and the application working with that client. The client uses the CLNTCONN channel to send a request over Transmission Control Protocol/Internet Protocol (TCP/IP) or LU 6.2. This request is an individual API that is sent serially to the server. The request is received by the server using the SVRCONN channel and is followed by a response which tells the client that the API request was processed. The client is now able to send the next API request. A server can receive messages from many clients through the SVRCONN channel.

Communication methods: When the z/TPF system is your client, you can use either TCP/IP or LU 6.2 as your communication method. When z/TPF is your server, communication must be limited to TCP/IP.

84 z/TPF Application Modernization using Standard and Open Middleware System C System B with MQSeries Server Support

Local Queue Manager Application SVRCONN MQSeries Transmission Channel Server Queue TCP/IP

CLNTCONN Message Queue Channel MQGET Interface (MQI) MQPUT Application Client Queue

Figure 4-8 z/TPF WebSphere MQ client to server communication

 Queue manager to queue manager communication As shown in Figure 4-9, when one queue manager has to communicate to a second queue manager, the communication is done using receiver (RCVR) and sender (SDR) channels. Together, a pair of SDR and RCVR channels represent a single socket connection, and only a single instance of this can exist in the z/TPF system. If there is already an active receiver channel by the name of CHL1, no other receiver channels named CHL1 can be started. Messages are sent in batches from the transmission queue using the SDR channel over TPC/IP. The messages are received by a second system using the RCVR channel and are placed on the application queue. The RCVR channel then sends an acknowledgment to the SDR channel over the same socket once it has received all of the messages.

System A System B

Application Application

TCP/IP Local Queue Local Queue Manager Manager RCVR SDR Application Channel Channel Transmission Queue Queue

SDR RCVR Transmission Channel Channel Application Queue Queue

Figure 4-9 z/TPF WebSphere MQ queue manager to queue manager communication

Chapter 4. The z/TPF communications bindings 85 4.3.2 The SOAP communications binding for WebSphere MQ

Figure 4-10 shows what part of the protocol stack is managed by what software component when using WebSphere MQ for a transport layer for SOAP messages.

As shown in Figure 4-10, the z/TPF Internet daemon handles up to part of the TCP protocol layer. After that WebSphere MQ for z/TPF takes over. WebSphere MQ uses the AOA2 Internet daemon model, so the Internet daemon calls the socket, bind, listen, and activate_on_accept APIs. WebSphere MQ will issue activate_on_receipt and once data is received, it will read from and write to sockets.

Application Data Application

SOAP Application XML Handler

SOAP Handler SOAP CSO8

MQ WebSphere MQ

TCP

Internet Daemon IP

Figure 4-10 Software and protocol components for SOAP using WebSphere MQ for z/TPF

This section provides an example of the communications binding on top of WebSphere MQ. The communications binding—program CSO8 in this example—is called when a message arrives on a WebSphere MQ local queue—called TPF.SOAP.REQUESTS—that has been designated to handle SOAP requests. In the following sample code, the queue was defined with the “trigger every” attribute. As a result, every time a message arrives on the queue, the z/TPF system creates a new ECB and triggers a program in the process object associated with the queue.

For testing purposes, it is possible to have both the client and the server on the same z/TPF system. When testing is done in this manner, no external TCP/IP connectivity is required. TCP/IP uses local sockets in this case. If, however, the client and server are going to reside on separate z/TPF processors and in different loosely-coupled complexes, then it is necessary to have TCP/IP connectivity. This first situation is shown in Example 4-6 on page 87, and the second one in Example 4-7 on page 88 and Example 4-8 on page 89.

Use the following steps to set up an environment for SOAP over WebSphere MQ in a single processor z/TPF configuration. The accompanying example of this is shown in Example 4-6 on page 87: 1. Define a WebSphere MQ queue manager (TPF.QMGR in the example). 2. Define a local queue (TPF.SOAP.REQUESTS) to be used to receive SOAP messages on with the trigger every attribute.

86 z/TPF Application Modernization using Standard and Open Middleware 3. Define a WebSphere MQ process called SOAP to create a new ECB in program CSO8 when invoked. 4. Define a transmit queue (TPF.SOAP.RESPONSES) to be used to send the SOAP response messages. 5. Start the WebSphere MQ queue manager.

Example 4-6 Setting up an environment for SOAP over WebSphere MQ in a single processor z/TPF configuration ZMQSC DEF QMGR-TPF.QMGR CSMP0097I 11.53.56 CPU-B SS-BSS SSU-HPN IS-01 MQSC0001I 11.53.56 DEFINE QUEUE MANAGER SUCCESSFUL+

ZMQSC DEFINE QL-TPF.SOAP.REQUESTS PROCESS-SOAP TRIGTYPE-EVERY TRIGGER CSMP0097I 12.57.13 CPU-B SS-BSS SSU-HPN IS-01 MQSC0069I 12.57.13 LOCAL QUEUE TPF.SOAP.REQUESTS DEFINED+

ZMQSC DEFINE PROCESS-SOAP APPLICID-CSO8 CSMP0097I 13.39.07 CPU-B SS-BSS SSU-HPN IS-01 MQSC0700I 13.39.07 PROCESS-SOAP DEFINITION COMPLETED SUCCESSFULLY +

ZMQSC DEFINE QL-TPF.SOAP.RESPONSES CSMP0097I 12.57.44 CPU-B SS-BSS SSU-HPN IS-01 MQSC0069I 12.57.44 LOCAL QUEUE TPF.SOAP.RESPONSES DEFINED+

ZMQSC START QMGR CSMP0097I 12.57.56 CPU-B SS-BSS SSU-HPN IS-01 MQSC0019I 12.57.56 START QUEUE MANAGER SUCCESSFUL+ CSMP0097I 12.57.57 CPU-B SS-BSS SSU-HPN IS-01 INET0050I 12.57.57 MQSIS NOW ACCEPTING CONNECTIONS ON IP - ANY PORT - 01414 PID - 60710016+

To set up an environment for SOAP over WebSphere MQ in a multiple processor z/TPF configuration, the following steps have to be completed for the server side. The accompanying example of this is shown in Example 4-7 on page 88: 1. Define a WebSphere MQ queue manager (TPF.QMGR.SERVER). 2. Define a local queue (TPF.SOAP.REQUESTS) to be used to receive SOAP messages on with the trigger every attribute. 3. Define a WebSphere MQ process called SOAP to create a new ECB in program CSO8 when invoked. 4. Define a transmit queue (TPF.SOAP.SERVER.XMITQ) to be used to send the SOAP response messages. 5. Define a local definition of a remote queue (TPF.SOAP.RESPONSES) to be used to correspond to the correct transmit queue through which the SOAP response messages will be sent. 6. Define the receiver channel (TPF.CLIENT.TO.SERVER) to be used to receive SOAP requests from the client. 7. Define a sender channel (TPF.SERVER.TO.CLIENT) to be used to send the SOAP response back to the client. 8. Start the WebSphere MQ queue manager. 9. Start the channels.

Chapter 4. The z/TPF communications bindings 87 Example 4-7 Setting up the server side for SOAP over WebSphere MQ in a multiple processor z/TPF configuration ZMQSC DEFINE QMGR-TPF.QMGR.SERVER CSMP0097I 11.53.56 CPU-B SS-BSS SSU-HPN IS-01 MQSC0001I 11.53.56 DEFINE QUEUE MANAGER SUCCESSFUL+

ZMQSC DEFINE QL-TPF.SOAP.REQUESTS PROCESS-SOAP TRIGTYPE-EVERY TRIGGER CSMP0097I 12.57.44 CPU-B SS-BSS SSU-HPN IS-01 MQSC0069I 12.57.44 LOCAL QUEUE TPF.SOAP.RESPONSES DEFINED+

ZMQSC DEFINE PROCESS-SOAP APPLICID-CSO8 CSMP0097I 13.39.07 CPU-B SS-BSS SSU-HPN IS-01 MQSC0700I 13.39.07 PROCESS-SOAP2 DEFINITION COMPLETED SUCCESSFULLY +

ZMQSC DEFINE QL-TPF.SOAP.SERVER.XMITQ USAGE-XMITQ CSMP0097I 13.28.37 CPU-B SS-BSS SSU-HPN IS-01 MQSC0069I 13.28.37 LOCAL QUEUE TPF.SOAP.SERVER.XMITQ DEFINED+

ZMQSC DEFINE QR-TPF.SOAP.RESPONSES RQMNAME-TPF.QMGR.CLIENT RNAME-TPF.SOAP.RESPONSES XMITQ-TPF.SOAP.SERVER.XMITQ CSMP0097I 13.41.29 CPU-B SS-BSS SSU-HPN IS-01 MQSC0145I 13.41.29 REMOTE QUEUE TPF.SOAP.RESPONSES DEFINED+

ZMQSC DEFINE CHL-TPF.CLIENT.TO.SERVER CHLTYPE-RCVR CSMP0097I 13.32.17 CPU-B SS-BSS SSU-HPN IS-01 MQSC0004I 13.32.17 DEFINE CHANNEL SUCCESSFUL+

ZMQSC DEFINE CHL-TPF.SERVER.TO.CLIENT CHLTYPE-SDR CONNAME-client_ipaddress XMITQ-TPF.SOAP.SERVER.XMITQ CSMP0097I 13.32.17 CPU-B SS-BSS SSU-HPN IS-01 MQSC0004I 13.32.17 DEFINE CHANNEL SUCCESSFUL+

ZMQSC START QMGR CSMP0097I 13.33.45 CPU-B SS-BSS SSU-HPN IS-01 MQSC0019I 13.33.45 START QUEUE MANAGER SUCCESSFUL+ CSMP0097I 13.33.45 CPU-B SS-BSS SSU-HPN IS-01 INET0050I 13.33.45 MQS IS NOW ACCEPTING CONNECTIONS ON IP - ANY PORT - 01414 PID - 61180031+

ZMQSC START CHL-ALL CSMP0097I 13.34.31 CPU-B SS-BSS SSU-HPN IS-01 MQSC0230I 13.34.31 ALL CHANNELS STARTED+

Use the following steps to setup of the client side in an environment for SOAP over WebSphere MQ in a multiple processor z/TPF configuration. The accompanying example of this is shown in Example 4-8 on page 89: 1. Define a WebSphere MQ queue manager (TPF.QMGR.CLIENT). 2. Define a local queue (TPF.SOAP.RESPONSES) to be used to hold SOAP response messages on with the trigger every attribute. 3. Define a transmit queue (TPF.SOAP.CLIENT.XMITQ) to be used to send the SOAP request.

88 z/TPF Application Modernization using Standard and Open Middleware 4. Define a local definition of a remote queue (TPF.SOAP.REQUESTS), to be used to correspond to the correct transmit queue through which the SOAP request messages will be sent. 5. Define a receiver channel (TPF.SERVER.TO.CLIENT) to be used to receive SOAP requests from the server. 6. Define a sender channel (TPF.CLIENT.TO.SERVER) to be used to send the SOAP requests to the server. 7. Start the WebSphere MQ queue manager. 8. Start the channels.

Example 4-8 Setting up the client side for SOAP over WebSphere MQ in a multiple processor z/TPF configuration ZMQSC DEFINE QMGR-TPF.QMGR.CLIENT CSMP0097I 11.53.56 CPU-B SS-BSS SSU-HPN IS-01 MQSC0001I 11.53.56 DEFINE QUEUE MANAGER SUCCESSFUL+

ZMQSC DEFINE QL-TPF.SOAP.RESPONSES CSMP0097I 12.57.44 CPU-B SS-BSS SSU-HPN IS-01 MQSC0069I 12.57.44 LOCAL QUEUE TPF.SOAP.RESPONSES DEFINED+

ZMQSC DEFINE QL-TPF.SOAP.CLIENT.XMITQ USAGE-XMITQ CSMP0097I 13.28.37 CPU-B SS-BSS SSU-HPN IS-01 MQSC0069I 13.28.37 LOCAL QUEUE TPF.SOAP.CLIENT.XMITQ DEFINED+

ZMQSC DEFINE QR-TPF.SOAP.REQUESTS RQMNAME-TPF.QMGR.SERVER RNAME-TPF.SOAP.REQUESTS XMITQ-TPF.SOAP.CLIENT.XMITQ CSMP0097I 13.41.29 CPU-B SS-BSS SSU-HPN IS-01 MQSC0145I 13.41.29 REMOTE QUEUE TPF.SOAP.REQUESTS DEFINED+

ZMQSC DEFINE CHL-TPF.SERVER.TO.CLIENT CHLTYPE-RCVR CSMP0097I 13.30.57 CPU-B SS-BSS SSU-HPN IS-01 MQSC0004I 13.30.57 DEFINE CHANNEL SUCCESSFUL+

ZMQSC DEFINE CHL-TPF.CLIENT.TO.SERVER CHLTYPE-SDR CONNAME-9.57.13.211 XMITQ-TPF.SOAP.CLIENT.XMITQ CSMP0097I 13.32.17 CPU-B SS-BSS SSU-HPN IS-01 MQSC0004I 13.32.17 DEFINE CHANNEL SUCCESSFUL+

ZMQSC START QMGR CSMP0097I 13.33.45 CPU-B SS-BSS SSU-HPN IS-01 MQSC0019I 13.33.45 START QUEUE MANAGER SUCCESSFUL+ CSMP0097I 13.33.45 CPU-B SS-BSS SSU-HPN IS-01 INET0050I 13.33.45 MQSIS NOW ACCEPTING CONNECTIONS ON IP - ANY PORT - 01414 PID - 61180031+

ZMQSC START CHL-ALL SMP0097I 13.34.31 CPU-B SS-BSS SSU-HPN IS-01 MQSC0230I 13.34.31 ALL CHANNELS STARTED+

The sample code receives the SOAP request from an indicated MQ queue, and calls tpf_soap_handler() to process the message. In order to identify the service to be activated by TPF's SOAP server support, the applRoutingInfo field in the commsBinding structure must be filled in with the service's URI.

Chapter 4. The z/TPF communications bindings 89 This sample assumes that the name of the service to be activated by TPF's SOAP server support is designated by the following naming scheme: queue_name@queue_mgr_name, where queue_name is the name of the MQ queue that the request was received on, and queue_mgr_name is the name of the local MQ queue manager that the request was received at. Given the queue naming scheme above, this would lead to a service name of [email protected] in the single processor example — or in the multiple processor example, [email protected].

This is only one example of how the name of the service to be invoked can be determined. Other potential schemes might include these:  Translate a particular local queue name to a known service (for example, all messages received on queue SERVICEQ1 are destined to activate service /creditauth, whereas messages received on SERVICEQ2 activate service /balancing, and so on.  Send all inbound SOAP requests to a single queue; the routing information for the correct service to invoke is contained in the MQ message descriptor (MQMD) or is actually part of the MQ message itself.

The sample code can be modified to conform to the routing scheme that is selected by the user. Furthermore, whatever naming scheme is used, the tpf_soap_appl_handler() user exit must be updated to properly handle the routing of the service request to the correct application based on the service name that is passed. Lastly, this sample code assumes that the SOAP reply message to be returned to the client application is to be sent using the queue specified in the ReplyToQ and ReplyToQMgr field of the MQMD of the original SOAP request.

Therefore, users must also define a remote queue on their TPF system to handle the sending of these response messages. Follow the MQ definition procedure described in TPF Operations to define remote queue, transmission queue, and MQ channel that are associated with the SOAP messages.

Example 4-9 shows the actual sample code in program cso8.c.

Example 4-9 Sample WebSphere MQ for z/TPF communications binding 1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include

8 soapMsg* inputMsg; 9 soapMsg* outputMsg;

10 commsBinding* binding; 11 void CSO8() { 12 MQTMC2* triggerData; 13 char QMName[MQ_Q_MGR_NAME_LENGTH]; 14 int retVal = 0; 15 MQOD od = {MQOD_DEFAULT}; /*Object descriptor*/ 16 MQMDmd = {MQMD_DEFAULT}; /*Message descriptor*/ 17 MQPMO pmo= {MQPMO_DEFAULT}; /*PUT options*/ 15 MQOD od = {MQOD_DEFAULT}; /*Object descriptor*/ 16 MQMDmd = {MQMD_DEFAULT}; /*Message descriptor*/ 17 MQPMO pmo= {MQPMO_DEFAULT}; /*PUT options*/ 18 MQHOBJHobjRQ; /*object handle of Remote Q*/

90 z/TPF Application Modernization using Standard and Open Middleware 19 MQHOBJHobjLQ; /*object handle of LocalQ*/ 20 MQHCONN Hconn; /*connection handle */ 21 MQLONG msgRead; /* Number of bytes read*/ 22 MQLONG O_options; /*MQOPEN options*/ 23 MQLONG C_options = 0; /*MQCLOSE options*/ 24 MQLONG CompCode; /*completion code*/ 25 MQLONG BufferLength = 4095; /*Buffer Length*/ 26 MQGMO gmo = {MQGMO_DEFAULT}; /*Get Msg Options */ 27 char RQMName[MQ_Q_MGR_NAME_LENGTH]; 28 char RQName[MQ_Q_NAME_LENGTH]; 29 MQLONG Reason; /* reason code */ 30 MQLONG CReason; /*reason code MQCONN */ 31 MQLONG buflen; /*buffer length */ 32 chr* Buffer; 33 char MQ_URI[MQ_Q_MGR_NAME_LENGTH + MQ_Q_NAME_LENGTH + 1] = {0}; 34 char localQ[MQ_Q_NAME_LENGTH]; 35 char* loc; /*strchr location*/ 36 inputMsg = calloc(1,sizeof(soapMsg)); 37 outputMsg = calloc(1,sizeof(soapMsg)); 38 binding = calloc(1,sizeof(commsBinding)); 39 if(inputMsg == NULL || outputMsg == NULL || binding == NULL) { 40 exit(-1); 41 } 42 triggerData =(MQTMC2 *) ecbptr()->ce1cr0; 43 if(triggerData == NULL) { 44 exit(-1); 45 } 46 memcpy(localQ, triggerData->QName, MQ_Q_NAME_LENGTH); 47 QMName[0] = 0; 48 MQCONN(QMName, &Hconn, &CompCode, &CReason); 49 if(CompCode == MQCC_FAILED) 50 exit(CReason); 51 memcpy(od.ObjectName, localQ, MQ_Q_NAME_LENGTH); 52 O_options = MQOO_INPUT_AS_Q_DEF; 53 MQOPEN(Hconn, &od, O_options, &HobjLQ, &CompCode, &Reason ); 54 if(CompCode == MQCC_FAILED) 55 exit(Reason); 56 Buffer =(char*) malloc(BufferLength); 57 MQGET(Hconn, HobjLQ, &md, &gmo, BufferLength, (MQBYTE*)Buffer, 58 &msgRead, &CompCode, &Reason); 59 if(Reason == MQRC_NO_MSG_AVAILABLE) 60 exit(Reason); 61 if(msgRead < 0) 62 exit(-1); 63 inputMsg ->version = SOAP1_2; 64 inputMsg ->msgLength = msgRead; 65 inputMsg ->XMLptr = Buffer; 66 inputMsg ->clientEncoding = md.Encoding; 67 memcpy(RQMName, md.ReplyToQMgr, MQ_Q_MGR_NAME_LENGTH); 68 memcpy(RQName, md.ReplyToQ,MQ_Q_NAME_LENGTH); 69 binding->bindingType = MQ; 70 strncpy(MQ_URI , triggerData->QName, MQ_Q_NAME_LENGTH); 71 loc = strchr(MQ_URI,' '); 72 if(loc) { 73 *loc = '\0';

Chapter 4. The z/TPF communications bindings 91 74 } 75 strncat(MQ_URI, "@", 1); 76 strncat(MQ_URI, triggerData->QMgrName, MQ_Q_MGR_NAME_LENGTH); 77 loc = strchr(MQ_URI,' '); 78 if(loc) { 79 *loc = '\0'; 80 } 81 binding->applRoutingInfo = MQ_URI; 82 retVal = tpf_soap_handler(inputMsg, outputMsg, binding); 83 if(outputMsg->XMLptr != NULL) { 84 memcpy(od.ObjectName, RQName, MQ_Q_NAME_LENGTH); 85 memcpy(od.ObjectQMgrName, RQMName, MQ_Q_MGR_NAME_LENGTH); 86 O_options = MQOO_OUTPUT; 87 MQOPEN(Hconn, &od, O_options, &HobjRQ, &CompCode, &Reason ); 88 if(CompCode == MQCC_FAILED) 89 exit(Reason); 90 buflen = outputMsg->msgLength; 91 MQPUT(Hconn, HobjRQ, &md, &pmo, buflen, outputMsg->XMLptr, 92 &CompCode, &Reason); 93 if(CompCode == MQCC_FAILED) 94 exit(Reason); 95 free(outputMsg->XMLptr); 96 MQCLOSE(Hconn, &HobjRQ, C_options, &CompCode, &Reason); 97 } 98 C_options = 0; 99 MQCLOSE(Hconn, &HobjLQ, C_options, &CompCode, &Reason); 100 MQDISC(&Hconn, &CompCode, &Reason); 101 }

In Example 4-9 on page 90:  Lines 8-10 contain the definitions for the variables that are used in the z/TPF SOAP handler API.  Lines 36-41 set up storage areas for the SOAP input message structure, the SOAP output message structure, and the communications binding structure.  Lines 42-45 retrieve the trigger data structure.  Lines 48-50 connect to the local queue manager.  Lines 51-55 open the queue to receive the SOAP request.  Lines 56-62 retrieve the request message from the queue into a heap storage area.  Lines 63-66 set up values in the input soapMsg data structure.  Lines 67-81 set up values in the commsBinding data structure. This includes building the application routing information which as described earlier uses a scheme that looks like this: queue_name@queue_mgr_name.  Line 82 calls the z/TPF SOAP handler.  Lines 84-89 open the local queue to receive the SOAP responses.  Lines 90-94 put the SOAP response onto the reply queue.  Line 96 closes the local queue to receive the SOAP responses.  Line 99 closes the local queue that the SOAP request was received from.  Line 100 disconnects from the local queue manager.

92 z/TPF Application Modernization using Standard and Open Middleware 4.3.3 WebSphere MQ over SSL

z/TPF WebSphere MQ supports SSL on sender channels, receiver channels, and SRVRCONN channels. To establish a secure WebSphere MQ session using SSL, you must create one or more WebSphere MQ configuration files for SSL and place them in the /etc/ssl/mq/ directory on the z/TPF system. There are two kinds of z/TPF WebSphere MQ configuration files for SSL:  The WebSphere MQ queue manager configuration file for SSL generally applies to all of the channels unless a WebSphere MQ channel-specific configuration file for SSL is defined. The WebSphere MQ queue manager configuration file for SSL must use the following naming convention: /etc/ssl/mq/mq.conf.  The WebSphere MQ channel-specific configuration file for SSL applies to individual channels. Specify the channel-specific files to override the WebSphere MQ queue manager configuration file for SSL by entering the ZMQSC DEFINE CHL or ZMQSC ALTER CHL command with the SSLCONF parameter specified. The SSLCONF parameter takes the base name of the file and adds the /etc/ssl/mq/ directory and the.conf extension to the path name.

Example 4-10 shows a sample z/TPF WebSphere MQ channel-specific configuration file for SSL:

Example 4-10 z/TPF WebSphere MQ channel configuration file for SSL usessl=yes version=tlsv1 cipher=AES128-SHA verifypeer=yes cainfo=/certs/mqsslca.arm certificate=/certs/tpfcert.pem certtype=pem key=/certs/key.pem keytype=pem

Chapter 4. The z/TPF communications bindings 93 94 z/TPF Application Modernization using Standard and Open Middleware 5

Chapter 5. XML on z/TPF

XML is a central component of service-oriented architecture (SOA) and web services. This chapter discusses the various aspects of XML as it pertains to z/TPF and introduces the various APIs available on z/TPF.

This chapter contains the following topics:  5.1, “B2B XML scanner” on page 96  5.2, “z/TPF XML APIs” on page 97  5.3, “XML4C” on page 105  5.4, “z/TPF XML APIs versus XML4C” on page 106

© Copyright IBM Corp. 2013. All rights reserved. 95 5.1 B2B XML scanner

The B2B XML scanner is an internal component that is used to parse an incoming SOAP message and create a tree-like structure, called infoNodes (the XML structure). There is also an API, tpf_xml_parseDocument(), which can be used to parse an XML document manually and generate the infoNodes structure.

Programmers can use the z/TPF XML APIs to work with XML documents. Besides being easier to work with than working directly with the infoNodes structures, this also prevents any possible future incompatibilities in the event that the infoNodes structures change. The z/TPF XML APIs are described later in this chapter.

5.1.1 The infoNodes structure

When the B2B XML scanner processes an incoming SOAP message, it creates a tree-like structure, which is called the infoNodes structure. The structure consists of five pointers that point to arrays of pointers to other structures, as shown in Table 5-1. Refer to the cbnode.h header file to see a detailed layout of each structure and the accessible fields within each structure.

Table 5-1 InfoNodes structure pointers Pointer name Structure purpose

attribute_ptr Pointer to array of attributeNode structure pointers. Each structure contains information about an attribute in the XML document, except namespace attributes.

content_ptr Pointer to array of contentNode structure pointers. Each structure represents an element content or attribute value.

docnode_ptr Pointer to the docNode structure, containing information about the document itself. There is only one docNode structure for each XML document.

element_ptr Pointer to array of elementNode structure pointers. Each structure represents the information about one element in the XML document,

namespace_ptr Pointer to array of namespaceNode structure pointers. Each structure containing information about one namespace of the XML document.

Each array contains pointers to structures of its type and the number of structure pointers in the array depends on the number of occurrences of the type of data it reflects. For instance, the elementNode array contains as many elementNode structure pointers as there are elements in the XML document. The same is valid for the other arrays. This means you can traverse the attributeNode array and list all of the attributes that occur in the XML document, regardless of which element they belong to.

To create a relationship between the various types of node records, there are index pointers within certain structures. The elementNode structure, for instance, contains an attributePtr field that points to the first attribute structure for that element, if any. The field is not a real pointer in the sense of a C language pointer, although it is a mere index into the attributeNode structure pointer array. The numAttributes field of the elementNode structure shows how many attributeNode structures belong to this element and they are in sequence from the first index onward.

The character pointers in the various node structures are null terminated strings.

Example 5-1 shows the corresponding infoNodes structures to extract the relevant data.

96 z/TPF Application Modernization using Standard and Open Middleware Example 5-1 Sample XML document John Smith Sales

Examining the docNode structure contents shows valuable information, such as the character encoding of the document, the number of elements in the document, pointer to the infoNodes structure, and so on. There is only one docNode structure for each XML document.

The elementNode array contains pointers to elementNode structures, each representing an element in the XML document. In Example 5-1, there are six elements in total: SOAP-ENV:Envelope, SOAP-ENV:Body, m:MyApplication, m:employee, m:name, and m:department. The element_ptr field of the infoNodes structure points to the first elementNode structure pointer in the array, which is SOAP-ENV:Envelope.

For more details about each node structure and for additional examples, refer to the z/TPF product Information Center. There are also various TPF Users Group presentations that can be accessed through the IBM TPF website: http://www.ibm.com/tpf

5.2 z/TPF XML APIs

To make it easier for an application programmer to work with incoming XML data, the z/TPF XML APIs handle all the heavy lifting and manual traversing of the infoNodes structure created by the B2B XML scanner and provides a clean interface to work with the XML document. They also provide assistance in creating XML response messages.

The implementation of the z/TPF XML APIs was done in such a way that at a future date it is possible to use a different XML scanner than the B2B XML scanner, without having to change the applications.

Besides processing SOAP input messages, the z/TPF XML APIs can also be used on any other XML document by passing the memory reference of an XML document to the respective z/TPF XML API functions.

5.2.1 Processing XML documents

There are two ways in which XML documents can be processed with the z/TPF XML APIs.

The first approach is for incoming SOAP messages where the XML document is being passed through the B2B XML scanner by the SOAP communications binding and the resulting infoNodes structure is passed on to the application. In this case, the z/TPF XML APIs are first initialized with the infoNodes structure, and then the other API functions can be

Chapter 5. XML on z/TPF 97 used to process the XML document content. The code fragment in Example 5-2 shows the overall approach.

Example 5-2 Processing a SOAP XML message XMLHandle apiHandle; int retCode

// initialize the API retCode = tpf_xml_initialize_handle(&apiHandle, B2B_XML_SCANNER, infoNodePtr);

// Use the appropriate tpf_xml_get* and tpf_xml_position* functions // to access the SOAP message content

// free up handle to release temporary storage tpf_xml_terminate_handle(&apiHandle);

Alternatively, the z/TPF XML APIs can be used to process XML documents that have not been forwarded and pre-processed by the SOAP handler. In this case, the entire XML document must reside in memory so that it can be referenced when initializing the z/TPF XMP APIs. When the APIs are properly initialized and the XML document has been parsed, the appropriate z/TPF XML API functions can be used to process the XML document content. The code fragment in Example 5-3 outlines the basic steps involved in this approach.

Example 5-3 Processing a stand-alone XML document XMLHandle apiHandle; int parseError; int retCode;

// initialize the API retCode = tpf_xml_initialize_handle(&apiHandle, B2B_XML_SCANNER, NULL);

// parse an in-memory XML document retCode = tpf_xml_parseDocument(apiHandle, xmlDocPtr, TPF_CCSID_IBM1047, strlen(xmlDocPtr), &parseError, 0);

// Use the appropriate tpf_xml_get* and tpf_xml_position* functions // to access the SOAP message content

// free up handle to release temporary storage tpf_xml_terminate_handle(&apiHandle);

When the z/TPF XML APIs are set up and ready for use, you can use any of the tpf_xml_get* and tpf_xml_position* functions to retrieve individual items from the XML document.

These functions are:  tpf_xml_getElementsByTagName()  tpf_xml_getXMLDocumentDeclarations() tpf_xml_getNextElement()  tpf_xml_getFirstElementByTagName()  tpf_xml_getNextElementByTagName()  tpf_xml_positionToRoot()  tpf_xml_positionAfterElementTagName()  tpf_xml_positionBeforeElementTagName()  tpf_xml_positionAfterNextElementTagName()

98 z/TPF Application Modernization using Standard and Open Middleware  tpf_xml_positionBeforeNextElementTagName()

Example 5-4 uses the previous SOAP message example (Example 5-1 on page 97). The z/TPF XML APIs are used to retrieve data from the XML document.

Example 5-4 Example of using z/TPF XML APIs char name[128]; char gender[128]; XMLHandle apiHandle; XMLNodesArray* xmlPtr; int retCode // initialize the API retCode = tpf_xml_initialize_handle(&apiHandle, B2B_XML_SCANNER, infoNodePtr); xmlPtr = tpf_xml_getFirstElementByTagName(apiHandle, TYPE_TEXT, “name”); for(int i=0; i < xmlPtr->nodesArraySize, i++) { if(xmlPtr->nodesArray[i].flags == ATTRIBUTE_CONTENT) { strcpy(gender, xmlPtr->nodesArray[i].nodeValueStr); } else { strcpy(name, xmlPtr->nodesArray[i].nodeValueStr); } } // free up handle to release temporary storage tpf_xml_terminate_handle(&apiHandle);

Tip: When you process an incoming XML document with the z/TPF XML APIs, you can also modify the received XML document structure and content before passing it on to another application, for instance. The following section describes some of the API functions that can be used to add or modify the content.

5.2.2 Creating XML documents

The z/TPF XML APIs also allow the creation of XML documents. An initial call to the respective API creates the basic XML document structure, and subsequent API calls append, insert, modify, or remove elements within that document structure. The use of the API greatly reduces troubleshooting headaches by minimizing typographical errors.

The API functions involved in creating XML documents are:  tpf_xml_initialize_handle()  tpf_xml_createXMLStructure()  tpf_xml_appendElement()  tpf_xml_insertElement()  tpf_xml_modifyContent()  tpf_xml_buildXMLDocument()  tpf_xml_buildXMLDocumentFragment()  tpf_xml_terminateHandle()  tpf_xml_appendBinaryElement()  tpf_xml_insertBinaryElement()  tpf_xml_modifyBinaryContent()  tpf_xml_appendElement_ext()  tpf_xml_insertElement_ext()  tpf_xml_modifyContent_ext()

In addition to these API functions, you can use the tpf_xml_position* and tpf_xml_get* functions.

Chapter 5. XML on z/TPF 99 Example 5-5 uses the z/TPF XML APIs to create a SOAP XML message that represents the message in Example 5-1 on page 97.

Example 5-5 Creating SOAP XML message with z/TPF XML APIs XMLHandle apiHandle; char* SOAPMsg; int SOAPMsgLen; int retCode

// initialize the API retCode = tpf_xml_initialize_handle(&apiHandle, B2B_XML_SCANNER, null);

// create initial XML structure retCode = tpf_xml_createXMLStructure(apiHandle, “1.0”, 819, “ISO-8859-1”, “STANDALONE_NOT_USED”, 0);

// add SOAP header retCode = tpf_xml_appendElement(apiHandle, NULL, “Envelope”, NULL, “SOAP-ENV”, “http://www.w3.org/2001/06/soap-envelope”, 0); retCode = tpf_xml_appendElement(apiHandle, NULL, “Body”, NULL, “SOAP-ENV”, “http://www.w3.org/2001/06/soap-envelope”, 0);

// add message content retCode = tpf_xml_appendElement(apiHandle, “Body”, “myApplication”, NULL, “m”, “http://www.example.org/myapplication”, 0); retCode = tpf_xml_appendElement(apiHandle, “myApplication”, “employee”, NULL, “m”, “http://www.example.org/myapplication”, 0); retCode = tpf_xml_appendElement(apiHandle, “employee”, “name”, “John Smith”, “m”, “http://www.example.org/myapplication”, 1, “gender”, “male”, NULL, NULL); retCode = tpf_xml_appendElement(apiHandle, “employee”, “department”, “Sales”, “m”, “http://www.example.org/myapplication”, 0);

// create XML document SOAPMsg = tpf_xml_buildXMLDocument(apiHandle, &SOAPMsgLen, 0);

// clean up storage retCode = tpf_xml_terminate_handle(&apiHandle);

By using the tpf_xml_position* and tpf_xml_insertElement() functions, you can create the XML document in the order that best fits the application flow. It does not have to be in the sequence of the final document, as shown in the previous example. For instance, several program modules can each add their own content to the XML document, and at the end the main program adds the SOAP headers before returning the message to the SOAP handler.

5.2.3 Creating an XML document fragment

An XML document fragment is a portion of well-formed XML that might or might not contain a root element.

This API traverses the XML structure from the beginning of the element name that the XML structure position pointer is currently pointing to and builds an XML document fragment. The returned XML document fragment contains the element node and all of the descendants of the element node. If any of the data in the XML structure is marked as nondisplayable, it is added to the XML document fragment as nondisplayable.

100 z/TPF Application Modernization using Standard and Open Middleware Example 5-6 builds an XML document fragment from the XML structure.

Example 5-6 Part of an XML document John Smith 4019 2445 0277 5567 Example Bank 04/02

#include

char *documentFragment; int documentLen = 0;

/* This example assumes all nodes have been created */ /* and that the api_handle has already been initialized */ /* by a prior call to tpf_xml_initialize_handle */ /* set position before the element "CreditCard" */ retCode = tpf_xml_positionBeforeElementTagName (api_handle, "CreditCard"); if (retCode != 0) { ..../* code to do error processing */ } documentFragment = tpf_xml_buildXMLdocumentFragment (api_handle, &documentLen, 0);

5.2.4 Sending binary data as part of an XML document

z/TPF XML APIs are available for applications to indicate to the z/TPF system that they are including binary data as part of the XML documents that are being created.

The binary data APIs are:  tpf_xml_appendBinaryElement  tpf_xml_insertBinaryElement  tpf_xml_modifyBinaryContent

These APIs indicate the addition of binary content to an XML structure that will be used solely by this or another z/TPF system. They do not actually construct a complete XML document. However, if the application calls the tpf_xml_buildXMLdocument function to create a complete XML document that contains binary data, that data will first be base64- or hexadecimal-encoded by the z/TPF system to construct a valid XML document.

For applications to get the binary data from an element by using the z/TPF XML APIs, use the following data types:  The TYPE_HEX_BINARY data type  The TYPE_BASE64_BINARY data type  The nodeValueBinary field in the NODE_VALUE_DATA_TYPE union that is returned in the nodesArray structure.

Chapter 5. XML on z/TPF 101 All of the supported data types return either fixed-length data (such as TYPE_INT) or a NULL-terminated string (such as TYPE_TEXT); however, because the binary data can be an arbitrary length and can contain embedded NULLs, the nodeValueBinary field points to a substructure that indicates the length of the data being returned as well as a pointer to a copy of the binary data.

Example 5-7 shows how to position the XML structure pointer to point after the specified element node and then inserts an element.

Example 5-7 Part of an XML message Karen Sayers #include int retCode; void *jpegPhoto; /* pointer to the binary data */ int jpegSize; /* This example assumes that the XML API handle has been */ /* initialized by a prior call to tpf_xml_initialize_handle */ /* set position to after the element "LastName" */ retCode = tpf_xml_positionAfterElementTagName (api_handle, "LastName"); if (retCode != 0) { ... /* code to do error processing */ } /* insert the element Photo with content of a JPEG file */ retCode = tpf_xml_insertBinary Element(api_handle, "PassengerName", "Photo", jpegPhoto, jpegSize, TYPE_HEX_BINARY "m", "http://www.some-uri", 0); if (retCode != 0 ) { ... /* code to do error processing */ }

5.2.5 Additional z/TPF XML APIs for append, insert, and modify

The following z/TPF XML APIs allow you to append, insert, and modify elements in an XML structure.  tpf_xml_appendElement_ext()  tpf_xml_insertElement_ext()  tpf_xml_modifyContent_ext()

These APIs can be used with binary or non-binary content node, namespace node, attribute nodes, and attribute content nodes. The differences are that the elements and attributes are passed to the API in a nodeParameters array structure instead of individually.

102 z/TPF Application Modernization using Standard and Open Middleware The extended functions are primarily intended for use when updating an XML structure for binary or non-binary data that contains storage areas that are marked as nondisplayable. If there is not a need for nondisplayable storage, use the append and insert element APIs shown in Example 5-7 on page 102.

When sensitive data is processed by an application as part of a transaction, the data is not encrypted in memory. Support for nondisplayable storage provides you with a way to protect sensitive data from being exposed in dumps, operator commands, and debugger displays.

Example 5-8 appends an element node of Photograph as the child of the Body element of the XML structure.

Example 5-8 Append an element node #include int retCode; void *jpegPhoto; /*pointer to the binary data */ int jpegSize

/* This example assumes that the XML API handle has been */ /* initialized by a prior call to tpf_xml_initialize_handle */ nodeParameters elementParms; nodeParameters attributeParms[1]; nodeParameters *attrPtr = attributeParms;

/* This example assumes that the XML API handle has been */ /* initialized by a prior call to tpf_xml_initialize_handle */

/* set position to after the element "LastName" */ retCode = tpf_xml_positionAfterElementTagName (api_handle, "LastName"); if (retCode != 0) { ... /* code to do error processing */ } elementParms.tagName = “Photo”; elementParms.tagValue = jpegPhoto; elementParms.tagLen = jpegSize; elementParms.namespacePrefix = “m”, elementParms.namespaceURI = “http://www.some.uri”; attributeParms[0].tagName = “date”; attributeParms[0].tagValue = “October 10, 2009”; attributeParms[0].tagLen = strlen(attributeParms[0].tagValue); attributeParms[0].namespacePrefix = NULL, attributeParms[0].namespaceURI = NULL;

/* insert the element Photo with content of a JPEG file */ retCode = tpf_xml_appendElement_ext (xmlapi_handle, "PassengerName", &elementParms, (TYPE_BASE64_BINARY | TYPE_NONDISPLAYABLE), 0,

Chapter 5. XML on z/TPF 103 1, &attrPtr); if (retCode != 0) { ... /* code to do error processing */ }

See z/TPF web services Support for more information about z/TPF XML API support at:

http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ib m.ztpf-ztpfdf.doc_put.cur%2Fgtps6mst.toc.html

5.2.6 Packing and unpacking an XML structure

An XML structure might be passed from one z/TPF process to another while it is being processed. However, because the physical layout of the underlying XML structure is stored in discontiguous ECB heap storage, it cannot easily be passed from one process to another. Using the tpf_xml_packXMLstructure function more efficiently promotes passing an in-progress XML document from one process to another.

The XML structure that is being passed can represent an XML document, such as a SOAP message, that was received by the z/TPF system and parsed using the tpf_xml_parseDocument function. Alternately, it can represent an XML document that is being created by a z/TPF application using the tpf_xml_createXMLstructure function.

The tpf_xml_packXMLstructure function takes an existing XML API handle and corresponding XML structure and returns a pointer to a contiguous storage area that represents the XML document that is being processed. The storage can then be filed to a z/TPF database, transmitted to another z/TPF system, or in some other way passed to another z/TPF process for further processing.

If the XML document has been packed using the tpf_xml_packXMLstructure function and you want to unpack it, the tpf_xml_initialize_handle function supports an XML_PARSER type (PACKED_XML_STRUCTURE), which indicates that a new XML API handle should be created using the contents of the previously packed XML structure.

Example 5-9 creates a packed XML structure from an XML structure that was in use.

Example 5-9 Create a packed XML structure #include

int retCode; PPackedXML *packedXMLstruct; int fd;

/* This example assumes all nodes have been created */ /* and that the api_handle has already been initialized */ /* by a prior call to tpf_xml_initialize_handle */

retCode = tpf_xml_packXMLstructure (api_handle, &packedXMLstruct);

if (retCode != 0) { .... /* code to do error processing */

104 z/TPF Application Modernization using Standard and Open Middleware } else { /* Terminate the api_handle since it is no longer */ /* needed now that we packed the XML structure */

tpf_xml_terminate_handle (&api_handle);

fd = open (“/tmp/myPackedFile.tmp”, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);

if (fd != -1) { write (fd, packedXMLstruct, packedXMLstruct->len); close (fd);

free (packedXMLstruct); } }

See the z/TPF C/C++ Language Support User's Guide for more information about the z/TPF XML APIs:

http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ib m.ztpf-ztpfdf.doc_put.cur%2Fgtpc2mst.toc.html

5.2.7 Restrictions

Remember the following important restrictions when you work with the z/TPF XML APIs:  An existing XML document that has been parsed into XML structures with the z/TPF XML APIs cannot be used to build a new XML document with the tpf_xml_buildXMLDocument() function. This is caused by the data normalization that is performed by the B2B XML scanner.  Because the XML structures are stored in the ECB heap area, they cannot be shared across ECBs.

5.3 XML4C

XML4C provides APIs for both the Document Object Model (DOM) and Simple API for XML (SAX) specifications.

In November 1999, IBM contributed the XML4C parser, as open source, to the Apache XML Project, and it became Apache’s Xerces-C XML Parser. XML4C Version 3.5.1 is based on Xerces-C Version 1.5.0 and is fully compliant with the Unicode specification. While the Apache Xerces-C parser can be updated by the open source community, the XML4C parser is maintained only by IBM and might differ from Xerces-C.

Detailed documentation for XML4C is at the following IBM website, which is also listed in the TPF Product Information Center:

http://www.ibm.com/software/htp/tpf/pubs/xml4ic/xml4c351/html/index.html

Chapter 5. XML on z/TPF 105 Because of the complexity and the extensive functionality of the XML4C API, it is outside of the scope of this book. If you require advanced XML processing capabilities beyond what the B2B XML scanner and the z/TPF XML API provide, consult the TPF Product Information Center for additional information about XML4C and links to additional resources.

5.4 z/TPF XML APIs versus XML4C

In general, the DOM and SAX specifications are more powerful than the z/TPF XML APIs and provide more functionality. However, with the added functionality comes more processing overhead and reduced performance, when compared with the B2B XML scanner and the z/TPF XML APIs. On the other side, the DOM and SAX specifications provide a standardized set of APIs to work with XML documents and code written to these APIs can run on multiple platforms, besides z/TPF. This fact also reduces the effort required to port existing applications that utilize these APIs to z/TPF.

Decide what is more important in your particular situation, and pick the XML API that provides you the best support. Generally speaking, z/TPF-based applications are concerned with consuming as little processing time as possible.

Table 5-2 was created by the developers of the z/TPF XML APIs. It outlines some of the differences between the two APIs and can provide you some guidance when deciding between the two APIs.

Table 5-2 Table 5-2 XML API comparison Function z/TPF XML API XML4C

Well-Formedness Checking Yes Yes

DTD Validation No Yes

XML Schema Validation No Yes

Namespaces Only provides access to the specified namespace but Ye s does not validate it.

SAX 1.0 No Yes

SAX 2.0 No Yes

DOM Level 1 subset (conceptual) Yes

DOM Level 2 subset (conceptual) Yes

Based on customer requests, it is likely that the z/TPF XML APIs will be extended in the future. Always check z/TPF PUT announcements about additional XML support in the future.

106 z/TPF Application Modernization using Standard and Open Middleware Part 3

Part 3 z/TPF as a Web service provider and consumer

Part 3 of the book describes a z/TPF application as a Web Service provider and as a Web Service SOAP consumer. It also describes accessing z/TPFDF databases through service data objects.

This part contains the following chapters:  Chapter 6, “z/TPF application as a Web service provider” on page 109  Chapter 7, “Accessing z/TPFDF databases through SDO” on page 127  Chapter 8, “z/TPF SOAP consumer processing” on page 139  Chapter 9, “Using a z/TPF application as a Web service SOAP consumer” on page 149

© Copyright IBM Corp. 2013. All rights reserved. 107 108 z/TPF Application Modernization using Standard and Open Middleware 6

Chapter 6. z/TPF application as a Web service provider

This chapter describes a sample Web service built and enabled on a z/TPF system.

This chapter contains the following topics:  6.1, “Defining the sample Web service” on page 110  6.2, “Creating a SOAP message handler deployment descriptor” on page 113  6.3, “Creating a provider Web service deployment descriptor” on page 114  6.4, “Creating a Web server wrapper” on page 117  6.5, “Enabling z/TPF SOAP support” on page 123  6.6, “Deploying a SOAP message handler to the z/TPF system” on page 124  6.7, “Deploying a Web service to the z/TPF system” on page 125  6.8, “Writing a Web service wrapper for SOAP bridge support” on page 125  6.9, “Deploying a Web service for SOAP bridge support” on page 126

© Copyright IBM Corp. 2013. All rights reserved. 109 6.1 Defining the sample Web service

This chapter uses a Web service called CalculatorService to illustrate the concepts of using a z/TPF application as a web service provider.

The XML interface to the Calculator Web Service has been kept as simple as possible to illustrate this example. The input message is a request for add or subtract. The output message contains the calculated addResponse or subResponse.

Example 6-1 shows a sample request to CalculatorService. The input message is a request for add or subtract.

Example 6-1 The example CalculatorService request 23 64

The output message, shown in Example 6-2, contains the calculated addResponse or subResponse.

Example 6-2 The example CalculatorService response 87

Example 6-3 shows the WSDL document for this web service.

Example 6-3 The example Web Service WSDL document 1 2

110 z/TPF Application Modernization using Standard and Open Middleware 7 xmlns="http://schemas.xmlsoap.org/wsdl/"> 8 9 14 15 16 17 18 19 20 21 22 23 24 25 26 27

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

Chapter 6. z/TPF application as a Web service provider 111 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

In the WSDL document for the service, the XML interface is encoded as follows, from the bottom up:  The service, which normally groups related ports together, but there is only one port called CalculatorService.  The portType CalculatorService containing the operations add and subtract having: – addRequest as an input – addResponse as an output – subRequest as an input – subResponse as an output  The SOAP binding for CalculatorService, which defines the SOAP endpoint address to be the TCP/IP address of the z/TPF system: http:///xxx.xxx.xxx.xxxx/CalculatorService  The addRequest, addResponse, subRequest, and subResponse messages and their parts.  The list of type definitions.

112 z/TPF Application Modernization using Standard and Open Middleware 6.2 Creating a SOAP message handler deployment descriptor

SOAP message handler deployment descriptors are specialized XML documents that control the activation of SOAP message handlers to the SOAP runtime.

Deployment descriptors must be named ddname.xml, where ddname is the 1 to 256-character unique name of the file to be placed in the /etc/tpf-ws/ directory of the z/TPF file system.

The format for the z/TPF deployment descriptors is defined in the base/tpf-ws/schema/tpf_ws_dd_vn.xsd XML Schema file (where n is the version number) that is shipped with the z/TPF system.

The elements of the SOAP message handler deployment descriptor must appear in the XML document in the same order that they are listed in Example 6-4.

Example 6-4 SOAP message handler deployment descriptor elements 1 2 6 logging 7 CSOL 8 This is a logging message handler that writes log messages to the syslog daemon 9

In Example 6-4 on page 113:  Lines 2-4 show the root element of the SOAP message handle deployment descriptor with the namespace for the elements that follow.  Line 5 shows the location of the deployment descriptor schema document in the z/TPF file system  Line 6 shows the 1- to 32-character, user-specified symbolic name that uniquely identifies the SOAP feature being implemented with this SOAP message handler.  Line 7 shows the 4-character name of the z/TPF program to be activated when a SOAP request is received for a given Web service and the corresponding Web service deployment descriptor for that service has this SOAP message handler listed in its SOAP message handler chain.  Not shown: element SOAPMessageHandlerURI The 1- to 512-character URI for the SOAP feature being implemented with this SOAP message handler. The URI uniquely identifies this SOAP message handler. It must match the namespace URI used in the SOAP header blocks referenced by this SOAP message handler. This element is optional because message handlers can be defined that do not directly operate on information in SOAP header blocks. However, specify this element if the information is available, to handle the VerifySOAPHeaders element correctly in a provider Web service deployment descriptor. The SOAPMessageHandlerURI element can appear multiple times if this SOAP message handler uses multiple namespace URIs to implement the SOAP feature.  Line 8 shows a 1- to 256-character, meaningful description that you wrote of the SOAP message handler that is identified by this SOAP message handler deployment descriptor. This element is optional.

Chapter 6. z/TPF application as a Web service provider 113 6.3 Creating a provider Web service deployment descriptor

Provider Web service deployment descriptors are specialized XML documents that control the activation of provider web services to the SOAP runtime.

The deployment descriptor must be named according to the file format ddname.xml, where ddname is the 1- to 256-character, unique name of the file to be placed in the /etc/tpf-ws/ directory of the z/TPF file system.

The format for z/TPF deployment descriptors is defined in the base/tpf-ws/schema/tpf_ws_dd_vn.xsd XML Schema file (where n is the version number) that is shipped with the z/TPF system.

The following elements of the provider Web service deployment descriptor must appear in the XML document in the same order shown in Example 6-5.

Example 6-5 Provider web service deployment descriptor elements 1 2 6 /CalculatorService 7 CSOB 8 9 10 logging 12 13 14 false 15 SOAP1.1 16 17 add 18 sub 19 This a sample Web Service that implements a simple Calculator: see CalculatorService.wsdl for more details. 20 21

In Example 6-5 on page 114:  Lines 2-4 show the root element of the SOAP provider Web service deployment descriptor with the namespace for the elements that follow.  Line 5 shows the location of the deployment descriptor schema document in the z/TPF file system  Line 6 shows the 1- to 512-character URI for the Web service that is identified by this deployment descriptor. The URI that is specified must match exactly the value that will be specified in the applRoutingInfo field of the commsBinding structure, which is passed to the tpf_soap_handler function.  Line 7 indicates the 4-character name of the z/TPF program that is activated when a SOAP request is received for this Web service.

114 z/TPF Application Modernization using Standard and Open Middleware  Line 8 shows the elements in the Web service deployment descriptor that control the processing of the SOAP handler when a SOAP request is received for this Web service.  Line 9 shows the list of SOAP message handlers that are to be called when a SOAP request is received for this Web service. The order that the SOAP message handlers are specified is the order in which they will be called when processing a SOAP request. The same SOAP message handlers are called in the reverse order when processing a SOAP response message to be sent to the originator. This element is optional.  Lines 10-13 indicate the SOAP message handler to be called when processing a SOAP request that is received for this Web service, or a SOAP response that is sent by this Web service. The SOAP message handler name specified is the 1- to 32-character, user-specified symbolic name that uniquely identifies the SOAP message handler to be called.

Tip: The TPF Toolkit provides tooling to help you create the provider web service deployment descriptor.

A corresponding SOAP message handler deployment descriptor must exist. The SOAPMessageHandler element can appear multiple times when more than one SOAP message handler is to be called for this Web service. The following attributes can be specified for this element: – required The required attribute indicates whether the SOAP message handler is required to perform processing on the SOAP requests and responses for this Web service. The value that is set will be passed to the SOAP message handler program to perform the actual processing. The meaning of this attribute can be different for each SOAP message handler: • true Indicates that the SOAP message handler is required to perform processing on the SOAP requests and responses for this Web service. • false Indicates that the SOAP message handler is not required to perform processing on the SOAP requests and responses for this Web service. – extensionFile (not shown) Indicates the 1- to 256-character relative path name of the SOAP message handler extension file that specifies service-specific information to control the processing of the SOAP message handler. The path name should have a file extension of .xml; however, this is not required. This attribute is optional.  Line 14 indicates whether the z/TPF SOAP runtime verifies the SOAP header blocks that appear in SOAP requests received for this Web service. SOAP header blocks are used to implement SOAP features, which extend the basic SOAP standard: – true All SOAP header blocks that are present in SOAP requests received for this Web service will be verified. If the z/TPF SOAP runtime detects a SOAP header block that has the mustUnderstand attribute set to true (SOAP 1.1 or SOAP 1.2) or 1 (SOAP 1.1), and a corresponding SOAP message handler has not been called to process the SOAP header block, the z/TPF system will generate a SOAP fault message to be returned to the originator. The z/TPF SOAP runtime will only generate a fault message for those SOAP header blocks for which it is determined that the z/TPF system plays the required role, as

Chapter 6. z/TPF application as a Web service provider 115 determined by the actor attribute (SOAP 1.1) or the “role” attribute (SOAP 1.2) specified on the SOAP header block. The following roles are valid for the z/TPF system: http://www.w3.org/2003/05/soap-envelope/role/none http://www.w3.org/2003/05/soap-envelope/role/next http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver – false The z/TPF SOAP runtime does not verify any of the SOAP header blocks that are contained in SOAP requests that are received for this Web service. All SOAP message handlers specified in the SOAPMessageHandlerChain are still called by the z/TPF SOAP runtime; however, no verification is performed that all of the necessary SOAP header blocks have been processed. Use this value when there might be SOAP header blocks included in the SOAP requests that are handled by the Web service itself, rather than by SOAP message handlers.  Line 15 shows the acceptable format of SOAP requests for this Web service. This element is optional, and if not specified, the z/TPF SOAP runtime treats this Web service as though the DEFAULT value was specified. If the Web service accepts SOAP requests in multiple formats, this element can appear multiple times, unless otherwise stated. If a SOAP request is received for this Web service in an unacceptable format, the z/TPF SOAP runtime generates a SOAP fault message to return to the originator. –DEFAULT Indicates that SOAP requests are expected to be in the format corresponding to the SOAP version that is specified in the version field of the inputMsg parameter passed to the tpf_soap_handler function. When this value is specified, the SOAPVersion element cannot appear more than once. –SOAP1.1 Indicates that a SOAP request for this Web service is acceptable if it is in SOAP 1.1 format. This value and the BP1.1_SSBP1.1 value cannot both be specified for the same Web service. –SOAP1.2 Indicates that a SOAP request for this Web service is acceptable if it is in SOAP 1.2 format. – BP1.1_SSBP1.1 Indicates that a SOAP request for this Web service is acceptable if it is in SOAP 1.1 format. Also, this instructs the z/TPF SOAP runtime to perform checks on the message to ensure that it is compliant with the Organization for the Advancement of Structured Information Standards (OASIS) Web Services Interoperability (WS-I) Basic Profile 1.1 and the OASIS WS-I Simple Soap Binding Profile 1.1. When a SOAP request is found to be non-compliant, the z/TPF SOAP runtime generates a SOAP fault message to be returned to the originator. This value and the SOAP1.1 value cannot both be specified for the same Web service.  Lines 17-18 Operation shows the 1- to 128-character name of a service method that is exposed as part of this Web service. The Operation element is optional, but can appear multiple times if this Web service exposes multiple methods.  Line 19-20 shows a 1- to 256-character, meaningful description that you have written of the Web service that is identified by this deployment descriptor. This element is optional.

116 z/TPF Application Modernization using Standard and Open Middleware 6.4 Creating a Web server wrapper

Web service wrappers are intended to be an isolation point for the portion of code that does the following:  Deserializes the operation and parameter data from the parsed SOAP request.  Calls the application that implements the Web service.  Serializes the return from the application and builds the Body portion of the SOAP response.

This architecture allows the application to be deployed as a Web service while not requiring changes to handle request data in the SOAP format.

SOAP support uses the TPF_CALL_BY_NAME API to call the four-character Web service wrapper program name that is specified in the provider Web service deployment descriptor for a Web service. Processing is implemented in C shared objects. CSOs must have a single entry point as defined in the makefile. The interface to the CSO must match the interface that is defined by the typedef that is used to define SOAP message handlers. The format of the typedef is: typedef int (*intfn)(tpfSoapMsgCtx*);

An explanation of the typedef follows:  Web service wrappers must return an integer. Valid values are SendReply, SendErrorReplySender, SendErrorReplyReceiver, and ErrorReplyNeeded, as defined in the tpf/c_soap.h header file.  The only parameter is a pointer to a tpfSoapMsgCtx structure, which is defined in the tpf/c_soapctx.h header file.  The intfn pointer is a pointer to the function type and is passed to the TPF_CALL_BY_NAME macro. With this pointer and the four-character program name that implements the Web service wrapper, the TPF_CALL_BY_NAME macro returns a pointer to function value that calls an enter with return linkage (ENTRC linkage) to the specified program.

The tpfSoapMsgCtx structure contains information about the Web service that is being processed, for example:  An XMLHandle structure that represents the SOAP message and is called requestMsg.  An XMLHandle structure that represents the response message and is called responseMsg.

You can use the z/TPF XML APIs to help in accessing the data in the SOAP request and in creating the SOAP response. The TPF Toolkit provides tooling to help you create the Web service wrapper.

Example 6-6 shows a sample Web service wrapper calling a z/TPF application simpleCalcApp().

Example 6-6 Web service wrapper calling simpleCalcApp() int CSOB(tpfSoapMsgCtx *ctx) { XMLHandle inputHandle = ctx->request_handle.xml_handle; xmlNodesArray *xptr = NULL; char *returnMsg=NULL, *returnElement=NULL; int ret_val=0;

Chapter 6. z/TPF application as a Web service provider 117 char result[32]; int retCode, number1=0, number2=0, operation=0; /* position to after the SOAP body */ retCode = tpf_xml_positionAfterElementTagName(inputHandle,"Body"); if (retCode != 0) { create_soap_fault_return( ReceiverOrServer, "Unable to process request", "Could not find SOAP Body element",ctx); return SendErrorReplyReceiver; } /* get next element after the body...should be our operation */ xptr = tpf_xml_getNextElement(inputHandle, TYPE_TEXT); if (xptr == NULL) { /* any errors, return a SOAP fault response */ create_soap_fault_return( SenderOrClient, "Unable to perform calculator function", "Expected element tag not found",ctx); return SendErrorReplySender; } else { if (xptr->returnCode == 0){ if (xptr->nodesArraySize == 0){ create_soap_fault_return( SenderOrClient, "Unable to perform calculator function", "Expected element tag not found",ctx); return SendErrorReplySender; } else { if (strcasecmp(xptr->nodesArray[0].nodeName, "add") == 0) { operation = CSOB_ADD; } else if (strcasecmp(xptr->nodesArray[0].nodeName, "sub") == 0) { operation = CSOB_SUB; } else { /* error case, bad operation */ create_soap_fault_return( SenderOrClient, "Unable to perform calculator function", "Bad operation requested",ctx); return SendErrorReplySender; } } } else { create_soap_fault_return( SenderOrClient, "Unable to perform calculator function", "Operation not specified",ctx); return SendErrorReplySender; } } /* get the operands for this request */ xptr = tpf_xml_getElementsByTagName(inputHandle, TYPE_INT, "value");

118 z/TPF Application Modernization using Standard and Open Middleware if (xptr == NULL) { /* any errors, return a SOAP fault response */ create_soap_fault_return( SenderOrClient, "Unable to perform calculator function", "Expected element tag not found",ctx); return SendErrorReplySender; } else { if (xptr->returnCode == 0){ if (xptr->nodesArraySize == 0){ create_soap_fault_return( SenderOrClient, "Unable to perform calculator function", "Expected element tag not found",ctx); return SendErrorReplySender; } else { if (xptr->nodesArraySize == 2) { number1 = xptr->nodesArray[0].nodeValueDataType.nodeValueInt; number2 = xptr->nodesArray[1].nodeValueDataType.nodeValueInt; } else { create_soap_fault_return( SenderOrClient, "Unable to perform calculator function", "Incorrect number of operands",ctx); return SendErrorReplySender; } } } else { create_soap_fault_return( SenderOrClient, "Unable to perform calculator function", "Conversion to integer failed on input values",ctx); return SendErrorReplySender; } } /***********************************************************/ /* Now we call the simple calculator application: */ /* int simpleCalcApp(int operation, int op1, int opt2) */ /***********************************************************/ if (operation == CSOB_ADD) { ret_val = simpleCalcApp(CSOB_ADD, number1, number2); sprintf (result, "%d", ret_val); returnMsg = "addResponse"; returnElement = "addReturn"; } else if (operation == CSOB_SUB) { ret_val = simpleCalcApp(CSOB_SUB, number1, number2); sprintf (result, "%d", ret_val); returnMsg = "subResponse"; returnElement = "subReturn"; } /*********************************************************/ /* Create Response Message */ /*********************************************************/

Chapter 6. z/TPF application as a Web service provider 119 retCode = tpf_xml_initialize_handle (&(ctx->response_handle.xml_handle), NO_PARSER, NULL); /* if error, return a SOAP fault response */ if (retCode != 0) { create_soap_fault_return( ReceiverOrServer, "Unable to process request", "Initialize API handle failed",ctx); return SendErrorReplyReceiver; } /* create an XML structure to be used for the response */ retCode = tpf_xml_createXMLstructure (ctx->response_handle.xml_handle, "1.0", 819, "ISO-8859-1", STANDALONE_YES, 2, "Web Service Wrapper Sample", returnMsg); /* if error, return a SOAP fault response */ if (retCode != 0) { create_soap_fault_return( ReceiverOrServer, "Unable to create XML response", "Create XML structure for response failed",ctx); return SendErrorReplyReceiver; } /* add the first required element of the SOAP response - Envelope */ retCode = tpf_xml_appendElement (ctx->response_handle.xml_handle, NULL, "Envelope", NULL, "SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", 0); /* if error, return a SOAP fault response */ if (retCode != 0) { create_soap_fault_return( ReceiverOrServer, "Unable to create XML response", "Adding elements failed",ctx); return SendErrorReplyReceiver; } /* add the next required element of the SOAP response - Body */ retCode = tpf_xml_appendElement (ctx->response_handle.xml_handle, "Envelope", "Body", NULL, "SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/",

120 z/TPF Application Modernization using Standard and Open Middleware 0); /* if error, return a SOAP fault response */ if (retCode != 0) { create_soap_fault_return( ReceiverOrServer, "Unable to create XML response", "Adding elements failed",ctx); return SendErrorReplyReceiver; } /* add the element for the result of the calculator function */ retCode = tpf_xml_appendElement (ctx->response_handle.xml_handle, "Body", returnMsg, NULL, "ns1", "http://www.mycompany.com/sample/calculator", 0); /* if error, return a SOAP fault response */ if (retCode != 0) { create_soap_fault_return( ReceiverOrServer, "Unable to create XML response", "Adding elements failed",ctx); return SendErrorReplyReceiver; } /* add the element for the result of the calculator function */ retCode = tpf_xml_appendElement (ctx->response_handle.xml_handle, returnMsg, returnElement, result, "ns1", "http://www.mycompany.com/sample/calculator", 0);

/* if error, return a SOAP fault response */ if (retCode != 0) { create_soap_fault_return( ReceiverOrServer, "Unable to create XML response", "Adding elements failed",ctx); return SendErrorReplyReceiver; } ctx->response_handle.type = TPF_HDL_RESP; return(SendReply); } /*************************************************************/ /* Create fault structure for tpf_soap_build_fault */ /* Use the parameters passed in to fill out the structure */ /*************************************************************/ void create_soap_fault_return(FAULTS faultDesc, char *reason, char *detail, tpfSoapMsgCtx *ctx)

Chapter 6. z/TPF application as a Web service provider 121 { soapFault fault, *fault_ptr; int retCode; /* determine SOAP version to be used */ fault_ptr = &fault; fault_ptr->version = ctx->request->version; if (fault_ptr->version == UNKNOWN) { fault_ptr->version = DEFAULT_SOAP_VERSION; } switch (ctx->request->clientEncoding) { case TPF_CCSID_LATIN1: fault_ptr->encoding = TPF_CSNAME_LATIN1; break; case TPF_CCSID_UTF8: fault_ptr->encoding = TPF_CSNAME_UTF8; break; case TPF_CCSID_UTF16BE: fault_ptr->encoding = TPF_CSNAME_UTF16BE; break; case TPF_CCSID_UTF16LE: fault_ptr->encoding = TPF_CSNAME_UTF16LE; break; case TPF_CCSID_IBM1047: fault_ptr->encoding = TPF_CSNAME_IBM1047; break; case TPF_CCSID_IBM500: fault_ptr->encoding = TPF_CSNAME_IBM500; break; default: fault_ptr->encoding = TPF_MY_HOST_CSNAME; break; } fault_ptr->xmlVersion = XML1_0; /* get the correct descriptions based on SOAP version */ if (fault_ptr->version == SOAP1_1) { fault_ptr->faultCode = faultDesc; switch (faultDesc) { case SenderOrClient: fault_ptr->faultCode = Client; break; case ReceiverOrServer: fault_ptr->faultCode = Server; break; default: break; } fault_ptr->faultString = reason; fault_ptr->faultActor = NULL; } else { fault_ptr->code = faultDesc; fault_ptr->language = "en-US"; switch (faultDesc) {

case SenderOrClient:

122 z/TPF Application Modernization using Standard and Open Middleware fault_ptr->code = Sender; break; case ReceiverOrServer: fault_ptr->code = Receiver; break; default: break; } fault_ptr->subcodeValue = NULL; fault_ptr->reason = reason; fault_ptr->subcodeValue = NULL; fault_ptr->node = fault_ptr->role = NULL; } /* complete other shared fault fields for response */ fault_ptr->detail = detail; retCode = tpf_soap_build_fault_ext(fault_ptr, &(ctx->response_handle.xml_handle)); if (retCode != TPF_FAULT_BUILT) { return; } ctx->response_handle.type = TPF_HDL_FAULT; return; }

6.5 Enabling z/TPF SOAP support

You must complete the following tasks to ensure that you have all the components correctly set up on your z/TPF system to receive and respond to SOAP messages. 1. Identify your host encoding. A SOAP message must be in the host encoding before it can be processed by an application. To ensure that SOAP messages are translated correctly, you must identify the host encoding of your z/TPF system in the c_soap.h header file. By default, this header file defines the host encoding as TPF_CCSID_IBM1047 or Latin Open Systems EBCDIC. If your host encoding is different than the default character set, you must do these steps: a. Open the c_soap.h header file, as shown in Example 6-7. b. Locate the #define TPF_MY_HOST_CCSID field. c. Change the TPF_CCSID_IBM1047 value to the appropriate coded character set identifier (CCSID) value. d. Locate the #define TPF_MY_HOST_CSNAME field. e. Change the ibm-1047 value to the appropriate character set name. See 3.3, “SOAP message encoding” on page 41 for more information about how SOAP uses encodings and supported translation functions.

Example 6-7 Locating the default character set in header file c_soap.h /* host codeset definitions */ #ifndef TPF_MY_HOST_CSNAME #define TPF_MY_HOST_CSNAME TPF_CSNAME_IBM1047 #endif #ifndef TPF_MY_HOST_CCSID

Chapter 6. z/TPF application as a Web service provider 123 #define TPF_MY_HOST_CCSID TPF_CCSID_IBM1047 #endif

f. Identify the SOAP version. SOAP support on the z/TPF system includes versions 1.1 and 1.2. If you want to use version 1.2, you do not have to make any changes. If you want to use version 1.1 of SOAP, open the c_usoapeq.h header file and locate the #define DEFAULT_SOAP_VERSION field. Change the SOAP1_2 value to SOAP1_1, as shown in Example 6-8.

Example 6-8 Locating the default SOAP version in header file c_usoapeq.h #define DEFAULT_SOAP_VERSION SOAP1_2

2. Enable a SOAP communications binding. When a SOAP message arrives on the z/TPF system, it travels over the network. A SOAP communications binding is required on z/TPF to take the message from the network, to begin the required processing, and to send the response back to the client. You can use any SOAP communications binding. 3. Ensure that the appropriate translation is enabled. You might have to update the SOAP handler user exit with translation routines, which must translate a SOAP message to your host encoding. See 3.1, “SOAP handler” on page 34 for more information about how translation is handled with z/TPF SOAP support. 4. Create or modify an application for using SOAP.

6.6 Deploying a SOAP message handler to the z/TPF system

To deploy a SOAP message handler to the z/TPF system: 1. Load and activate the SOAP message handler program. Because this is simply another application, follow the same procedure for loading and activating any application. 2. If there is one, load and activate the SOAP message handler extension program. Again, because this is simply another application, follow the same procedure for loading and activating any application. 3. Load the SOAP message handler deployment descriptor by FTPing the file in binary form to the z/TPF file system under the /etc/tpf-ws/ directory. 4. Activate the SOAP message handler deployment descriptor by entering the ZWSAT command with the DEPLOY parameter to deploy the SOAP message handler.

The TPF Toolkit provides an action to load the deployment descriptor file using FTP to send the file to the z/TPF file system. The TPF Toolkit can also activate the deployment descriptor by using the DEPLOY action for a selected Web service resource shown in the Remote Systems Explorer (RSE).

There are two options for undeploying a SOAP message handler on the z/TPF system:  Enter the ZWSAT command with the UNDEPLOY parameter to mark the resource as unavailable.  Enter the ZWSAT command with the REMOVE parameter to remove the entry for the resource from the web services deployment table (WSDT).

The undeploy action and the remove action have essentially the same effect when performed for a SOAP message handler.

124 z/TPF Application Modernization using Standard and Open Middleware 6.7 Deploying a Web service to the z/TPF system

To deploy a Web service to the z/TPF system: 1. Follow your normal procedure for loading and activating the application. 2. Load and activate the Web service wrapper. Because this is simply another application, follow the same procedure for loading and activating any application. 3. Load the provider Web service deployment descriptor by FTPing the file in binary form to the z/TPF file system under the /etc/tpf-ws/ directory. 4. Activate the provider Web service deployment descriptor by entering the ZWSAT command with the DEPLOY parameter to deploy the Web service.

Tip: Validate the WSDL file, and test the Web service before you deploy the Web service. The TPF Toolkit can help you to do this.

The TPF Toolkit provides an action to load the deployment descriptor file using FTP to send the file to the z/TPF file system. The TPF Toolkit can also activate the deployment descriptor by using the DEPLOY action for a selected Web service resource shown in the Remote Systems Explorer (RSE).

6.8 Writing a Web service wrapper for SOAP bridge support

To write a Web service wrapper for SOAP bridge support: 1. When you deploy a Web service that uses SOAP bridge support, each inbound SOAP request must have a line number, interchange address, and terminal address (LNIATA) associated with it. You must determine how the LNIATA becomes associated with each request. When you choose the LNIATA, the Web service wrapper must call the tpf_soapBridge_register function to register that LNIATA to be used with SOAP bridge support. When the LNIATA is registered, the z/TPF system is notified that any output messages destined for that address should be intercepted for delivery by the SOAP bridge rather than being routed by the normal mechanism determined by the terminal type. 2. After registering the LNIATA to be associated with a given SOAP request, you must convert the request itself into a format that the z/TPF application can understand. To perform this conversion, the wrapper might need to interrogate elements in the SOAP body and assemble them together into the correct application message (AMSG) format. Use the tpf_convertToAMSG function to convert the character string into AMSG format when the input message can be concatenated into a single character string. 3. Call the tpf_soapBridge_route function to route the message to the destination application after the input message is in AMSG format. In the Web service wrapper, you can choose to: – Explicitly name the application to route the message to. – Use an LNIATA that is permanently logged on to a specific application. – Build the corresponding routing control parameter list (RCPL), which specifies the destination application. The tpf_soapBridge_route function creates a new ECB, which will transport the input message to the message router program (COA4) and ultimately to the destination application.

Chapter 6. z/TPF application as a Web service provider 125 The application issues a ROUTC macro call (or a series of ROUTC macro calls) to send the correct response messages. However, because the SOAP handler is expecting the SOAP response to be returned from the same ECB that processed the original request, the z/TPF system intercepts the output messages that are destined for the SOAP bridge LNIATA and queues those messages until they are requested by the Web service wrapper. 4. Call the tpf_soapBridge_receive function to get an output message destined for a particular LNIATA. If an application can send multiple output messages in response to a single input message, the Web service wrapper must issue multiple calls to the tpf_soapBridge_receive function to get each of the corresponding output messages. The wrapper must then compile the output messages into a single SOAP response to be returned to the SOAP handler and ultimately to the Web service consumer. 5. Before returning the SOAP response to the SOAP handler, determine whether the Web service wrapper should keep the LNIATA that was registered for use by SOAP bridge support. For example, depending on the nature of the application it might be necessary to maintain the same LNIATA across several SOAP requests. In this case, after processing the initial SOAP request, the SOAP response that is returned to the Web service consumer might need to contain the actual LNIATA or a token that is associated with that LNIATA. (The same token must be returned on any requests that follow.) This permits a conversation of sorts to exist between the Web service consumer and the Web service provider. In this case, it is not necessary to unregister the LNIATA for use by SOAP bridge support at this time. 6. If it is determined by the Web service wrapper that the conversation has ended (or when there is a single request/response flow), unregister the LNIATA by calling the tpf_soapBridge_unregister function. After calling this function, output messages that were destined for the specified LNIATA will no longer be intercepted by SOAP bridge support. Furthermore, any output messages queued by SOAP bridge support that were not retrieved for that LNIATA are discarded.

A sample SOAP bridge Web service wrapper is available for download at the following website:

http://www.ibm.com/software/htp/tpf/maint/toolsztpf.html

6.9 Deploying a Web service for SOAP bridge support

Taking advantage of SOAP bridge support permits you to easily expose heritage applications as web services without changing the actual applications. It enables you to continue using the existing business logic on your z/TPF system and externalize it as a callable service. Deploying an existing z/TPF application as a Web service is the same as deploying any other application as a Web service; however, to deploy the z/TPF application as a service over the SOAP bridge means using the z/TPF SOAP bridge application programming interfaces (APIs) in the corresponding Web service wrapper.

126 z/TPF Application Modernization using Standard and Open Middleware 7

Chapter 7. Accessing z/TPFDF databases through SDO

This chapter discusses the value of service data objects (SDO) in relationship to z/TPFDF and provides an overview of setting up and using SDO to access z/TPFDF databases.

This chapter contains the following topics:  7.1, “Value of SDO access to z/TPFDF” on page 128  7.2, “Enabling SDO access ” on page 128  7.3, “SDO examples” on page 130

© Copyright IBM Corp. 2013. All rights reserved. 127 7.1 Value of SDO access to z/TPFDF

From a business perspective, using SDO to access z/TPFDF databases on z/TPF can provide value to your enterprise in several ways:  In the same way that web services allow previously hidden services to participate in service-oriented architecture (SOA), SDO provides a standard way for data to be exposed and used in SOA. Businesses are quickly realizing the value of the data they have in their enterprise systems, and the easier they can provide access to the data means the faster they can extract value from that data. Traditionally, z/TPFDF databases are only accessed by an application running on the z/TPF system. While SDO is not expected to replace the critical, high-volume transactional applications that operate against z/TPFDF databases on z/TPF, businesses can realize additional value from their z/TPFDF data by allowing other systems to access and manipulate this data through SDO. These other systems might provide ancillary functions that provide value to your customers or might update the z/TPFDF data with data from other systems, unlocking insights into your customers and your business.  In the past, accessing z/TPFDF databases from other platforms meant creating your own access methods. These methods were usually logging to tape, writing to message queues, or creating custom protocols and transformations for data transmission, formatting, and serialization. Not only is this time consuming in terms of development and maintenance, but it necessarily limited which platforms had access to the data as you only can spend the resource to provide support on those systems which had the most critical need to access z/TPFDF databases. As a standard, SDO is readily available on a wide variety of platforms. SDO access to z/TPFDF uses WebSphere MQ as the communications transport, which is also available on most platforms. By using these standards, development and maintenance costs are greatly reduced by not having to write your own protocols or transformations. This also means that z/TPFDF databases can be accessed from any system participating in your SOA environment, removing the limitations imposed by having custom protocols and transformations. The SDO standard can also simplify applications by providing a standard way to represent data across data sources. Instead of writing and maintaining code to handle the different data sources (relational databases, XML, z/TPFDF, and so on), application programmers can program to the SDO standard regardless of the data source. This allows programmers to concentrate on the business logic instead of the unique access and management methods for each data source.  Not only does SDO provide a standard data representation regardless of the data source, but it also hides the persistence methodologies used by the different data sources. While it might seem trivial to handle the persistence method used by a single data source, it can become cumbersome and expensive in terms of program development and maintenance when an application is managing heterogeneous data sources. As businesses strive to extract additional value from their data, it is increasingly common for applications to join data from relational databases, z/TPFDF, and other data stores. By hiding the persistence methodologies from the application, SDO can provide savings through simpler and easier to maintain applications without changing presentation or business logic.

7.2 Enabling SDO access

This section provides an overview of enabling SDO access to z/TPFDF databases, both on the z/TPF and the client systems.

128 z/TPF Application Modernization using Standard and Open Middleware 7.2.1 Enabling SDO access for z/TPFDF

Use the following steps to enable SDO access for z/TPFDF: 1. Create the necessary directories in the z/TPF file system. These directories will hold the metadata describing the z/TPFDF databases and access control and configuration files. 2. Prepare the z/TPFDF databases for use by SDO: a. Update the z/TPFDF DBDEFs with new parameters specifying database names, aliases, and versions. Adding the database name joins DBDEFs with the same database name into a single logical database and allows those logical databases to be accessed by SDO. b. Create, edit, and load the metadata for the z/TPFDF databases that will be accessed through SDO. By using the ZUDFM METADATA command on z/TPFDF, you can easily create the metadata for each of your databases based on your DBDEFs and existing database definitions in z/TPFDF. By editing the metadata, you can provide aliases for your structures and fields and make sure data types are consistent with their usage. 3. Configure WebSphere MQ on z/TPF to act as the transport mechanism for SDO. 4. Update and load the z/TPFDF SDO security user exit as needed. Depending on where access control is provided in your enterprise, you can perform access control in the z/TPFDF SDO security user exit or at higher levels in your enterprise. 5. Configure the z/TPFDF SDO access and configuration files. The access file defines the database permissions (read-only or read/write) and optional authentication method for each database, user, subsystem, and subsystem user combination. The configuration file provides z/TPF-specific controls to limit system resources used by SDO.

Complete instructions and examples for all of the steps are in the Service Data Objects (SDO) Access to z/TPFDF User’s Guide at:

http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ib m.ztpf-ztpfdf.doc_put.cur%2Fbdfs7mst.toc.html

7.2.2 Enabling SDO on the client system

To use SDO to access z/TPFDF databases from your client application, you first need to set up the client environment to use the z/TPFDF Data Access Service (DAS). Complete instructions on setting up the client environment are included in the readme file that is part of the z/TPFDF DAS package downloaded in step 1. In addition to the set up steps, the file includes websites where the various software products can be found and product version requirements: 1. Download the z/TPFDF Data Access Service (DAS) package from the IBM Library Downloads for the TPF Family of Products website at: http://www.ibm.com/tpf/download/tools.htm 2. Download and install the Apache Tuscany SDO library. This library provides the SDO APIs and framework needed to create, manage, and update data graphs and data objects. 3. Download and install an XML parser for use by the z/TPFDF DAS. 4. Install and configure WebSphere MQ client for use as the SDO transport mechanism between the z/TPF and client systems. 5. Install the z/TPFDF DAS downloaded in step 1. The DAS manages the communications and data transfer between the client systems and z/TPF for the client application.

Chapter 7. Accessing z/TPFDF databases through SDO 129 The z/TPFDF DAS provides two methods for use by the client application: readData and applyChanges, which allow the client application to read data from z/TPFDF in the form of data graphs and write changed data graphs back to z/TPFDF. More information about these methods and supporting classes are in the IBM TPF Product Information Center and in the javadoc files in the ZTPFDFDAS.jar file. 6. Optionally, install a software development kit (SDK) to provide a Java development environment.

7.3 SDO examples

The examples in this section provide a basic overview to reading and updating a sample credit card database in z/TPFDF through SDO. Additional examples with more detail and explanations are in the Service Data Objects (SDO) Access to z/TPFDF User’s Guide, at the following website.

http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ib m.ztpf-ztpfdf.doc_put.cur%2Fbdfs7mst.toc.html

7.3.1 Example credit database

This examples uses a credit card database containing credit card, purchase, and security information. The SDO XML metadata file that represents this database are in Appendix E, “XML file for SDO examples” on page 449. All figures provide a conceptual view of the data and do not show actual z/TPFDF files, data graphs, or data objects.

Figure 7-1 on page 131 shows a subset of the Credit database as it is stored in z/TPFDF.

130 z/TPF Application Modernization using Standard and Open Middleware DR11ED: CreditFile

Credit50 Purchases SecurityFile CreditCard Flags Limit

50 12345678 0 5000.00

50 98765432 0 10000.00

DR12ED: Purchases DR14ED: SecurityFile

AuthD3 UserName SSN Address Flag1 Flag2 User Security56 PinUniqueKey Pin Unique Key 56 1 1234

D3 John Doe xxx-xx-1234 12 Main St. 0 0 1 56 2 9876

D3 Jane Doe xxx-xx-6789 12 Main St. 0 0 2 Security5D PhotoUniqueKey Photo

Purchase Vendor ID Date Time Amount Purchase 5D 1 D7 UniqueKey

D7 012345678 2012July31 12:05 9.13 2

D7 005566777 2012Aug12 20:20 168.50 1

D7 000555555 2012Sep3 21:21 17.45 2

Figure 7-1 Credit database in z/TPFDF

The database has the following files:  CreditFile CreditFile is an index file and is partitioned by the credit card brand. Within each partition or brand, Creditfile is indexed by the credit card number. Within each CreditFile subfile, each logical record (LREC) represents a single credit card number within the brand (partition) and links to one Purchases file and one SecurityFile file. Figure 7-1 shows a single CreditFile subfile with two LREC 50s representing credit cards 12345678 and 98765432. These credit cards belong to the same brand (partition) and index to the same CreditFile subfile.  Purchases The Purchases file contains authorized users for a given credit card in LREC AuthD3. The UserUniqueKey field is used to associate a specific authorized user with their purchases (PurchaseUniqueKey) and their security data (PinUniqueKey and PhotoUniqueKey). For example, Figure 7-1 shows that John Doe made one purchase on August 12, and Jane Doe made the other two purchases.  SecurityFile The SecurityFile file contains the security data for each authorized user. Figure 7-1 shows PIN records for each authorized user and a photo for John Doe.

Figure 7-2 on page 132 shows the Credit database represented as a data graph. Boxes represent data objects. The items listed in the data objects (CreditCard, Flags, and Limit in Credit[50]) are properties containing data in the data object. Arrows represent the references between data objects. Note that this data graph is a conceptual view of how data in a

Chapter 7. Accessing z/TPFDF databases through SDO 131 z/TPFDF database can be mapped into a data graph and does not represent a data graph that can exist during processing.

Square brackets, [ ], denote that the data objects are part of a many-valued property of its parent object. A many-valued property can also be thought of as a list. For example, the Purchases data object has a many-valued property that contains two AuthD3 data objects.

CreditFile is an index file containing multiple subfiles, so CreditFile is also a many-valued property or list of Root. If you were to read all subfiles, then there would be many instances of CreditFile in the data graph. However, since Figure 7-2 shows only read information for a single credit card, there is only one CreditFile data object in the data graph.

Root

CreditFile[0]

Credit50[0]

CreditCard="12345678" Flags=0 Limit=5000.00

Purchases SecurityFile

AuthD3[0] AuthD3[1] Security56[0] Security56[1]

UserName="John Doe" UserName="Jane Doe" PinUniqueKey=1 PinUniqueKey=2 SSN="xxx-xx-1234" SSN="xxx-xx-6789" Pin=1234 Pin=9876 Address="12 Main St." Address="12 Main St." Flag1=0 Flag1=0 Flag2=0 Flag2=0 UserUniqueKey=1 UserUniqueKey=2 Security5D[0]

PurchaseD7[0] PurchaseD7[1] PurchaseD7[2] PhotoUniqueKey=1

VendorID=012345678 VendorID=005566777 VendorID=000555555 Photo= Date=2012Jul31 Date=2012Aug12 Date=2012Sep3 Time=12:05 Time=20:20 Time=21:21 Amount=9.13 Amount=168.50 Amount=17:45 PurchaseUniqueKey=2 PurchaseUniqueKey=1 PurchaseUniqueKey=2

Figure 7-2 Data graph showing the credit database

7.3.2 Example 1: Displaying purchases above $100.00

In Example 7-1, the application reads all purchases for credit card 12345678 and displays those purchases exceeding $100.00.

Example 7-1 Read and display purchases 1 import java.util.List; 2 import com.ibm.tpf.dfdas.ZTPFDFDAS; 3 import com.ibm.tpf.dfdas.exception.*; 4 import com.ibm.tpf.dfdas.parameters.*; 5 import commonj.sdo.*; 6 public class Example1 {

132 z/TPF Application Modernization using Standard and Open Middleware 7 public static void main(String[] args) { 8 try { 9 // Create the DatabaseParameter for the Data Access Service (DAS) 10 DatabaseParameter databaseParam = 11 new DatabaseParameter( "CREDIT", "BSS" );

12 // Create the AuthorizationModule for the DAS 13 AuthorizationModule authModule = 14 new AuthorizationModule( "TPFTEST", "TPFTEST", "ALLOW", null );

15 // Instantiate the Data Access Service (DAS) 16 ZTPFDFDAS das = new ZTPFDFDAS( "DASConfig.xml", databaseParam, 17 authModule);

18 // Read credit card “12345678” in brand 1 19 String cardstr = new String("12345678"); 20 int cardbrand = 1; 21 PathParameter path = new PathParameter("0", cardstr, 22 TopFile.PARTITION, cardbrand);

23 // Set up parameters for readData call 24 SearchParameter searchKeys = new SearchParameter(); 25 searchKeys.addCondition("CreditFile", "CreditCard", 26 SearchOperator.EQUAL, cardstr);

27 // Set properties to * - return all fields 28 PropertiesParameter properties = new PropertiesParameter("*");

29 // Read the data from the database 30 DataGraph dg = das.readData("Purchases", path, searchKeys, 31 properties); 32 DataObject root = dg.getRootObject(); 33 DataObject creditRecord = 34 root.getDataObject("CreditFile.0").getDataObject("Credit50.0"); 35 DataObject purchaseSubfile = creditRecord.getDataObject("Purchases"); 36 List purchaseList= purchaseSubfile.getList("PurchaseD7"); 37 // Search the purchase list for excessive purchases 38 if (purchaseList.size() > 0) { 39 float purchaseAmount;

40 for(DataObject purchase : purchaseList) { 41 purchaseAmount = purchase.getFloat("Amount");

42 // Display all purchases over $100.00 43 if (purchaseAmount >= 100.00) { 44 System.out.println("$" + purchaseAmount + 45 " was spent at " + 46 purchase.getString("VendorID") + 47 " on " + 48 purchase.getString("Date") + 49 " at " + 50 purchase.getString("Time")); 51 } 52 }

Chapter 7. Accessing z/TPFDF databases through SDO 133 53 } 54 } catch (SDODFException e) { 55 System.out.println("SDODF exception occurred"); 56 e.printStackTrace(); 57 } catch (Exception e) { 58 System.out.println("General exception occurred"); 59 e.printStackTrace(); 60 } 61 } 62 }

In Example 7-1 on page 132:  The first few lines of code in Example 7-1 on page 132 instantiate the z/TPFDF DAS for use by the application.  The DatabaseParameter object (lines 10-11) tells the DAS to connect to the CREDIT database in the BSS subsystem.  The AuthorizationModule object (lines 13-14) provides userID, password, and other authorization information that is provided to the SDO access control routine and SDO security user exit on the z/TPF system.  The DASConfig.xml file on line 16 provides the DAS with all of the WebSphere MQ information necessary to connect to the z/TPF system.  Lines 18-28 create the search and path objects necessary to find and read the Purchase file for credit card 12345678 in brand 1. In this example, CreditFile is a partitioned index where each partition represents the credit card brand and each credit card is indexed into the partition for its brand. The PathParameter object contains the input values, credit card number and brand used find the correct CreditFile for the desired card and brand combination.  Each CreditFile can contain multiple Credit50 data objects because different credit card numbers can result in the same hash. The SearchParameter on lines 24-26 is used to select the desired Credit50 data object in the chosen CreditFile. In this way, only the Credit50 data object for card 12345678 is returned instead of all the Credit50 data objects in CreditFile.  The asterisk passed to the PropertiesParameter object on line 28 is a wildcard that indicates to return all properties for the selected data objects.  The readData method (lines 30-31) reads the data from z/TPFDF and returns the data graph shown in Figure 7-3 on page 135. The remaining code in Example 7-1 on page 132 uses the standard SDO methods getRootObject and getDataObject to get the data graph root and traverse the data graph. The code loops through the purchases and uses the standard SDO methods getFloat and getString to check for and display all purchases exceeding $100.00. In this case, only the purchase on August 12, 2012 for $168.50 will be displayed.

134 z/TPF Application Modernization using Standard and Open Middleware Root

CreditFile[0]

Credit50[0]

CreditCard="12345678" Flags=0 Limit=5000.00

Purchases

PurchaseD7[0] PurchaseD7[1] PurchaseD7[2] AuthD3[0] AuthD3[1]

VendorID=012345678 VendorID=005566777 VendorID=000555555 UserName="John Doe" UserName="Jane Doe" Date=2012Jul31 Date=2012Aug12 Date=2012Sep3 SSN="xxx-xx-1234" SSN="xxx-xx-6789" Time=12:05 Time=20:20 Time=21:21 Address="12 Main St." Address="12 Main St." Amount=9.13 Amount=168.50 Amount=17:45 Flag1=0 Flag1=0 PurchaseUniqueKey=2 PurchaseUniqueKey=1 PurchaseUniqueKey=2 Flag2=0 Flag2=0 UserUniqueKey=1 UserUniqueKey=2

Figure 7-3 Data graph returned by the readData method

7.3.3 Example 2: Adding and updating security information

In Example 7-2, the application reads the security information for credit card 12345678 by an authorized user with the unique key UserUniqueKey 2. The application updates the PIN for that user, adds a photo to the data graph, and then applies those changes back to z/TPFDF.

Example 7-2 Adding and updating security information 1 import java.util.List; 2 import java.io.File; 3 import java.io.InputStream; 4 import java.io.FileInputStream; 5 import java.io.BufferedInputStream; 6 import com.ibm.tpf.dfdas.ZTPFDFDAS; 7 import com.ibm.tpf.dfdas.exception.*; 8 import com.ibm.tpf.dfdas.parameters.*; 9 import commonj.sdo.*; 10 public class Example2 {

11 public static void main(String[] args) { 12 try {

13 // Create the DatabaseParameter for the Data Access Service (DAS) 14 DatabaseParameter databaseParam = 15 new DatabaseParameter( "CREDIT", "BSS" );

16 // Create the AuthorizationModule for the DAS 17 AuthorizationModule authModule = 18 new AuthorizationModule( "TPFTEST", "TPFTEST", "ALLOW", null );

Chapter 7. Accessing z/TPFDF databases through SDO 135 19 // Instantiate the Data Access Service (DAS) 20 ZTPFDFDAS das = new ZTPFDFDAS( "DASConfig.xml", databaseParam, 21 authModule);

22 // Read credit card “12345678” in brand 1 23 String cardstr = new String("12345678"); 24 int cardbrand = 1; 25 PathParameter path = new PathParameter("0", cardstr, 26 TopFile.PARTITION, cardbrand);

27 // Set up parameters for readData call 28 SearchParameter searchKeys = new SearchParameter(); 29 searchKeys.addCondition("CreditFile", "CreditCard", 30 SearchOperator.EQUAL, cardstr); 31 searchKeys.addCondition("SecurityFile", "PinUniqueKey", 32 SearchOperator.EQUAL, 2);

33 // Set Purchases properties to only return Pin and Photo properties 34 PropertiesParameter properties = new PropertiesParameter(); 35 properties.addProperty("SecurityFile", "Pin"); 36 properties.addProperty("SecurityFile", "PinUniqueKey"); 37 properties.addProperty("SecurityFile", "PhotoUniqueKey"); 38 properties.addProperty("SecurityFile", "Photo");

39 // Read the data from the database 40 DataGraph dg = das.readData("SecurityFile", path, searchKeys, 41 properties);

42 DataObject root = dg.getRootObject(); 43 DataObject creditRecord = 44 root.getDataObject("CreditFile.0").getDataObject("Credit50.0"); 45 DataObject securitySubfile = 46 creditRecord.getDataObject("SecurityFile"); 47 DataObject pinRecord = securitySubfile.getDataObject("Security56.0");

48 // Set a new pin 49 pinRecord.setFloat("Pin", 5555);

50 // Read the picture file into a byte array. For this example, 51 // assume the read method reads the entire file in one method call 52 File photoFile = new File("C:\\temp\\photo2.jpg"); 53 byte[] photo = new byte[(int) photoFile.length()]; 54 InputStream inputFile = 55 new BufferedInputStream(new FileInputStream(photoFile)); 56 inputFile.read(photo, 0, photo.length); 57 inputFile.close();

58 // Create a new photo data object and set the key & photo properties 59 DataObject photoRecord = 60 SecuritySubfile.createDataObject("Security5D"); 61 photoRecord.setInt("PhotoUniqueKey", 2); 62 photoRecord.setBytes("Photo", photo);

63 // Apply all changes to z/TPFDF

136 z/TPF Application Modernization using Standard and Open Middleware 64 das.applyChanges(dg);

65 System.out.println("Changes successfully applied."); 66 } catch (SDODFException e) { 67 System.out.println("SDODF exception occurred"); 68 e.printStackTrace(); 69 } catch (Exception e) { 70 System.out.println("General exception occurred"); 71 e.printStackTrace(); 72 } 73 } 74 }

In Example 7-2 on page 135, the z/TPFDF DAS and readData parameter objects are instantiated similar to Example 7-1 on page 132, but with some differences:  The additional search key condition on lines 31-32. This search condition causes readData to return the PIN data object only for authorized user 2. This simplifies later logic because you do not have to search multiple PIN data objects for the correct authorized user.  Another difference is the PropertiesParameters on lines 34-38. To avoid transferring excessive amounts of data, defining specific properties causes readData only returns PIN and photo data objects, leaving out all other data object types in SecurityFile.  Figure 7-4 shows the data graph returned by the readData on lines 40-41. Only the PIN data object for authorized user 2 was returned. A photo data object was not returned because one does not exist in the z/TPFDF database for authorized user 2.

Root

CreditFile[0]

Credit50[0]

CreditCard="12345678"

SecurityFile

Security56[0]

PinUniqueKey=2 Pin=9876

Figure 7-4 Data graph returned by Example 7-2 on page 135

 Starting at the root data object, lines 42-49 traverse the data graph to the PIN data object and set a new PIN for authorized user 2.  Lines 52-62 read a photo file into a byte array and store that byte array into a new photo data object.  Finally, the applyChanges method is called to store the updates in z/TPFDF.

Chapter 7. Accessing z/TPFDF databases through SDO 137 Figure 7-5 shows the data graph after the updates.

Root

CreditFile[0]

Credit50[0]

CreditCard="12345678"

SecurityFile

Security56[0] Security5D[0]

PinUniqueKey=2 PhotoUniqueKey=2 Pin=5555 Photo=

Figure 7-5 Data graph after updates in Example 7-2 on page 135

Figure 7-6 shows the SecurityFile on z/TPFDF after the updates are written through the applyChanges method.

DR14ED: SecurityFile

Security56 PinUniqueKey Pin

56 1 1234

56 2 5555

Security5D PhotoUniqueKey Photo

5D 1

5D 2

Figure 7-6 Updated z/TPFDF SecurityFile Example 7-2 on page 135

138 z/TPF Application Modernization using Standard and Open Middleware 8

Chapter 8. z/TPF SOAP consumer processing

This chapter describes the z/TPF SOAP consumer processing support which permits z/TPF applications to call SOAP-based web services.

This chapter contains the following topics:  8.1, “SOAP consumer support” on page 140  8.2, “SOAP consumer support components” on page 140  8.3, “SOAP consumer message encoding support” on page 143  8.4, “Understanding the z/TPF SOAP consumer APIs” on page 144  8.5, “Setting up SOAP consumer communications handlers” on page 144

© Copyright IBM Corp. 2013. All rights reserved. 139 8.1 SOAP consumer support

z/TPF SOAP consumer support permits z/TPF applications to call SOAP-based web services in a way that is both well-defined and easy to use. SOAP requests are built by the z/TPF system on behalf of the application and sent to the service provider. Service providers return SOAP response messages to the z/TPF system. The SOAP messages are then processed and passed back to the application.

z/TPF SOAP consumer support involves a variety of components in the process of building and sending SOAP requests and receiving and processing SOAP responses. The processing flow of a Web service call depends on several factors:  The service that is being called.  The message exchange pattern (MEP) that is chosen by the application.  The data format.  The communications protocol that is used to transmit the request and response.  Whether each component is able to complete its portion of the processing.  Any special coding in the related user exits.

Figure 8-1 summarizes the components that comprise z/TPF SOAP consumer support.

Web services deployment z/TPF ZWSAT command application table (WSDT) tpf_soap InvokeService() tpf_soapinitHandleExit user exit Web service resource deploy and undeploy SOAP consumer SOAP message handlers user exits handler (optional)

Web service stubs Req Msg SOAP Communications handlers content -or- async request handler Req provider Msg tpf_soapTranslationExit user exit

z/TPF XML APIs

tpf_soapEndExit user exit

Figure 8-1 SOAP consumer support components

8.2 SOAP consumer support components

The following list summarizes the components that comprise z/TPF SOAP consumer support:  z/TPF application

140 z/TPF Application Modernization using Standard and Open Middleware An application that you supply on your z/TPF system that will consume a Web service. The Web service calls one or more of the tpf_soap* functions to build and send a SOAP request message and to receive and process a SOAP response message. The application is responsible for passing the necessary parameter information to the SOAP consumer handler to build the SOAP request message; however, it is not necessary for the application to know the details of how the message itself is actually formatted. When the Web service request has completed successfully, the output parameters are returned to the application. See the z/TPF C/C++ Language Support User's Guide for more information about the tpf_soap* functions.  SOAP consumer handler The SOAP consumer handler is a set of programs that receive control when an application calls one of the tpf_soap* functions. The SOAP consumer handler performs the following tasks: – Performs a lookup operation against the web services deployment table (WSDT) for the Web service that is being called and initializes a SOAP consumer API handle to represent this instance of the service call. – Sets default and user-specified options that control the processing and routing of SOAP request and response messages. – Optionally calls multiple SOAP message handlers to process SOAP headers or a Web service stub for processing the SOAP body, or both. – Calls one of the SOAP consumer communications handlers for routing the SOAP request and receiving the SOAP response from the Web service provider. – Passes the SOAP message to the B2B XML scanner. – Performs the SOAP syntax checks on the SOAP response.  Web services deployment table The WSDT is a subsystem-unique system table in memory that contains information about Web service resources, such as which consumer web services and SOAP message handlers are deployed or undeployed. It is built from the deployment descriptors in the z/TPF file system and is referenced during runtime by the SOAP consumer handler.  Deployment descriptors A deployment descriptor is an XML document that resides in the file system and must conform to the z/TPF base/tpf-ws/schema/tpf_ws_dd_vn.xsd XML Schema file (where n is the version number). Each Web service resource, that is, each consumer Web service and SOAP message handler, must have a deployment descriptor, which defines their attributes and controls their deployment and undeployment to the SOAP runtime.  SOAP consumer initialize handle (tpf_soapInitHandleExit) user exit The tpf_soapInitHandleExit user exit is called by the SOAP consumer handler. This user exit, by default, simply returns without updating the SOAP consumer API handle. You can use this user exit for any user-specific instructions that are appropriate for your system. For example, you might want to override default communications settings to be used when the SOAP request is sent to the service provider.  SOAP message handler A SOAP message handler is a program or collection of programs that is used to implement SOAP features, which can be standard extensions to the SOAP protocol that rely on SOAP message headers (such as WS-Addressing) or customized user-specific extensions, which might not rely on SOAP message headers. A SOAP message handler

Chapter 8. z/TPF SOAP consumer processing 141 provides a single, reusable interface for extending one or more web services and is described by a SOAP message handler deployment descriptor. In addition to the standard extensions to the SOAP protocol, you can develop and deploy customized SOAP message handlers to perform processing that is specific to your installation or environment. For example, if a set of deployed web services requires that every SOAP request for the web services be logged to a logging facility, you can develop a logging message handler and deploy it to the SOAP support. Each consumer Web service deployment descriptor can specify a chain of SOAP message handlers that must be called each time a SOAP request is built for the Web service. SOAP support calls the program that corresponds to each listed SOAP message handler in the order that they are listed in the consumer Web service deployment descriptor. As SOAP responses are received by the SOAP consumer communications handlers, the same SOAP message handlers are called, in the reverse order that they were called when processing the request. This creates a virtual pipeline through which input and output SOAP messages flow.  Web service stubs A Web service stub is a four-character z/TPF program that logically sits between the z/TPF application and a Web service provider. There is one Web service stub for each consumer Web service that is deployed in the z/TPF system. The main tasks of the Web service stub are: – To serialize the service parameter data into a SOAP request message (in XML format) so that it can be transmitted to the service provider. – To deserialize the SOAP response message so that the result can be used by the application. This architecture permits applications to be deployed that will call web services without having to build the applications with knowledge of SOAP or XML or the underlying communications protocols.  SOAP consumer communications handler SOAP consumer communications handlers are responsible for sending SOAP requests to and receiving SOAP responses from service providers. A SOAP consumer communications handler is called by the SOAP consumer handler when the building of a SOAP request is completed and it is ready to be transmitted to the service provider. The SOAP consumer communications handler might communicate to the service provider over the network or it might route the messages internally if the service provider resides in the z/TPF complex. The z/TPF system provides support for three SOAP consumer communications handlers: – The first method takes advantage of z/TPF HTTP client support, which requires that you install the CURL open source library. – The second method uses z/TPF WebSphere MQ support. – The third method is the TPF-to-TPF communication handler that permits you to route requests both locally (in the z/TPF processor without having to go through the network layer) and between two z/TPF processors (going through the network layer). In addition, you can write your own SOAP consumer communications handler to work with any transport mechanism that you are already using.  SOAP consumer asynchronous request handler The SOAP consumer asynchronous request handler is responsible for sending SOAP requests and receiving SOAP responses from service providers when the application has specified that an asynchronous request-reply message exchange pattern (MEP) be used. The SOAP consumer asynchronous request handler creates a new ECB and enters the

142 z/TPF Application Modernization using Standard and Open Middleware user-specified program when a SOAP response is received for a corresponding asynchronous SOAP request.  SOAP consumer translation user exit (tpf_soapTranslationExit) The tpf_soapTranslationExit user exit is called by the SOAP consumer handler when it receives a SOAP response message to perform any required translations so that the SOAP message is in your host encoding.  z/TPF XML APIs The z/TPF XML APIs are a set of functions that are used to construct the SOAP request message and perform actions on the SOAP response message. These APIs are used by the SOAP consumer handler, the SOAP message handlers, and the Web service

8.3 SOAP consumer message encoding support

The consumer Web service deployment descriptor has two elements: ConsumerCodePage and ProviderCodePage. These elements specify the encoding and control the translation of the SOAP request and response messages. When a SOAP request message is received by the SOAP consumer handlers, it is translated from the encoding specified by the ConsumerCodePage element and to the encoding specified by the ProviderCodePage element. The SOAP request message is then sent to the SOAP provider. When a SOAP message is received from a provider, the SOAP consumer handler translates the message from the ProviderCodePage encoding to the ConsumerCodePage encoding.

To perform translations, the SOAP consumer handler first tries to use the tpf_convert* application programming interfaces:  tpf_convert_ebcdic_to_latin1  tpf_convert_ebcdic_to_unicode  tpf_convert_latin1_to_ebcdic  tpf_convert_unicode_to_ebcdic

The tpf_convert* APIs permit the encodings shown in Table 8-1.

Table 8-1 Encodings permitted by the tpf_convert* APIs From To

IBM-1047, IBM-500 Latin 1 (ISO-8859-1), UTF-8, UTF-16BE, UTF-16LE

Latin 1 (ISO-8859-1), UTF-16BE IBM-1047, IBM-500

If the ConsumerCodePage and ProviderCodePage elements are not one of these encoding combinations, the SOAP consumer handler next calls the SOAP consumer translation user exit (tpf_soapTranslationExit). This user exit performs the translation and passes back the translated message with TPF_SOAP_TRANSLATION_DONE. If the user exit cannot perform the translation, it returns TPF_SOAP_TRANSLATE and the SOAP consumer handler calls the iconv API.

Most translations can be performed using the tpf_convert* APIs, the SOAP consumer translation user exit, or the iconv API. However, the B2B scanner is limited in the encodings that it can handle. This does not affect the SOAP consumer handler when the data format is SOAP_XML_DOCUMENT, but it does affect the SOAP_XML_HANDLE and SOAP_PARMS data formats.

Chapter 8. z/TPF SOAP consumer processing 143 8.4 Understanding the z/TPF SOAP consumer APIs

The z/TPF SOAP consumer application programming interfaces permit z/TPF applications to call web services that are on remote platforms or on the z/TPF system itself.

Applications interact with SOAP consumer support by means of a SOAP consumer API handle. The handle is created by calling the tpf_soapInitHandle function and it is initially populated with information about the specified Web service. The information about the service is taken from the corresponding consumer Web service deployment descriptor. (Applications can change options in the handle after it has been created.) The supported SOAP consumer APIs are:  tpf_soapInitHandle  tpf_soapInvokeService  tpf_soapGetOpts  tpf_soapSetOpts  tpf_soapEnd

When an application calls a Web service, it can specify one of three different message exchange patterns (MEPs):  Synchronous request and reply  Asynchronous request and reply  One-way only request

When the application specifies a synchronous call, the tpf_soapInvokeService function does not return to the caller until a response to the SOAP request is received. When the call is asynchronous, the application must provide the four-character program name of a program that will receive control when the response to the SOAP request is received. When the call is either asynchronous or one-way request only, the tpf_soapInvokeService function returns immediately to the caller when the request has been sent; however, it might not wait for the response to be received. The underlying communications protocol determines when the message is considered to be sent; where being sent might not mean that the message has been delivered to the service provider.

8.5 Setting up SOAP consumer communications handlers

Several communications mechanisms are available to the z/TPF SOAP consumer handler for sending service requests and receiving service responses. You must set up and configure the underlying communication protocol before a SOAP consumer communications handler can successfully call a service using a specific communications mechanism.

8.5.1 Using Hypertext Transfer Protocol

The HTTP SOAP consumer communications handler uses z/TPF HTTP client support. This support requires that you have the CURL open source library installed on your z/TPF system.

Get the default HTTP options for sending and receiving messages from the default #define values in the tpf/c_httpc.h header file. The default options are set at the time that the SOAP consumer API handle is initialized by the tpf_soapInitHandle C function. You can override these options using the SOAP consumer initialize handle (tpf_soapInitHandleExit) user exit or through the application itself by using the tpf_soapSetOpts C function.

144 z/TPF Application Modernization using Standard and Open Middleware Additional set up might be required for the HTTP SOAP consumer communications handler to operate successfully. For example, you might need to do one or both of the following tasks:  Create an HTTP client configuration file for SSL if you are establishing a secure HTTP (HTTPS) session.  Create a .netrc file to store user IDs and passwords to be used when establishing HTTP sessions.

Tip: When you use the HTTP SOAP consumer communications handler with an asynchronous request-reply message exchange pattern (MEP), control does not immediately return to the ECB that called the tpf_soapInvokeService C function. The calling ECB is blocked until the response is received by the z/TPF system.

See z/TPF System Generation and z/TPFDF System Generation for more information about using the CONFIG macro to install the CURL open source library.

See z/TPF Transmission Control Protocol/Internet Protocol for more information about using z/TPF HTTP client support.

8.5.2 Using z/TPF WebSphere MQ

The z/TPF WebSphere MQ SOAP consumer communications handler uses z/TPF WebSphere MQ support. The communications handler uses the MQPUT and MQGET C functions and must be used with WebSphere MQ local queue manager support.

Get the default WebSphere MQ options for putting and getting messages from the default #define values in the tpf/cmqc.h header file. The default options are set at the time that the SOAP consumer API handle is initialized by the tpf_soapInitHandle C function. You can override these options by using the SOAP consumer initialize handle (tpf_soapInitHandleExit) user exit or through the application itself by using the tpf_soapSetOpts C function.

There are additional considerations to keep in mind when you use the WebSphere MQ SOAP consumer communications handler. For example:  Before you can deploy a consumer Web service resource, all of the necessary WebSphere MQ resources (for example, the queue manager, local and remote queues, sender and receiver channels, and so on) that are used to deliver SOAP requests and receive SOAP responses must already be defined to the z/TPF system.  If you plan to transmit SOAP requests and responses across secure WebSphere MQ sender and receiver channels using Secure Sockets Layer (SSL), the corresponding channel definitions must have been defined accordingly. There is no mechanism in SOAP consumer support to specify that SOAP requests and responses should be sent across a secure WebSphere MQ.  You must define separate local queues for receiving synchronous and asynchronous SOAP responses. In both cases, these queues are intended for system use only; do not use these queues for general application use.  The SOAP consumer communications handler uses the ReplyToQ and ReplyToQMgr fields in the MQMD structure when sending the SOAP request, to indicate the queue where the SOAP response should be sent. You must ensure that the service provider honors this information when it returns the SOAP response.  The SOAP consumer communications handler uses the MQMO_MATCH_CORREL_ID option when it issues the MQGET C function to get the response message for a given SOAP

Chapter 8. z/TPF SOAP consumer processing 145 request. You must ensure that the service provider returns the SOAP response with the same correlation ID that was set in the SOAP request.  Additional restrictions apply when using the WebSphere MQ SOAP consumer communications handler with an asynchronous request-reply message exchange pattern (MEP): – You must define a WebSphere MQ process that specifies the z/TPF system program that will be given control to handle all asynchronous SOAP replies when you enter the following command: ZMQSC DEFINE PROCESS-ZTPFSOAPC APPLICID-CCMQ – You must define all queues that will receive asynchronous SOAP responses as trigger-every type of queues, where qlname specifies the local name of the queue: ZMQSC DEF QL-qlname TRIGTYPE-EVERY TRIGGER PROCESS-ZTPFSOAPC

See z/TPF Application Programming for more information about z/TPF WebSphere MQ support.

See z/TPF Operations for more information about using the ZMQSC commands.

8.5.3 Using the z/TPF-to-z/TPF transport

The z/TPF-to-z/TPF SOAP consumer communications handler uses a z/TPF-specific TCP/IP-based communications protocol to efficiently send and receive SOAP requests and responses when both the service consumer and provider reside on a z/TPF system. The same communications protocol is used whether the consumer and provider are on the same z/TPF processor, a different z/TPF processor in the same loosely coupled complex, or different z/TPF complexes.

The host name, or the IP address, and the port number of the z/TPF processor to connect to is obtained from the consumer Web service deployment descriptor at the time that the SOAP consumer API handle is initialized by the tpf_soapInitHandle C function. You can override these options using the SOAP consumer initialize handle (tpf_soapInitHandleExit) user exit or through the application itself using the tpf_soapSetOpts C function.

The z/TPF-to-z/TPF SOAP consumer communications handler does not provide a mechanism for establishing a secure connection using SSL or TLS. You must define the Internet daemon listener on each z/TPF processor that will provide a Web service to be consumed by another z/TPF system. To add the z/TPF-to-z/TPF SOAP consumer communications handler daemon to the Internet daemon configuration file (IDCF), enter: ZINET ADD S-ZTPFSOAP PGM-CCWS MODEL-AOR AORLENGTH-20 P-TCP PORT-portnum IP-ipaddr ACT-acttype STATE-state

In the syntax:  portnum A protocol port number to which the Internet daemon listener will bind the Internet server application socket, where portnum is a number in the range 1 to 65535.  ipaddr A local intranet IP address or the value ANY. This type of address is typically assigned by a local network administrator.  acttype Specifies how you want to start the Internet server application:

146 z/TPF Application Modernization using Standard and Open Middleware – Specify OPER to start and stop the daemon manually. – Specify AUTO to start the daemon automatically when the Internet daemon is started.  state The lowest z/TPF system state in which the daemon can be started. Specify 1052, CRAS, or NORM.

8.5.4 Using the z/TPF local transport

The z/TPF local SOAP consumer communications handler permits you to enter the z/TPF SOAP handler, which calls the necessary service provider, using the same application ECB that called the tpf_soapInvokeService C function. This transport is useful when it is necessary to pass information contained directly in the ECB between the service consumer and the service provider. This option is only valid when both the service consumer and service provider are on the same z/TPF processor and in the same subsystem.

Tip: The application cannot specify the asynchronous request-reply message exchange pattern (MEP) when calling a Web service using the z/TPF local transport.

8.5.5 Using a user-specific transport

The user-specific SOAP consumer communications handler permits you to use your own communications protocol for sending and receiving SOAP requests and responses.

Tip: You must provide a timeout and asynchronous processing for user-specific transports.

SOAP support uses the TPF_CALL_BY_NAME C function to call the four-character, user-specific SOAP consumer communications handler program name that is specified in the consumer Web service deployment descriptor for a Web service. Processing is implemented in C shared objects (CSOs). CSOs must have a single entry point as defined in the makefile. The interface to the CSO must match the interface that is defined by the typedef that is used to define user-specific SOAP consumer communications handlers. The format of the typedef is: typedef int (*intfn) (t_soapHandle, t_soapInv *, char *, soapMsg *, soapMsg *);

An explanation of the typedef is:  SOAP consumer communications handlers must return an integer; as defined in the tpf/c_soapc.h header file. Valid values include: – COMMHDLR_RET_SUCCESS – COMMHDLR_RET_ERROR  The first parameter is a SOAP consumer API handle structure, which is defined in the tpf/c_soapc.h header file.  The second parameter is a pointer to a t_soapInv structure, which is defined in the tpf/c_soapc.h header file. It contains information about the request to be sent, including the message exchange pattern (MEP).  The third parameter is a pointer to the user data that is specified in the consumer Web service deployment descriptor for this user-specific transport.  The fourth parameter is a pointer to a soapMsg structure, which is defined in the c_soap.h header file, that represents the SOAP request to be sent.

Chapter 8. z/TPF SOAP consumer processing 147  The fifth parameter is a pointer to a soapMsg structure, which is defined in the c_soap.h header file, that must be filled in by the caller and represents the SOAP response that was received, if applicable.

If an error occurs, the user-specific transport should set the errno value indicate to the application the type of error that occurred. You must set the errno value to ETPFSOAP_USERERR to indicate to the SOAP consumer handler that a transport-specific error occurred.

Use the following APIs to help set up an asynchronous, user-specific transport:  tpf_soapCopySOAPHandleHeap Copies the SOAP consumer API handle from ECB heap to system heap storage so that it can be passed from one ECB to another.  tpf_soapCopySOAPHandleMalloc Copies the SOAP consumer API handle from system heap storage to ECB heap after it is passed from one ECB to another.  tpf_soapProcessAsyncResponse Processes an asynchronous SOAP response and passes the results to the user-specified asynchronous program.

Tip: If an error occurs while a user-specific transport is processing an asynchronous request and a NULL response will be returned to the application, the user-specific transport must set an errno value before calling the tpf_soapProcessAsyncResponse API so that a value of TPF_SOAP_ERROR can be returned to the application.

148 z/TPF Application Modernization using Standard and Open Middleware 9

Chapter 9. Using a z/TPF application as a Web service SOAP consumer

z/TPF applications can act as web service consumers, allowing them to take part in service-oriented architectures (SOA). This chapter describes a sample consumer web service built and enabled on a z/TPF system.

This chapter contains the following topics:  9.1, “Creating a consumer Web service” on page 150  9.2, “Creating a SOAP message handler deployment descriptor” on page 150  9.3, “Creating a consumer Web service deployment descriptor” on page 151  9.4, “Creating or changing an application to use SOAP consumer support ” on page 157  9.5, “Creating a Web service stub” on page 158  9.6, “SOAP message handler response processing for a consumer Web service” on page 167  9.7, “SOAP message handler fault processing for a consumer Web service” on page 167  9.8, “Deploying a SOAP message handler to the z/TPF system” on page 168  9.9, “Deploying a consumer Web service to the z/TPF system” on page 168

© Copyright IBM Corp. 2013. All rights reserved. 149 9.1 Creating a consumer Web service

When an application on your z/TPF system must consume a Web service that resides on either a remote platform or on the z/TPF system itself, you can use the tpf_soap* C functions to simplify calling that Web service.

Before the Web service can be called from the z/TPF application, you must make the Web service known to the z/TPF system. The following tasks describe how to define a Web service that will be consumed by an application on your z/TPF system.

9.2 Creating a SOAP message handler deployment descriptor

SOAP message handler deployment descriptors are specialized XML documents that are used to control the activation of SOAP message handlers to the SOAP runtime.

Deployment descriptors must be named according to the following format ddname.xml, where ddname is the 1- to 256-character, unique name of the file to be placed in the /etc/tpf-ws/ directory of the z/TPF file system.

The format for the z/TPF deployment descriptors is defined in the base/tpf-ws/schema/tpf_ws_dd_vn.xsd XML Schema file (where n is the version number) that is shipped with the z/TPF system.

The elements of the SOAP message handler deployment descriptor must appear in the XML document in the order that they are listed in Example 9-1.

Example 9-1 SOAP message handler deployment descriptor elements 1 2 4 logging 5 CSOL 6 This is a logging message handler that writes log 7 messages to the syslog daemon 8

In Example 9-1:  Line 2 shows the root element of the SOAP message handle deployment descriptor with the namespace for the elements that follow.  Line 3 shows the location of the deployment descriptor schema document in the z/TPF file system.  Line 4 shows the 1- to 32-character, user-specified symbolic name that uniquely identifies the SOAP feature being implemented with this SOAP message handler.  Line 5 shows the 4-character name of the z/TPF program to be activated when a SOAP request is received for a given Web service and the corresponding Web service deployment descriptor for that service has this SOAP message handler listed in its SOAP message handler chain.

150 z/TPF Application Modernization using Standard and Open Middleware  Not shown: element SOAPMessageHandlerURI The 1- to 512-character URI for the SOAP feature being implemented with this SOAP message handler. The URI uniquely identifies this SOAP message handler. It must match the namespace URI used in the SOAP header blocks referenced by this SOAP message handler. This element is optional because message handlers can be defined that do not directly operate on information in SOAP header blocks. However, specify this element if the information is available, to handle the VerifySOAPHeaders element correctly in a provider Web service deployment descriptor. The SOAPMessageHandlerURI element can appear multiple times if this SOAP message handler uses multiple namespace URIs to implement the SOAP feature.  Line 6 shows a 1- to 256-character, meaningful description that you have written of the SOAP message handler that is identified by this SOAP message handler deployment descriptor. This element is optional.

9.3 Creating a consumer Web service deployment descriptor

Consumer Web service deployment descriptors are specialized XML documents that are used to control the activation of consumer web services.

The deployment descriptor must be named according to the following format ddname.xml where ddname is the 1- to 252-character, unique name of the file to be placed in the /etc/tpf-ws/ directory of the z/TPF file system.

The format for z/TPF deployment descriptors is defined in the base/tpf-ws/schema/tpf_ws_dd_vn.xsd XML Schema file (where n is the version number and must be 2 or higher) that is shipped with the z/TPF system. The following elements of the consumer Web service deployment descriptor must appear in the XML document in the same order as they are listed in Example 9-2.

Tip: TPF Toolkit provides tooling to help you create the consumer Web service deployment descriptor.

Example 9-2 Consumer web service deployment descriptor 1 2 6 /CalculatorService 7 QWC1 8 9 10 11 logging 12 13 14 false 15 SOAP1.1 16 SOAP1.2 17 18 add

Chapter 9. Using a z/TPF application as a Web service SOAP consumer 151 19 sub 20 21 This a sample Consumer Web Service that calls a simple 22 Calculator: see CalculatorService.wsdl for more details 23 24 false 25 ibm-1047 26 utf-8 27 28 29 30 31 32 33 34 35 36 127.0.0.1 37 1000 38 39 40 41 42 43 44 http://127.0.0.1/CalculatorService 45 46 47Content-Type: text/xml;charset=utf-8 48 soapAction: "" 49 50 51 52 53 54 CalculatorQueue 55 56 CalculatorAsyncReplyQueue 57 58 59 CalculatorSyncReplyQueue 60 61 62 http://127.0.0.1/CalculatorService 63 64 65 66 67 68 69QWC3

70http://127.0.0.1/calcService 71 72

152 z/TPF Application Modernization using Standard and Open Middleware 73 74

In Example 9-2 on page 151:  Lines 2-4 show the root element of the SOAP consumer Web service deployment descriptor with the namespace for the elements that follow. The namespace universal resource identifier (URI) for this element and for each of the elements that follow must be set to: http://www.ibm.com/xmlns/prod/ztpf/soap Set this namespace URI by using a default namespace for the XML document or by establishing your own namespace prefix.  Line 5 shows the location of the deployment descriptor schema document in the z/TPF file system. This attribute must be present on the root element of the deployment descriptor XML document. Set it to the following value to indicate the location of the deployment descriptor schema document in the z/TPF file system: xsi:schemaLocation="http://www.ibm.com/xmlns/prod/ztpf/soap file:/etc/tpf-ws/schema/tpf_ws_dd_vn.xsd" where n is the version number.  Line 6 shows the 1- to 512-character URI for the Web service that is identified by this deployment descriptor. The URI that is specified must match exactly the value that will be specified for the tpf_soapInvokeService C function call.  Line 7 shows the four-character name of the Web service stub that is called to build the SOAP request message and to process the SOAP response message. Valid characters include A-Z and 0-9.  Line 8 identifies the elements in the Web service deployment descriptor that control the processing of the SOAP consumer handler when a SOAP request or response is being processed for this Web service.  Line 9 shows the list of SOAP message handlers that are to be called when a SOAP request is being built for this Web service. The order that the SOAP message handlers are specified is the order in which they will be called when processing the tpf_soapInvokeService C function call. The same SOAP message handlers will be called in the reverse order when processing a SOAP response message. This element is optional.  Lines 10-13 show the SOAP message handler to be called when processing a SOAP request that is sent to this Web service, or a SOAP response that is received from this Web service. The SOAP message handler name specified is the 1- to 32-character, user-specified symbolic name that uniquely identifies the SOAP message handler to be called. A corresponding SOAP message handler deployment descriptor must exist. The SOAPMessageHandler element can appear multiple times when more than one SOAP message handler is to be called for this Web service. The following attribute can be specified for this element: required. The required attribute indicates whether SOAP header blocks that are referenced by this SOAP message handler are required to appear in SOAP requests and responses for this Web service. The value that is set will be passed to the SOAP message handler program to perform the actual validation: –true Indicates that the corresponding SOAP header blocks must be present in SOAP requests and responses for this Web service.

Chapter 9. Using a z/TPF application as a Web service SOAP consumer 153 – false Indicates that the corresponding SOAP header blocks are optional in SOAP requests and responses for this Web service.  Line 14 shows whether the z/TPF SOAP runtime should verify the SOAP header blocks that appear in SOAP responses received for this Web service. SOAP header blocks are used to implement SOAP features, which extend the basic SOAP standard: –true All SOAP header blocks that are present in SOAP responses received for this Web service are verified. If the z/TPF SOAP runtime detects a SOAP header block that has the mustUnderstand attribute set to "true" (SOAP 1.1 or SOAP 1.2) or "1" (SOAP 1.1), and a corresponding SOAP message handler has not been called to process the SOAP header block, the z/TPF system will treat this SOAP response as not valid and return an error to the calling application.

Tip: The z/TPF SOAP runtime will only verify those SOAP header blocks for which it is determined that the z/TPF system plays the required role, as determined by the actor attribute (SOAP 1.1) or the role attribute (SOAP 1.2) specified on the SOAP header block. The following roles are valid for the z/TPF system:  http://www.w3.org/2003/05/soap-envelope/role/none  http://www.w3.org/2003/05/soap-envelope/role/next  http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver

– false The z/TPF SOAP runtime does not verify any of the SOAP header blocks that are contained in SOAP responses that are received for this Web service. All SOAP message handlers specified in the SOAPMessageHandlerChain are still called by the z/TPF SOAP runtime; however, no verification is performed that all of the necessary SOAP header blocks have been processed. Use this value when there might be SOAP header blocks included in the SOAP responses that are handled by the Web service stub itself, rather than by SOAP message handlers.  Lines 15-16 show the acceptable format of SOAP requests for this Web service. This element is optional, and if not specified, the z/TPF SOAP runtime treats this Web service as though the DEFAULT value had been specified. If the Web service accepts SOAP requests in multiple formats, this element can appear multiple times, unless otherwise stated. If a SOAP response is received for this Web service in an unacceptable format, the z/TPF SOAP runtime will treat this SOAP response as not valid and return an error to the calling application: –DEFAULT Indicates that SOAP requests are expected to be in the format corresponding to the DEFAULT_SOAP_VERSION value that is set in the tpf/c_usoapeq.h header file. When this value is specified, the SOAPVersion element cannot appear more than once. –SOAP1.1 Indicates that a SOAP response for this Web service is acceptable if it is in SOAP 1.1 format. This value and the BP1.1_SSBP1.1 value cannot both be specified for the same Web service. –SOAP1.2 Indicates that a SOAP response for this Web service is acceptable if it is in SOAP 1.2 format.

154 z/TPF Application Modernization using Standard and Open Middleware – BP1.1_SSBP1.1 Indicates that a SOAP request for this Web service is acceptable if it is in SOAP 1.1 format. Also, this instructs the z/TPF SOAP runtime to perform checks on the message to ensure that it is compliant with the Organization for the Advancement of Structured Information Standards (OASIS) Web Services Interoperability (WS-I) Basic Profile 1.1 and the OASIS WS-I Simple Soap Binding Profile 1.1. When a SOAP response is found to be non-compliant, the z/TPF SOAP runtime will treat the SOAP response as not valid and return an error to the calling application. This value and the SOAP1.1 value cannot both be specified for the same Web service.  Lines 18-19 show the 1- to 128-character name of a service method that is exposed as part of this Web service. The Operation element is optional, but can appear multiple times if this Web service exposes multiple methods.  Lines 20-23 show a 1- to 256-character, meaningful description that you have written of the Web service that is identified by this deployment descriptor. This element is optional.  Line 24 shows whether the SOAP consumer handler should automatically try the next transport method in the chain if a transport-specific error is received from an attempt to call a Web service: –true Indicates that the next transport in the chain should be tried. –false Indicates that the tpf_soapInvokeService C function should return to the caller with the transport-specific error and leave it to the application to decide how to proceed.  Line 25 optionally indicates the code page of the SOAP provider Web service. If this option is not present, the DEFAULT_SOAP_PROVIDER_CODEPAGE value in tpf/c_usoapeq.h will be used as the default. If this option or the default are set to any of the following code pages, SOAP consumer processing will translate the XML request and response as needed. If the code page is not set to one of the code pages that follow, SOAP provider processing will first call the UWST user exit so that you can translate the XML message and if the translation is not done, will use iconv to translate the message: –IBM-500 – IBM-1047 – ISO-8859–1 – UTF-8 – UTF-16BE – UTF-16LE  Line 26 optionally indicates the code page of the SOAP consumer application. If this option is not present, the DEFAULT_SOAP_CONSUMER_CODEPAGE value in tpf/c_usoapeq.h will be used as the default. If this option or the default is set to any of the following code pages, SOAP consumer processing will translate the XML request and response as needed. If the code page is not set to one of the code pages that follow, SOAP consumer processing will first call the SOAP consumer translation user exit (tpf_soapTranslationExit) so that you can translate the XML message and if the translation is not done, will use iconv to translate the message: –IBM-500 – IBM-1047 – ISO-8859–1 – UTF-8 – UTF-16BE – UTF-16LE

Chapter 9. Using a z/TPF application as a Web service SOAP consumer 155 The UTF-8 and UTF-16BE translations can only be used with the SOAP_XML_DOCUMENT data format on the tpf_soapInvokeService function; otherwise, the B2B scanner will fail when parsing.  Line 27 shows the list of transports that can be used to reach this Web service. The first transport in the chain is considered the default. You can define one or more transports.  Line 28 shows the transport information that can be used to reach this Web service. The first transport in the chain is considered the default.  Line 30 shows the z/TPF transport information that can be used to reach this Web service. You can specify either TPFLocal or the combination of TPFtoTPFHost and TPFtoTPFPort.  Line 35 shows that the destination Web service resource is on the current z/TPF processor and that the same ECB will be used to call the service.  Line 36 shows the host name or IP address of the z/TPF processor that the Web service resides on.  Line 37 shows the port number that will be used to access the z/TPF Web service. This is an integer in the range of 1 to 65535.  Line 42 shows the HTTP transport information that can be used to reach this Web service.  Line 43-45 shows the uniform resource locator (URL) to use for the specified HTTP client request; the URL must be less than 1024 characters. The URL is a combination of the protocol (HTTP or HTTPS), the host name, and the request uniform resource identifier (URI). Optionally, it can also include the user name, password, and port number. For example, https://user:[email protected]:99 uses a secure HTTP connection with a user name of user and a password of pass; it connects to www.url.com over port 99. This is the accepted format of the url parameter: http[s]://[user[:password]@]host[:port]/[relative uri]  Line 46 shows a list of HTTP headers that are required for this Web service. This element is optional.  Lines 47-48 show the name and value of the header, in the form header: value. The length of header: value is from 1 to 1024 characters.  Line 53 shows the WebSphere MQ transport information that can be used to reach this Web service.  Line 54 shows the queue to send the SOAP message to when using the WebSphere MQ transport to access a Web service.  Line 55-57 shows the queue that the Web service will post the reply message to when using the WebSphere MQ transport to access a Web service using an asynchronous message exchange pattern (MEP).  Line 58-60 shows the queue that the Web service will post the reply message to when using the WebSphere MQ transport to access a Web service using a synchronous message exchange pattern (MEP).  Line 61 shows whether the SOAP consumer handler should include a request format header type 2 (MQRFH2) when sending the SOAP request to the Web service provider. When the MQRFH2 header is supported by the Web service provider, it will be set up by the SOAP consumer handler to include information about the Web service to be called. This element is optional. If a child element is not specified, the SOAP consumer handler will generate an MQRFH2 that specifies only the contentType for the SOAP request.

156 z/TPF Application Modernization using Standard and Open Middleware  Lines 62-63 show the 1- to 512-character URI that is used by the Web service provider to identify the Web service to which the SOAP request is to be delivered. This element is optional.  Line 68 shows the user transport information that can be used to reach this Web service.  Line 69 shows the 4-character name of the z/TPF program that is activated when a user-defined transport is to be used.  Line 70 shows a user-defined string to be passed to the specified user transport program. The length of the string can be from 1 to 1024 characters.

9.4 Creating or changing an application to use SOAP consumer support

After the Web service to be consumed is identified to the z/TPF system, applications can call that Web service using the z/TPF SOAP consumer APIs.

Use the following procedure to write or create an application to consume a Web service: 1. Call the tpf_soapInitHandle function to create a SOAP consumer API handle that represents the Web service that will be called. 2. The SOAP consumer API handle is created with a set of default options based on the settings in the consumer Web service deployment descriptor. You might need to manually change some of the settings in the SOAP consumer API handle by calling the tpf_soapGetOpts and tpf_soapSetOpts C functions. 3. Determine the operation to be called for the intended Web service and gather the necessary parameter data that must be passed to that operation. 4. Call the tpf_soapInvokeService function, passing in the SOAP consumer API handle, the parameters, and a pointer to the location to store the response data if this is using the synchronous message exchange pattern (MEP). 5. Process the response data that is returned from the service provider. 6. If additional operations will be called for the same Web service, the same SOAP consumer API handle can be reused. Repeat steps 2 through 5 if this is the case. 7. Call the tpf_soapEnd function when the last call for this Web service has been made so that all of the resources that are associated with the SOAP consumer API handle can be released.

Example 9-3 shows an application code snippet that illustrates the use of SOAP consumer support.

Example 9-3 Code snippet for consumer t_soapHandle soapH = 0; /* SOAP consumer API handle */ int rc = 0; /* Return code from SOAP APIs */ int *returnValue = NULL; /* Return value from service */ /* invocation (passed from stub) */ t_soapInv invokeParms = {0}; /* Pointer to service invocation */ /* parameters */ int resultValue = 0; /****************************************************************/ /* Initialize a SOAP consumer API handle, specifying the name */ /* of the Web service that will be invoked. */ /****************************************************************/

Chapter 9. Using a z/TPF application as a Web service SOAP consumer 157 soapH = tpf_soapInitHandle ("/CalculatorService"); if (soapH == TPF_SOAP_ERROR) { ... error processing exit (0); } /********************************************/ /* Set the various invocation parameters. */ /********************************************/ invokeParms.timeout = 1; invokeParms.messageExchangePattern = SOAP_CONSUMER_SYNC; invokeParms.timeoutInterval = SOAP_SECOND; /*************************************************************/ /* Copy the operation to perform */ /*************************************************************/ memcpy (invokeParms.operation, “add”, 3); /****************************************************************/ /* Go invoke the /CalculatorService Web service. The expected */ /* output from the stub is a pointer to an integer that */ /* contains the result of the requested operation. */ /****************************************************************/ rc = tpf_soapInvokeService (soapH, &invokeParms, (void **)(char *)&returnValue); if (rc == TPF_SOAP_SUCCESS) { /* Yes, convert return value from string to integer */ resultValue = atoi(returnValue); . . . process return … display calculator response /****************************************************************/ /* If the response was a Fault, output the Fault information. */ /****************************************************************/ } else if (errno == ETPFSOAP_SOAP_FAULT) {

. . . process fault

/****************************************************************/ /* If an error occurred, output the error string. */ /****************************************************************/ } else { optRC = tpf_soapGetOpts (soapH, SOAP_ERROR, 0, (void **)(char *)&secondaryRC); . . . process error } /***********************************************************/ /* End the SOAP handle before exiting. */ /***********************************************************/ tpf_soapEnd (soapH);

9.5 Creating a Web service stub

Web service stubs act as an isolation point for the code that does the following:  Serializes the operation and parameter data into the Body portion of the SOAP request.  Deserializes the return from the service provider from the parsed SOAP response.

158 z/TPF Application Modernization using Standard and Open Middleware This architecture permits you to write an application that calls a Web service without requiring that the application have detailed knowledge about the specific format of the request and response messages, the location of the service provider, or the underlying communications protocol that is used to transport the messages to and from the service provider. SOAP support uses the TPF_CALL_BY_NAME C function to call the four-character Web service stub name that is specified in the consumer Web service deployment descriptor for a Web service. Processing is implemented in C shared objects (CSOs). CSOs must have a single entry point as defined in the makefile. The interface to the CSO must match the interface that is defined by the typedef that is used to define Web service stubs.

The format of the typedef is: typedef int (*intfn)( t_soapHandle, char *, SOAP_WSSTUB_ACT, t_soapParms *, void **);

Example 9-4 shows the use of a web service stub.

Example 9-4 Example for Web service stub #include /* zTPF SOAP support */ #include /* zTPF SOAP consumer support */ #include /* zTPF XML APIs */ #include "qwc1.h" /* Stub-specific header file */

/*********************************************************************/ /* Constants used to represent each operation */ /*********************************************************************/ #define QWC1_ADD 1 #define QWC1_SUB 2

/*********************************************************************/ /* Constants for XML namespaces based on SOAP version */ /*********************************************************************/ #define SOAP11_NAMESPACE "http://schemas.xmlsoap.org/soap/envelope/" #define SOAP12_NAMESPACE "http://www.w3.org/2003/05/soap-envelope" int QWC1 (t_soapHandle soapHandle, char *operation, SOAP_WSSTUB_ACT action, t_soapParms *parms, void **returnValue) { int rc = WSSTUB_RET_CONT; /* Function return code */ int errnoRC = 0; /* Secondary error return */ int operationCode = 0; /* Indicator for operation */ /* being processed */ XMLHandle requestMsg = 0; /* XML Handle for SOAP */ /* request message */ PXMLHandle responseMsg = NULL; /* Pointer to XML Handle for */ /* response or fault message */ /****************************************************************/ /* Set indicator of which operation is being processed for */ /* this Web service. */ /****************************************************************/ if (!strcmp(operation, "add")) {

Chapter 9. Using a z/TPF application as a Web service SOAP consumer 159 operationCode = QWC1_ADD; } else if (!strcmp(operation, "sub")) { operationCode = QWC1_SUB; } else { errnoRC = EINVAL; rc = WSSTUB_RET_ERROR; }

/****************************************************************/ /* Determine the reason why this stub is being called. Call */ /* the correct function to implement the requested action. */ /****************************************************************/ if (rc == WSSTUB_RET_CONT) { switch (action) { case WSSTUB_ACT_REQ_OUTBOUND: /*************************************************/ /* Begin the creation of the SOAP request by */ /* initializing an XML API handle and creating */ /* the SOAP "Envelope" and "Body" elements. */ /*************************************************/ requestMsg = createSOAPenvelope (SOAP1_1);

if (requestMsg != -1) { switch (operationCode) { case QWC1_ADD: rc = qwc1_add_request (soapHandle, requestMsg, parms, returnValue); break; case QWC1_SUB: rc = qwc1_sub_request (soapHandle, requestMsg, parms, returnValue); break; default: errnoRC = EFAULT; rc = WSSTUB_RET_ERROR; break; } } else { errnoRC = EFAULT; rc = WSSTUB_RET_ERROR; }

160 z/TPF Application Modernization using Standard and Open Middleware /*************************************************/ /* If an error occurred and we started to build */ /* the SOAP request, clean it up at this time. */ /*************************************************/ if ((rc == WSSTUB_RET_ERROR) && (requestMsg != -1)) { tpf_xml_terminate_handle (&requestMsg); } else if (rc != WSSTUB_RET_ERROR) { tpf_soapSetOpts (soapHandle, SOAP_REQUESTMSG, 0, &requestMsg); } break; case WSSTUB_ACT_RESP_INBOUND: errnoRC = tpf_soapGetOpts (soapHandle, SOAP_LAST_XML_HANDLE, 0, (void **)(char *)&responseMsg);

if (errnoRC == TPF_SOAP_SUCCESS) { switch (operationCode) { case QWC1_ADD:

rc = qwc1_add_response (soapHandle, *responseMsg, returnValue); break;

case QWC1_SUB:

rc = qwc1_sub_response (soapHandle, *responseMsg, returnValue); break;

default:

errnoRC = EFAULT; rc = WSSTUB_RET_ERROR; break; }

/********************************************/ /* Free the storage that was allocated to */ /* hold the response XML handle value. */ /********************************************/ free (responseMsg); } else { errnoRC = EFAULT;

Chapter 9. Using a z/TPF application as a Web service SOAP consumer 161 rc = WSSTUB_RET_ERROR; }

break; case WSSTUB_ACT_RESP_FAULT:

errnoRC = tpf_soapGetOpts (soapHandle, SOAP_LAST_XML_HANDLE, 0, (void **)(char *)&responseMsg);

if (errnoRC == TPF_SOAP_SUCCESS) { switch (operationCode) { case QWC1_ADD:

rc = qwc1_add_fault (soapHandle, *responseMsg, returnValue); break;

case QWC1_SUB:

rc = qwc1_sub_fault (soapHandle, *responseMsg, returnValue); break;

default:

/**********************************/ /* If an unrecognized operation */ /* was specified, do nothing. We */ /* still must return */ /* WSSTUB_RET_SUCCESS to the SOAP */ /* handler. */ /**********************************/ break; }

/********************************************/ /* Free the storage that was allocated to */ /* hold the response XML handle value. */ /********************************************/ free (responseMsg); }

/*************************************************/ /* For fault processing, if an error occurs, */ /* there is nothing to report. We still must */ /* return WSSTUB_RET_SUCCESS to the SOAP handler.*/ /*************************************************/ rc = WSSTUB_RET_SUCCESS;

break;

162 z/TPF Application Modernization using Standard and Open Middleware default:

errnoRC = EINVAL; rc = WSSTUB_RET_ERROR; break;

} /* end of switch statement */

} /* end if rc == WSSTUB_RET_CONT */

/****************************************************************/ /* Return to tpf_soapInvokeService processing. If an error */ /* occurred, set a stub-specific error code in the SOAP handle */ /* to be passed back to the calling application. */ /****************************************************************/ if ((rc == WSSTUB_RET_ERROR) && (errnoRC != 0)) { { tpf_soapSetOpts (soapHandle, SOAP_ERROR, 0, &errnoRC); }

return (rc);

} /* end of function QWC1 ( ) */

/*********************************************************************/ /* This is an internal use function that begins the creation of a */ /* SOAP request message. It will create an XML API handle that */ /* represents the SOAP requests and will add both the "Envelope" and */ /* "Body" elements as appropriate. The request will be built using */ /* either the SOAP 1.1 or the SOAP 1.2 namespace as requested by the */ /* caller. */ /* */ /* Upon return, the XML API handle's position pointer is set to point*/ /* after the "Body" element. */ /*********************************************************************/ XMLHandle createSOAPenvelope (SOAP_VERSION version) { XMLHandle requestHandle = 0; /* SOAP request XML handle */ int rc = 0; /* XML API return code */ char *soapNamespace = NULL; /* SOAP version namespace */ char *soapPrefix = NULL; /* SOAP namespace prefix */

/****************************************************************/ /* Setup the correct XML namespace to use based on the SOAP */ /* version that was requested. Although the value of the */ /* namespace prefix really does not have relevance, for */ /* ease of readability, the conventional prefix used for each */ /* SOAP version (e.g., "SOAP-ENV" or "env") is used. */ /****************************************************************/ if (version == SOAP1_1) { soapNamespace = SOAP11_NAMESPACE;

Chapter 9. Using a z/TPF application as a Web service SOAP consumer 163 soapPrefix = "SOAP-ENV"; } else if (version == SOAP1_2) { soapNamespace = SOAP12_NAMESPACE; soapPrefix = "env"; } else { rc = -1; }

/****************************************************************/ /* Initialize the XML API handle for a new XML structure. */ /****************************************************************/ if (rc == 0) { rc = tpf_xml_initialize_handle (&requestHandle, NO_PARSER, NULL); }

/****************************************************************/ /* Create the XML declaration statement. */ /****************************************************************/ if (rc == 0) { rc = tpf_xml_createXMLstructure (requestHandle, "1.0", TPF_CCSID_UTF8, TPF_CSNAME_UTF8, STANDALONE_NOT_USED, 0); }

/****************************************************************/ /* Append the "Envelope" element to the SOAP response. */ /****************************************************************/ if (rc == 0) { rc = tpf_xml_appendElement (requestHandle, NULL, "Envelope", NULL, soapPrefix, soapNamespace, 0); }

/*******************************************************************/ /* Append the "Body" element to the SOAP response. */ /*******************************************************************/ if (rc == 0) { rc = tpf_xml_appendElement (requestHandle, "Envelope", "Body", NULL, soapPrefix, soapNamespace, 0); } /*******************************************************************/ /* If an error occurred, terminate the handle if one was created */ /* and return an error to the caller. */ /*******************************************************************/ if (rc != 0)

164 z/TPF Application Modernization using Standard and Open Middleware { if (requestHandle != 0) { tpf_xml_terminate_handle (&requestHandle); } requestHandle = -1; }

return (requestHandle);

/* end of function createSOAPenvelope( ) */

An explanation of the typedef is:  Web service stubs must return an integer. Valid values include WSSTUB_RET_CONT, WSSTUB_RET_ERROR, and WSSTUB_RET_SUCCESS, as defined in the c_soap.h header file.  The first parameter is a SOAP consumer API handle structure, which is defined in the c_soap.h header file.  The second parameter is a pointer to a NULL-terminated string that indicates the name of the operation to be called for this Web service.  The third parameter is an integer. It represents an action code (defined by the SOAP_WSSTUB_ACT enumeration in the c_soap.h header file) that identifies whether the Web service stub is being called to create a SOAP request (WSSTUB_ACT_REQ_OUTBOUND), process a SOAP response (WSSTUB_ACT_RESP_INBOUND), or process a SOAP fault (WSSTUB_ACT_RESP_FAULT).  The fourth parameter is a pointer to an array of t_soapParms structures. The array is defined in the tpf/c_soapc.h header file. Each entry in the array represents a single instance of parameter data that is being passed to the Web service. This parameter is only valid when the third parameter is set to WSSTUB_ACT_REQ_OUTBOUND; otherwise, this parameter is set to NULL.  The fifth parameter is a pointer to a void pointer. It is filled in with the return value that is passed back to the calling application. The exact format of the data that is passed back to the application is implementation-dependent and is not referenced by SOAP consumer support. Typically, this parameter is only meaningful when the third parameter is set to WSSTUB_ACT_RESP_INBOUND or WSSTUB_ACT_RESP_FAULT. However, if the Web service stub calls the underlying service locally or bypasses further processing of the request, the Web service stub can use this parameter to set up information to return to the calling application.  The intfn pointer is a pointer to the function type and is passed to the TPF_CALL_BY_NAME macro. With this pointer and the four-character program name that implements the Web service stub, the TPF_CALL_BY_NAME macro returns a pointer to the function value that calls an enter with return (ENTRC linkage) to the specified program.

The t_soapHandle structure contains information about the Web service that will be called, including a tpfSoapMsgCtx structure. Additional information includes:  An XMLHandle structure that represents the SOAP request message that is to be built and is called requestMsg.  An XMLHandle structure that represents the SOAP response message that was received and is called responseMsg.

Chapter 9. Using a z/TPF application as a Web service SOAP consumer 165  A t_consumerTransportChain structure that represents the communications transport options that are available for routing the request and receiving the response message.  You must use the z/TPF XML APIs to create the SOAP request and to help in accessing the data in the SOAP response. TPF Toolkit provides tooling to help you create the Web service stub.

9.5.1 Web service stub request processing

The SOAP consumer handler calls the request part of a Web service stub to create the Envelope and Body portions of the SOAP request.

When you have coded the required function in this part, be sure that the return call back to the SOAP consumer handler contains one of the following return codes:  WSSTUB_RET_CONT Use this return when processing is successful and the SOAP message handler chain should be called. If there is no SOAP message handler chain, the SOAP consumer handler sends the completed request to the service provider. Use the tpf_soapSetOpts C function with the SOAP_REQUESTMSG option to set the XMLHandle that contains the request message to be sent.  WSSTUB_RET_ERROR Use this return when processing is not successful and an error return code should be returned to the original application without further processing of the request. You can set a more detailed, user-specific error code by using the SOAP_ERROR option for the tpf_soapSetOpts C function.  WSSTUB_RET_SUCCESS Use this return when the Web service stub has either called the service (that is, called the underlying function directly on the z/TPF system) or for some other reason it is not necessary to continue to call the service. Control is returned immediately to the application by the SOAP consumer handler without further processing of the request.

9.5.2 Web service stub response processing

The SOAP consumer handler calls the response part of a Web service stub when it receives a SOAP response message to a SOAP request that was previously sent. The Web service stub is called after the SOAP message handlers that are defined in the SOAP message handler chain for the given Web service; it processes the Body portion of the SOAP response.

When you have coded the required function in this part, be sure that the return call back to the SOAP consumer handler contains one of the following return codes:  WSSTUB_RET_SUCCESS Use this return when processing is successful. The return data, if there is any, has been extracted and is ready to be returned to the original application.  WSSTUB_RET_ERROR Use this return when processing is unsuccessful and an error return code should be returned to the original application. A more detailed, user-specific error code can be set by using the tpf_soapSetOpts C function with the SOAP_ERROR option.

166 z/TPF Application Modernization using Standard and Open Middleware 9.5.3 Web service stub fault processing

The SOAP consumer handler calls the fault part of a Web service stub when it receives a SOAP fault in response to a SOAP request that was previously sent. The Web service stub is called after the SOAP message handlers that are defined in the SOAP message handler chain for the given Web service; it processes the Body portion of the SOAP fault.

When you have coded the required function in this part, be sure that the return call back to the SOAP consumer handler contains the following return code: WSSTUB_RET_SUCCESS

Use this return when processing is complete.

9.6 SOAP message handler response processing for a consumer Web service

The SOAP consumer handler calls the consumer response part of a SOAP message handler when it receives a SOAP response for a Web service that included this SOAP message handler in its deployment descriptor.

The SOAP message handler chain that is defined in the consumer Web service deployment descriptor lists the SOAP message handlers in the order that they are processed for the request flow. For response processing, the order is reversed.

After you code the required function in this part, be sure that the return call back to the SOAP consumer handler contains one of the following return codes:  MSGHDLR_RET_CONT Use this return when processing is successful and the next SOAP message handler in the chain should be called. If there are no more SOAP message handlers in the chain, the Web service stub is called.  MSGHDLR_RET_ERROR Use this return when processing is unsuccessful and an error return code should be returned to the original application. The SOAP consumer handler calls SOAP message handler error return processing for each of the SOAP message handlers, even though the SOAP message handler chain does not continue processing. The tpfSoapMsgCtx structure contains a web services deployment table (WSDT) structure (WSDT_entry wsdt_ent) that contains fields that you can access to determine whether the processing for the SOAP message handlers was performed, and whether it was successful.

9.7 SOAP message handler fault processing for a consumer Web service

The SOAP consumer handler calls the consumer fault part of a SOAP message handler when it receives a SOAP fault for a Web service that included this SOAP message handler in its deployment descriptor.

The SOAP message handler chain that is defined in the consumer Web service deployment descriptor lists the SOAP message handlers in the order that they are processed for a request flow. For fault processing, the order is reversed.

Chapter 9. Using a z/TPF application as a Web service SOAP consumer 167 After you code the required function in this part, be sure that the return call back to the SOAP consumer handler contains one of the following return codes:  MSGHDLR_RET_CONT Use this return to indicate that the next SOAP message handler in the chain should be called. When there are no more SOAP message handlers in the chain, the Web service stub is called.  MSGHDLR_RET_ERROR Use this return when processing is unsuccessful and an error return code should be returned to the original application. The SOAP consumer handler calls SOAP message handler error return processing for each of the SOAP message handlers, even though the SOAP message handler chain does not continue processing. The tpfSoapMsgCtx structure contains a web services deployment table (WSDT) structure (WSDT_entry wsdt_ent) that contains fields that you can access to determine whether the processing for the SOAP message handlers was performed, and whether it was successful.

9.8 Deploying a SOAP message handler to the z/TPF system

To deploy a SOAP message handler to the z/TPF system: 1. Load and activate the SOAP message handler program. Because this is simply another application, follow the same procedure for loading and activating any application. 2. If there is one, load and activate the SOAP message handler extension program; again, because this is simply another application, follow the same procedure for loading and activating any application. 3. Load the SOAP message handler deployment descriptor by FTPing the file in binary form to the z/TPF file system under the /etc/tpf-ws/ directory. 4. Activate the SOAP message handler deployment descriptor by entering the ZWSAT command with the DEPLOY parameter to deploy the SOAP message handler.

The TPF Toolkit provides an action to load the deployment descriptor file using FTP to send the file to the z/TPF file system. TPF Toolkit can also activate the deployment descriptor by using the DEPLOY action for a selected Web service resource shown in the Remote Systems Explorer (RSE). Undeploy a SOAP message handler on the z/TPF system.

There are two options for undeploying a SOAP message handler on the z/TPF system:  Enter the ZWSAT command with the UNDEPLOY parameter to mark the resource as unavailable.  Enter the ZWSAT command with the REMOVE parameter to remove the entry for the resource from the web services deployment table (WSDT).

The undeploy action and the remove action have essentially the same effect when performed for a SOAP message handler.

9.9 Deploying a consumer Web service to the z/TPF system

To deploy a consumer Web service to the z/TPF system: 1. Follow your normal procedure for loading and activating the application.

168 z/TPF Application Modernization using Standard and Open Middleware 2. Load and activate the Web service stub. Because this is simply another application, follow the same procedure for loading and activating any application. 3. Load the consumer Web service deployment descriptor by FTPing the file in binary form to the z/TPF file system under the /etc/tpf-ws/ directory. 4. Activate the consumer Web service deployment descriptor by entering the ZWSAT command with the DEPLOY parameter to deploy the Web service.

The TPF Toolkit provides an action to load the deployment descriptor file using FTP to send the file to the z/TPF file system. TPF Toolkit can also activate the deployment descriptor by using the DEPLOY action for a selected Web service resource shown in the Remote Systems Explorer (RSE).

Chapter 9. Using a z/TPF application as a Web service SOAP consumer 169 170 z/TPF Application Modernization using Standard and Open Middleware Part 4

Part 4 SOA consumer

Part 4 of this book describes the use of WebSphere Operational Decision Management in converting an existing function to use business rules. It also describes how to use business event processing for the z/TPF system.

This part contains the following chapters:  Chapter 10, “Using WebSphere Operational Decision Management to apply business rules” on page 173  Chapter 11, “Business event processing” on page 191

© Copyright IBM Corp. 2013. All rights reserved. 171 172 z/TPF Application Modernization using Standard and Open Middleware 10

Chapter 10. Using WebSphere Operational Decision Management to apply business rules

Business rules encapsulate organizational policies and the operational decisions associated with those policies. By externalizing functions used to enact these policies and decisions into business rules, we provide the ability for these functions to be deployed, monitored, and maintained separately from the core application code. This in turn allows greater business agility by reducing the amount of time and effort needed to update the rules governing those decisions.

This chapter discusses how to convert an existing function to use business rules. This will provide an idea of what is involved in changing a TPF C application to use business rules. Although some TPF applications are written in assembler, the procedure remains mostly the same.

This chapter contains the following topics:  10.1, “The sample application” on page 174  10.2, “Converting the application to use business rules” on page 174

© Copyright IBM Corp. 2013. All rights reserved. 173 10.1 The sample application

To illustrate the use of business rules, we reference the miniloan application that is in the WebSphere Operational Decision Management tutorials. If you have WebSphere Operational Decision Management installed, you can find this tutorial in the Windows start menu under Getting Started tutorials, and then select Decision Server Rules. This sample is also used in the WebSphere Operational Decision Management Information Center tutorial at:

http://pic.dhe.ibm.com/infocenter/dmanager/v8r0/topic/com.ibm.wodm.dserver.rules.g s/topics/wodm_dserver_rules_gs.html

It might be worthwhile to familiarize yourself with that tutorial to understand more about how business rules are created.

In the tutorial, the miniloan application is a simple web-based application that performs loan approvals. Since the criteria for a loan approval can often change, having the loan approval logic implemented through business rules allows the loan approval policy to be changed quickly and easily. In this chapter, the miniloan application is a z/TPF application with the loan approval functionality found within the z/TPF function: int ValidateLoan(struct Borrower *, struct Loan *);

10.2 Converting the application to use business rules

The conversion process to enable the application to use business rules will be done with the following steps:  Step 1. Creating an XML data representations of the parameters  Step 2. Generating the programming artifacts from XML  Step 3. Creating the Java execution object model (XOM)  Step 4. Creating a Ruleset (Rule Project)  Step 5. Deploy the RuleApp and Rule Request Server  Step 6. Create a RuleApp descriptor for z/TPF  Step 7. Deploy XML descriptors to z/TPF  Step 8. Update z/TPF application to call the business rule

10.2.1 Step 1. Creating an XML data representations of the parameters

To be used by business rules, data structures must be transformed into a Java class. This is done by creating a data model object definition for the Borrower structure in a .tdm.xml file. An XML description allows the tpfObjectConverter utility to create a common macro, C header, and Java class for the data structure. The XML schema defining the format of the data model descriptor is found in:

base/tpf-fdes/schema/tpf_object_model_schema.xsd

For this example, the Borrower structure is defined, as shown in Example 10-1.

Example 10-1 Borrower structure struct Borrower { char name[50]; int creditScore; unsigned int yearlyIncome;

174 z/TPF Application Modernization using Standard and Open Middleware };

After converting this structure to XML, the object definition for Borrower can look like Example 10-2. The TPF Toolkit also includes a wizard to help you create the XML file (see Appendix D, “TPF Toolkit wizards for WebSphere Operational Decision Management and Business Events” on page 427).

Example 10-2 Borrower object definition

There are two items to note in this XML representation:  An optional Java package name of miniloan is used as part of the Java class name.  Java does not support unsigned data types, so yearlyIncome was changed to a signed integer. A long type could have been used instead.

The Loan structure has the definition shown in Example 10-3.

Example 10-3 Loan structure struct Loan { int amount; int duration; double yearlyInterestRate; int yearlyRepayment; boolean approved; char *messages[10]; };

The Loan structure will be a bit more difficult to represent since it uses an array of pointers for the messages. Java does not use pointers so these will need to be either a fixed length string of characters or an array of varying strings. Without wanting to be too restrictive in the length of messages nor create a large array that can potentially be empty, the messages pointer array can be changed to an array of varying strings. With this conversion in mind, the object definition could look like Example 10-4.

Example 10-4 Loan object definition

Chapter 10. Using WebSphere Operational Decision Management to apply business rules 175 The Loan and Borrower object definitions can be placed in the same data model descriptor (.tdm.xml) file or separate files. When creating the object definitions, the object names, Borrower and Loan, must be unique across all data model descriptor files.

For simplicity, both object definitions can be created in one file called miniloan.tdm.xml and use an ObjectList name of miniloan. For naming conventions, it is best to have the name of the file match the ObjectList name used in the data model descriptor.

10.2.2 Step 2. Generating the programming artifacts from XML

Now that the .tdm.xml file is created, the tpfObjectConverter utility can be invoked directly or the data model descriptor can be added to the usr.cntl_tdmdd file to manage through bldtpf. To make it easier to generate these files in the future, update usr.cntl_tdmdd with the following entry: samples/miniloan.tdm.xml;USR;samples/include;samples/macro;samples/xom;samples;bas e/oco/lib/Rule_Request_Server.ear;

This allows the data model descriptor file (sample/miniloan.tdm.xml) to be used to generate C headers in the samples/include directory, macros in samples/macro directory, Java files in samples/xom directory, and an updated rule request server .ear file in the samples directory.

Run the following command: bldtpf –tdmdd base/cntl/usr.cntl_tdmdd

The miniloan/Borrower.java and miniloan/Loan.java files are in the samples/xom directory. This directory is what will be used in the WebSphere Operational Decision Management Rule Designer to create a Java execution object model (XOM) in a Java project. The project can then be imported to a rule project to create business rules.

10.2.3 Step 3. Creating the Java execution object model (XOM)

The execution object model (XOM) defines the objects, data and methods, that can be used for business rule execution. This XOM also forms the basis for the business object model (BOM) used in authoring rules. In order for the generated java files to be used by the business rules, it is necessary to incorporate them into a Java XOM.

176 z/TPF Application Modernization using Standard and Open Middleware To create a Java XOM: 1. In Rule Designer, select File  New  Project  Java Project to open the window shown in Figure 10-1. Type in sample-xom as the project name, and click Next.

Figure 10-1 Creating a new Java project, Step 1

Chapter 10. Using WebSphere Operational Decision Management to apply business rules 177 2. In the next window (Figure 10-2), click Link additional source to open the Link Source dialog, where you will include the generated Java files created through the tpfObjectConverter utility.

Figure 10-2 Creating a new Java project, Step 2

178 z/TPF Application Modernization using Standard and Open Middleware 3. The linux directory is mounted as H: so that the Rule Designer can find the generated files in the \samples\xom subdirectory. Enter the folder name in the Link Source dialog, as shown in Figure 10-3and click Finish.

Figure 10-3 Creating a new Java project, Step 3

Chapter 10. Using WebSphere Operational Decision Management to apply business rules 179 4. The additional source directory containing the generated Java files is included, as shown in Figure 10-4. Select the Libraries tab.

Figure 10-4 Creating a new Java project, Step 4

180 z/TPF Application Modernization using Standard and Open Middleware 5. The generated Java files contain some rules engine specific code, so the JAR needs to be included for the rules engine. One way to do this is to click Add Library, and then select the IBM WODM Library. Another specific way to include the needed JAR is to click Add Variable. In this example, click Add Variable as shown in Figure 10-5.

Figure 10-5 Creating a new Java project, Step 5

Chapter 10. Using WebSphere Operational Decision Management to apply business rules 181 6. The rules engine JAR is found under the ILOG_BR_STUDIO_HOME directory. In the New Variable Classpath Entry window, select ILOG_BR_STUDIO_HOME, and then click Extend, as shown in Figure 10-6.

Figure 10-6 Creating a new Java project, Step 6

7. In the Variable Extension window, select jrules-engine.jar, as shown in Figure 10-7 and click OK.

Figure 10-7 Creating a new Java project, Step 7

182 z/TPF Application Modernization using Standard and Open Middleware 8. The jrules-engine.jar file is now included in the build path for this XOM, as shown in Figure 10-8. Click Finish.

Figure 10-8 Creating a new Java project, Step 8

You now have everything you need to start work on creating business rules in a Rule Project.

10.2.4 Step 4. Creating a Ruleset (Rule Project)

A ruleset is an executable collection of rules that is used to implement a business policy or decision. Use the following procedure to create a ruleset: 1. In the Rule Designer, select File  New  Project  Rule Project. 2. Select the Projects tab, and then select the sample-xom project to add the Java XOM created previously to the list of required projects (Figure 10-9 on page 184).

Chapter 10. Using WebSphere Operational Decision Management to apply business rules 183 Figure 10-9 Creating a new rule project, Step 1

3. Click Finish. The rule project map, shown in Figure 10-10 is opened in the workspace as a result of creating a Rule Project. The map gives a step by step overview as well as links for creating RuleApps and rule sets in the Rule Project. The steps covered in detail in this chapter are in the Design step of the rule project. The other three steps, as shown in Figure 10-10, are IBM Orchestrate®, Author, Deploy and Integrate with an optional Review step.

Figure 10-10 Rule project map

4. Create a BOM Entry from this XOM:

184 z/TPF Application Modernization using Standard and Open Middleware a. Click the newly created Rule project folder, and select New  BOM Entry. b. Give the BOM Entry a name, and follow the dialog box to create a BOM entry from the sample-xom project. 5. After the BOM Entry is created, view the entry, and click Create add and remove methods for all attributes of type Collection, as shown in Figure 10-11.

Figure 10-11 BOM entry

Since the messages member of the Loan object is an array, it is implemented in Java as a Collection. Creating add and remove methods will make dealing with the messages member easier. 6. Continuing the design, the next step is to define the ruleset parameters. The borrower and loan parameters are defined, as shown in Figure 10-12 on page 186.

Chapter 10. Using WebSphere Operational Decision Management to apply business rules 185 Figure 10-12 Properties for the miniloan rules

These parameter definitions will be needed when creating the RuleApp descriptor later.

This completes the steps in the first task of the tutorial to design the rule project. The rest of the steps for the tutorial should be followed next to create the business rules for the miniloan application. We will not cover those steps in detail, but you can start with Task 2 in the tutorial at the following website: http://pic.dhe.ibm.com/infocenter/dmanager/v8r0/topic/com.ibm.wodm.dserver.rules.g s/topics/tut_dserver_gs_orchestrate_lsn.html

10.2.5 Step 5. Deploy the RuleApp and Rule Request Server

After the ruleset is created, it must be added to a RuleApp to be deployed to a Rule Execution Server (RES). In Rule Designer, this is done by creating and using a RuleApp Project. After the RuleApp is deployed to the RES to include the newly created ruleset, the Rule Request Server must also be updated on WebSphere Application Server to include the new XOM. To do this, the Rule_Request_Server.ear file that was updated in Step 2 using the tpfObjectConverter utility will be needed by the WebSphere Application Server administrator to perform the update.

The definitions for where the Rule Request Server has been deployed are kept in the endpoint group descriptor file (.ept.xml). It is important to keep the deployment of the RuleApp and the updates to the Rule Request Server synchronized across all servers as defined by an endpoint group. This file does not need to be updated with each new ruleapp or ruleset creation and is dependent on information from your local WebSphere Application Server administrator. There is a wizard in the TPF Toolkit to help in creating this file (see

186 z/TPF Application Modernization using Standard and Open Middleware “Endpoint group descriptor file wizards” on page 434). More information about endpoint group descriptors is in the z/TPF Product Information Center at: http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztpfdf .doc_put.cur/gtpd4/dd_endptgrp.html

10.2.6 Step 6. Create a RuleApp descriptor for z/TPF

For z/TPF to locate and use a ruleset, a ruleapp descriptor is needed. The RuleApp descriptor describes what RuleApp the ruleset was deployed with as well as which servers it was deployed to (endpoint group). All the information needed is in the RES console ruleset view, as shown in Figure 10-13.

Figure 10-13 Rule Execution Server console

If you do not have access to the RES console, the information can also be found by examining the Rule and RuleApp Projects in the Rule Designer. The main piece of information to locate is the ruleset path. As shown in Figure 10-13, it is /miniloanruleapp/1.0/miniloanrules/1.0. The version numbers are created during ruleapp deployment, and can change as updates are made. This ruleset has two parameters of borrower and loan of XOM Type miniloan.Borrower and miniloan.Loan, respectively. The borrower parameter is strictly for input while the loan parameter is both an input and output parameter.

A RuleApp descriptor is defined in files of type .ilr.xml. The XML schema for RuleApp descriptors is found in base/tpf-fdes/schema/tpf_ruleapp_schema.xsd. The TPF Toolkit includes a wizard to help in creating the XML file (see “RuleApp descriptor file wizard” on page 437). Using the information shown in Figure 10-13, the ruleapp entry looks like Example 10-5.

Example 10-5 RuleApp entry example

Chapter 10. Using WebSphere Operational Decision Management to apply business rules 187

One difference between the ruleapp information and the ruleapp entry is the type information. Back in 10.2.1, “Step 1. Creating an XML data representations of the parameters” on page 174, the following object entries were created: Object name="Loan" jName="miniloan.Loan" Object name="Borrower" jName="miniloan.Borrower"

The type that is included here is not the XOM type, but the data model object name. The data model descriptor includes the XOM type as well as other information needed to package and unpackage the objects for the ruleset request.

10.2.7 Step 7. Deploy XML descriptors to z/TPF

At this point, there are three XML files that can be deployed to z/TPF:  A data model descriptor (file type .tdm.xml)  An endpoint group descriptor (file type .ept.xml)  A RuleApp descriptor (file type .ilr.xml).

These files must get loaded to the /sys/tpf_pbfiles/tpf-fdes directory on z/TPF to be properly recognized. Use the z/TPF loader to load these files.

After these files are loaded, the ruleset is still not immediately available until the RuleApp descriptor has been deployed to z/TPF. Deployment on z/TPF is managed through the ZMDES command.

After issuing ZMDES with the DEPLOY parameter for the RuleApp descriptor file, the ruleapp and all rulesets contained therein will be usable on z/TPF. The other two XML descriptors do not need a ZMDES command to activate them because they are automatically deployed (made available) when loaded.

10.2.8 Step 8. Update z/TPF application to call the business rule

With everything in place, the ValidateLoan function can be changed to call the business rule as shown in Example 10-6.

Example 10-6 ValidateLoan function int ValidateLoan(struct Borrower *borrower, struct Loan **loan) { struct ilr_list parm_list[2]; int rc; parm_list[0].ilr_pname = “borrower”; parm_list[0].ilr_pinput = borrower; parm_list[1].ilr_pname = “loan”; parm_list[1].ilr_pinput = *loan; rc = tpf_ilrExecuteRuleset(“/miniloanruleapp/miniloanrules”, parm_list, NULL, NULL); if ((rc == ILR_OK) && (parm_list[1].ilr_poutput)) {

188 z/TPF Application Modernization using Standard and Open Middleware free(*loan); *loan = parm_list[1].ilr_poutput; } return rc; }

The loan parameter is both an input and output parameter so additional malloc storage is acquired for the output data. Since the size of the storage area can change with varying strings, we replaced the old structure instead of copying over it.

Any future changes can now be made without changing a single line of code on z/TPF.

Chapter 10. Using WebSphere Operational Decision Management to apply business rules 189 190 z/TPF Application Modernization using Standard and Open Middleware 11

Chapter 11. Business event processing

Business event processing is based on the interaction between an event source, a process, and a consumer. Use the information provided in this chapter to understand business event processing for the z/TPF system.

This chapter contains the following topics:  11.1, “Business event processing” on page 192  11.2, “z/TPF and business event processing” on page 193  11.3, “How z/TPF event processing works” on page 194  11.4, “Business event deployment descriptors” on page 195  11.5, “Common deployment” on page 198  11.6, “Enrichment program” on page 199  11.7, “Business event dispatch queue” on page 200  11.8, “Business event data format” on page 201  11.9, “Business event processing monitor” on page 208  11.10, “Enabling business event processing” on page 208  11.11, “Using business event processing” on page 209  11.12, “Removing a loosely coupled processor” on page 216

© Copyright IBM Corp. 2013. All rights reserved. 191 11.1 Business event processing

A business event is anything that happens that is significant to a system. Business event processing is the capture, enrichment, formatting, and emission of events, the subsequent routing and any further processing of emitted events (sometimes in combination with other events), and the consumption of the processed events. Business events can be produced throughout a business enterprise.

At the edges of the enterprise, business events can be detected by sensors. In the enterprise network, business events can be produced when business processes start and complete or fail. The activity of the enterprise and its business can be monitored and changed as a result of events.

11.1.1 Business event processing architecture

A business event processing architecture is based on interactions between three components: an event source, an event processor, and an event consumer, as shown in Figure 11-1.

Event source

Systems Events

Business Event processor processes Events Actions Event consumer Sensors

Applications Perform operations Consume, react to events on events • Alerts Other • Trigger workflow • Automated actions

Figure 11-1 Business event processing architecture

In Figure 11-1:  Event source An event source emits business events into the business event processing system. Examples of event sources are simple Radio Frequency Identification (RFID) sensors and actuators, business flows, applications, and system components.  Event processor Some ways that events can be processed include: – Enriching a single business event in a simple manner; for example, adding a time stamp to the event data. Processing of this kind is sometimes referred to as simple event processing. – Adding information about the source of the event.

192 z/TPF Application Modernization using Standard and Open Middleware – Processing multiple single business events from multiple event sources against event patterns to produce a new derived or compound event. Processing of this kind is sometimes referred to as complex event processing. The processed event is then available to an event consumer.  Event consumer The event consumer reacts to the business event. An event consumer can be as simple as updating a database or business dashboard, or as complex as required, carrying out new business processing as a result of the event. Here are some examples of ways events can be consumed: – Updating a business dashboard – Updating a database – Interacting with Web 2.0 components to dynamically update web pages – Sending an alert by using email or SMS based on event data – Putting event data on a message queue – Starting a new piece of application work Business event processing for z/TPF provides capture, enrichment, formatting, and routing of single business events, which enables the z/TPF system to act as a source of simple business events. However, these events can be consumed by a complex business event processing engine where they can be combined with events from other sources in addition to the z/TPF system.

11.1.2 How business event processing can help your business

You can use business event processing to enhance governance for standards compliance, and to monitor business processing. Business event processing enables detection of business situations, providing early and intelligent insight to assist you in making timely and effective business decisions.

Business event processing can help your business in these ways:  Getting the correct information at the correct level of detail to the correct person at the correct time.  Facilitating quick observation of exceptional business behavior and notifying the appropriate people.  Diagnosing problems based on symptoms and resolving them.  Providing data for dashboard display of real-time business service availability.  Monitoring the health of a system.

11.2 z/TPF and business event processing

You can specify, capture, and transmit business events from the z/TPF system. When a specified event occurs, the z/TPF system collects the data, and then formats and emits the data to the event consumers through a dispatch adapter. The z/TPF system provides the following support for simple business events:  You can use the tpf_bev_signal function anywhere in a z/TPF application to signal that a business event occurred.  You can use an enrichment program to gather additional information about the event to be passed on to the event consumers.

Chapter 11. Business event processing 193  You can choose to emit business events through WebSphere MQ or you can write your own custom dispatch adapter.  You can choose to format business event data with the Common Base Event format or you can write your own custom format program. The Common Base Event format is an event format that is used across many products, including WebSphere Business Monitor.

11.3 How z/TPF event processing works

Figure 11-2 provides an overview of the flow of event processing with z/TPF.

z/TPF Application

Capture Point

tpf_bev_signal

Enrichment Event signal program

Enrichment complete tpf_bev_signal enrichment complete

Business event dispatch queue

Common Base Event data format Custom WebSphere MQ dispatch adapter dispatch adapter Custom data format

Event Event consumer consumer

Figure 11-2 z/TPF event processing

The following steps outline how an event is processed in z/TPF: 1. An application calls the tpf_bev_signal function to indicate that a business event occurred. 2. If there is an enrichment program defined for the event, control passes to the enrichment program. The enrichment program gathers additional information for the event, and then calls the tpf_bev_signal_enrichment_complete function to continue processing the event.

194 z/TPF Application Modernization using Standard and Open Middleware If an enrichment program is not defined for the event, the tpf_bev_signal function processes the event. 3. The event information is added to the business event dispatch queue. The business event dispatch queue is a processor unique, local, WebSphere MQ queue. The purpose of the dispatch queue is to disassociate the business event call from the transmission of the business event to the consumers. 4. The dispatch queue handler removes the event information from the business event dispatch queue and sends the information to the business event dispatch adapter that is defined for that business event. A business event dispatch adapter is a transport mechanism that sends the business event data from the z/TPF system to the event consumers. 5. Each business event dispatch adapter formats the event data and transmits the data to the event consumers. You can format the business event data based on a standard data format or a custom data format. The data format is specified in the business event dispatch adapter specification. Before the data is sent to the specified data format program, business event processing performs an interim data transform.

11.4 Business event deployment descriptors

Business event deployment descriptors are specialized XML files that contain the characteristics for each business event. These XML files must be deployed on the z/TPF system before they can be used.

The z/TPF system uses a mechanism called common deployment to make deployment descriptors available for use.

Table 11-1 summarizes the business event deployment descriptors.

Table 11-1 Business event deployment descriptors Deployment File Name Description descriptor

Business event ddname.evspec.xml Defines a business event. specification

Business event ddname.evda.xml Defines the data format and dispatch adapter transmission mechanism for the specification business event data.

11.4.1 Business event specification

The business event specification is used to define a business event. This specialized XML file contains the name of the event, a definition of the data that is being provided for the event, and a list of business event dispatch adapters that are used to transmit the data to the event consumers.

The TPF Toolkit provides a wizard to help you create the deployment descriptors for use by WebSphere Operational Decision Management and by Business Events. The wizard is described in Appendix D, “TPF Toolkit wizards for WebSphere Operational Decision Management and Business Events” on page 427.

Chapter 11. Business event processing 195 You can use the business event specification as input to the tpfObjectConverter utility. Use the tpfObjectConverter utility to create programming artifacts such as C header files, assembler DSECTs, and Java classes.

Requirements and restrictions The following list contains requirements and restrictions for business even specifications:  Name the business event specification descriptor file according to the format ddname.evspec.xml, where ddname is the 1- to 250-character unique name. Ensure that this deployment descriptor is loaded to the /sys/tpf_pbfiles/tpf-fdes/ directory on the z/TPF system with the E-type loader or the image loader.  The format of the business event specification is defined in the tpf-evspec.xsd schema file that is shipped with the z/TPF system. Ensure that the schema file is loaded to the /sys/tpf_pbfiles/tpf-fdes/schema/ directory on the z/TPF system.  Common deployment uses the following information to locate the in-memory structures for this deployment descriptor: –Key element value – Type BEVEVESTYPE –Version Not used

Example Example 11-1 shows a sample business event specification describing a flight delay.

Example 11-1 Sample business event specification FlightDelay A flight departure was delayed. V1 QFLE CustomAdapter

196 z/TPF Application Modernization using Standard and Open Middleware

11.4.2 Business event dispatch adapter specification

The business event dispatch adapter specification defines the data format and transmission mechanism for the business event data. One business event dispatch adapter is used in the transmission of event data to one event consumer.

Requirements and restrictions The following list contains requirements and restrictions for business event dispatcher specifications:  Name the business event dispatch adapter specification descriptor file according to the format ddname.evda.xml, where ddname is the 1- to 250-character unique name. Ensure that this deployment descriptor is loaded to the /sys/tpf_pbfiles/tpf-fdes/ directory on the z/TPF system with the E-type loader or the image loader.  The format of the business event dispatch adapter specification is defined in the tpf-evda.xsd schema file that is shipped with the z/TPF system. Ensure that the schema file is loaded to the /sys/tpf_pbfiles/tpf-fdes/schema/ directory on the z/TPF system.  Common deployment uses the following information to locate the in-memory structures for this deployment descriptor: –Key element value – Type BEVEVDATYPE –Version Not used

Example Example 11-2 shows a sample business event dispatch adapter specification. The data that is associated with this business event is formatted based on the Common Base Event specification and transmitted with WebSphere MQ.

Example 11-2 Sample business event dispatch adapter specification: Common Base Event and WebSphere MQ Operations

Chapter 11. Business event processing 197 Inform operations about changes in flight status. SEND.QUEUE.TO.OPERATIONS CBE

Example 11-3 shows a sample business event dispatch adapter specification. The data that is associated with this business event is formatted based on a custom format program and transmitted by using a custom adapter program.

Example 11-3 Sample business event dispatch adapter specification = custom format and adapter Operations Inform operations about changes in flight status.

11.5 Common deployment

You must load your deployment descriptors to the z/TPF system with the E-type loader or the image loader. After the descriptors are loaded to the system, you can use the ZMDES command to deploy and undeploy the descriptor files.

Some aspects of deployment are unique to the type of deployment descriptor. For example, parsing the file and creating the in-memory structure that holds the results of the parsing. However, there are several tasks that must occur during deployment that are common to each type of deployment descriptor. In particular, common deployment handles the following tasks related to deploying a deployment descriptor on the z/TPF system:  Validates that the file exists.  Maintains the status of which files are deployed.  Deploys the file again after an IPL.

198 z/TPF Application Modernization using Standard and Open Middleware  Provides a mechanism to find the in-memory structure.  Handles any changes to the file; that is, handles a file in a loadset that was activated or deactivated.

Deployment descriptors that use common deployment are available for use in all z/TPF states. During restart, common deployment initializes the memory structures and calls function-unique processing for each deployment descriptor. Additionally, if a file is deployed, the in-memory structure is marked as available for use.

11.5.1 Common deployment rules and conventions

Deployment descriptors that use common deployment must conform to the following rules:  Deployment descriptors must have a unique file extension that identifies the function or application. Use the format .function_unique_name.xml, where function_unique_name is the unique name for the deployment descriptor associated with your function or application. For example, the unique file extension for a business event specification is .evspec.xml.  Deployment descriptors are program base unique files that must be loaded to the /sys/tpf_pbfiles/tpf-fdes/ directory on the z/TPF system with the E-type loader or the image loader.  Deployment descriptors contain information that is used by common deployment to find the in-memory structures, that is, a key, a type, and optionally, a version. The key, type, and version are generated by the function-unique processing that creates the in-memory structures and are based on the contents of the deployment descriptor. Each deployment descriptor must contain a unique combination of key, type, and version. The type generally correlates to the file extension of the descriptor; therefore, each descriptor file with the same type must contain a unique combination of key and version. For deployment descriptors that do not use a version (for example, .evspec.xml descriptor for business event processing), each descriptor file must contain a unique key. You can use the E-type loader to load and activate new versions of deployment descriptors. These new versions have the same file name and must have the same key, type, and version as the previously loaded versions.

IBM uses the following conventions for schemas that define deployment descriptors that use common deployment:  Include the unique file extension of the deployment descriptor in the schema name and use the following naming convention: tpf-function_unique_name.xsd, where function_unique_name is the unique name for the deployment descriptor.  IBM-delivered schemas are placed on Linux in relative directory base/tpf-fdes/schema/.  Schema files must be loaded to the /sys/tpf_pbfiles/tpf-fdes/schema/ directory on the z/TPF system.

11.6 Enrichment program

The enrichment program is an optional, user-written program. You can use an enrichment program to gather additional information about the business event that you want to pass along to the event consumer.

Chapter 11. Business event processing 199 To use an enrichment program, specify the four-character program name in the business event specification. If an enrichment program is defined for an event, the tpf_bev_signal function calls the specified program. When enrichment processing is completed, the enrichment program must call the tpf_bev_signal_enrichment_complete function to continue processing the event. If the enrichment program obtains any storage, such as ECB heap, the program is responsible for releasing that storage. When the enrichment program returns control to the tpf_bev_signal function, the function returns control to the program that signaled the event without any additional processing.

The enrichment process and the ECB that signaled the event can run asynchronously. The enrichment program can create another ECB to handle the enrichment process and that ECB can call the tpf_bev_signal_enrichment_complete function to complete processing the event.

If there is no enrichment program defined for an event, the tpf_bev_signal function processes the event.

11.7 Business event dispatch queue

The business event dispatch queue is a processor unique, local, WebSphere MQ queue. The purpose of the dispatch queue is to disassociate the business event call from the transmission of the business event to the consumers.

The ECB that processes the business event call adds the event to the business event dispatch queue and then returns control to the application that issued the event call. A separate ECB removes the business event information from the dispatch queue, formats the data, and transmits the information to the event consumer.

When the event information is added to the dispatch queue, the WebSphere MQ persistence, expiry time, and priority properties are obtained from the business event specification.

The system default business event dispatch queue is an unordered queue, that is, an event that occurs after another event can be transmitted to the same event consumer first. Processing on the default queue can use multiple ECBs. You can use the ZBEVF command to set the number of ECBs that can be used to process events on the default queue.

The business event specification provides an optional element () that you can use to specify a user-defined dispatch queue. You can use this user-defined dispatch queue to ensure that the order of the events is maintained. Because processing from a user-defined dispatch queue uses only one ECB, events are always removed from the dispatch queue in the same order that they are placed on the queue. If you use a user-defined business eventdispatch queue, the characteristics of the queue must be the same as the default queue.

11.7.1 Queue depth considerations

If the number of items on the business event dispatch queue becomes too large, it can be an indication of a problem. Either the process to remove the items from the queue stopped working or the process cannot keep up with the number requests.

You can set a queue depth warning level to monitor the size of the dispatch queue by entering the ZBEVF command with the QDEPTHWARN parameter specified. If the number of messages on the dispatch queue exceeds the value that you specify for the QDEPTHWARN parameter, a warning message is issued.

200 z/TPF Application Modernization using Standard and Open Middleware You also can specify a maximum depth for the business event dispatch queue by using the MAXDEPTH parameter on the ZMQSC DEFINE QL command. The default value of 0 specifies that there is no maximum queue length. You can prevent the size of the dispatch queue from growing too large by setting the MAXDEPTH parameter to a value other than 0. When event information is added to the dispatch queue, if the number of items on the queue exceeds the specified MAXDEPTH value, an error is returned to the application and the tpf_bev_signal request is rejected. Additionally, an error count for that event is incremented.

The dispatch queue grows when business events are added to the queue faster than the dispatch queue handler can remove the items from the queue. You can expect temporary spikes when the size of the dispatch queue grows. If the spikes are temporary, the business event dispatch queue can process the events. Set the maximum depth large enough so that errors are not received when temporary spikes occur. To determine what value to use for the MAXDEPTH, you must understand the expected rate of events per second and set the maximum depth to handle a specific number of seconds.

If you need to change the maximum depth for a dispatch queue after the initial definition, enter the ZMQSC ALTER QL command with the MAXDEPTH parameter specified.

11.7.2 Message length considerations

You might need to tune the maximum message length for the dispatch queue. Set the maximum message length based on data collections and your knowledge of the size of the event information that is passed with the business event processing APIs. You can change the maximum message length by entering the ZMQSC ALTER QL command with the MAXMSGL parameter specified.

11.7.3 Loosely coupled considerations

Business event processing is program base unique. Additionally, you can deploy the business event deployment descriptors on a processor by processor basis. Therefore, you can have a loosely coupled complex with one processor that uses business event processing and another processor that does not use business event processing. However, when you remove a processor from the loosely coupled complex, you must move any messages that are on the dispatch queue to another active processor in the complex.

11.7.4 Dispatch adapters

A business event dispatch adapter is a transport mechanism that sends the business event data from the z/TPF system to the event consumer. You can choose to use WebSphere MQ as the transport mechanism or you can create your own custom adapter program to handle the event transmission. Define the type of dispatch adapter that you want to use in the business event dispatch adapter specification

11.8 Business event data format

You can format the business event data based on a standard data format or a custom data format. The data format is specified in the business event dispatch adapter specification. Before the data is sent to the specified data format program, business event processing performs an interim data transform.

Chapter 11. Business event processing 201 Business event processing retrieves the event data from the tpf_bev_signal or tpf_bev_signal_enrichment_complete function and puts the raw data on the dispatch queue. When the event information is pulled from the business event dispatch queue, the raw data is transformed into the tpf_bev_info structure. This structure is passed to the data format routine for additional formatting before the data is transmitted to the event consumer.

Business event processing supports the standard Common Base Event data format. If you want to use a different data format, you can specify a user-written custom data format program to format the event data.

11.8.1 tpf_bev_info

Defines the structure of the data that is passed to all data format routines, including the custom data format program. The tpf_bev_info structure is defined in the tpf/ibev.h header file.

Structure format Example 11-4 shows the structure format for tpf_bev_info.

Example 11-4 Structure format for tpf_bev_info struct tpf_bev_info { char *event_name; char *event_intercept_name; struct timeval event_time; int event_info_item_count; struct tpf_bev_info_item event_info_item[]; }; struct tpf_bev_info_item { char *item_name; int item_dataType; int item_dataSize; TPF_BEV_ITEM_DATA item_data; };

Parameters The parameters for tpf_bev_info are:  event_name A pointer to the event name that was specified on the tpf_bev_signal function call.  event_intercept_name A pointer to the intercept name that was specified on the tpf_bev_signal function call.  event_time A timeval structure value that indicates the time that the data was placed on the business event dispatch queue. This value is obtained from the gettimeofday function.  event_info_count The number of event_info_item pointers in this structure.  event_info_item A tpf_bev_info_item array that contains the data to be passed for this event.  item_name

202 z/TPF Application Modernization using Standard and Open Middleware A pointer to a null-terminated character string that contains the name of this data field. This name is defined in the element structure of the business event specification.  item_dataType The data type for this data, as defined in enumeration type bev_dataType.  item_dataSize The number of bytes for the data field specified by the item_data parameter.  item_data The data for this business event, as defined by the TPF_BEV_ITEM_DATA typedef.

11.8.2 Common Base Event format

Common Base Event formatted business events on the z/TPF system are formatted based on the Common Base Event Specification V1.0.1.

Common Base Event formatted data consists of the following sections:  Data that is standard for all Common Base Event XML files. The standard data is defined by the commonbaseevent1_0_1.xsd schema file that is shipped with the z/TPF system.  Data that is unique to all Common Base Event XML files that are created by z/TPF business event processing. The z/TPF unique data is defined by the ibm_tpf_cbe_static.xsd schema file that is shipped with the z/TPF system.  Data that is associated with your specific business event. You must provide the schema file for the event data.

There is a unique XML name space for each section of the Common Base Event formatted output.

11.8.3 Element and attribute details

The tables in this section describe the default fields that are populated by z/TPF business event processing when you specify the Common Base Event data format. To specify the Common Base Event format, set the element in the business event dispatch adapter specification to CBE. You can use an enrichment program and the Common Base Event data user exit (ubev_cbeData_user_exit) to populate additional fields or to change the default values that are populated by the z/TPF system.

Table 11-2 on page 204 contains a description of the common base event element format.

Chapter 11. Business event processing 203 Table 11-2 Common Base Event format elements Element name Description Element usage

The root element for a Common  One element Base Event formatted XML file.  Multiple attributes For information about the  Multiple subelements attributes for this element, see Table 11-3. For information about the sub elements for this element, see Table 11-4 on page 204.

Table 11-3 contains a description of the common base even attributes

Table 11-3 attributes

Attribute name Description

Version A 1- to 16-character version for the Common Base Event specification. This value must be consistent with the version specified in the schema header.

creationTime The date and time that the business event occurred. This value is defined by the dateTime schema data type. The time is represented as hours, minutes, seconds, and microseconds.

Table 11-4 contains a description of the common base event elements.

Table 11-4 elements

Element name Description Element usage

Identifies the component that is affected by the business  One element event. For information about the attributes for this element, see  Multiple attributes Table 11-5.

The type of situation that caused the business event.  One element For information about the attribute for this element, see  One attribute Table 11-6 on page 205. For information about the sub element  One subelement for this element, see Table 11-7 on page 205.

The event information for a particular z/TPF business  One element event. For information about the sub elements for this element,  Multiple subelements see Table 11-8 on page 206.

204 z/TPF Application Modernization using Standard and Open Middleware Table 11-5 contains a description of the attributes for the element.

Table 11-5 attributes

Attribute name Description

component A 1- to 256-character name that specifies the logical identify of a component. For example, the name of an application or subsystem. For all z/TPF Common Base Event formatted files, the value for the component attribute is the z/TPF enterprise name. The z/TPF enterprise name is defined by the ENTERPRISE parameter on the CONFIG macro during in the system initialization process (SIP).

componentIdType A 1- to 32-character name that specifies the type for the component. For all z/TPF Common Base Event formatted files, the value for the componentIdType attribute is SystemName.

componentType A 1- to 512-character name that is used to characterize all instances of a particular component. For all z/TPF Common Base Event formatted files, the value for the componentType attribute is zTPF Enterprise.

Location A 1- to 256-character name that specifies the physical address of the component. For all z/TPF Common Base Event formatted files, the value for the location attribute is obtained from the gethostname function.

locationType A 1- to 32-character name that specifies the format and meaning of the value of the location attribute. For all z/TPF Common Base Event formatted files, the value for the locationType attribute is HostName.

subComponent A 1- to 512-character name that specifies an additional distinction for the component attribute. For all z/TPF Common Base Event formatted files, the value for the subComponent attribute is set to the intercept name that generated the event.

Table 11-6 contains a description of the attributes for the element.

Table 11-6 attributes

Attribute name Description

categoryName A 1- to 64-character name that specifies the type of situation that caused the event. For all z/TPF Common Base Event formatted files, the default value for the categoryName attribute is OtherSituation.

Table 11-7 contains a description of elements.

Table 11-7 elements

Element name Description Element usage

The type of situation that caused the event.  One element For information about the attribute for this element, see  One attribute Table 11-9 on page 206. For information about the sub  One subelement element for this element, see Table 11-10 on page 206.

Table 11-8 on page 206 contains a description of the elements of the element.

Chapter 11. Business event processing 205 Table 11-8 elements

Element name Description Element usage

Contains information that is static for all business events that  One element occur on a z/TPF system. For information about the elements for  Multiple subelements this element, see Table 11-11.

Contains the data that is generated for a particular business  One element event based on the business event specification  Undefined number of for that event. The XML name space for these elements is based subelements on the and elements defined in the business event specification. The relative name space is value_of_esUserTag/value_of_esName. The base name space for the data is http://www.ibm.com/xmlns/prod/ ztpf/events/. For information about the elements for this element, see Table 11-12.

Table 11-9 contains a description of the attributes of the element.

Table 11-9 attributes

Attribute name Description

reasoningScope A 1- to 64-character name that specifies the scope of the impact of the event. For all z/TPF Common Base Event formatted files, the default value for the reasoningScope attribute is INTERNAL.

Table 11-10 contains a description of the elements.

Table 11-10 elements

Element name Description Element usage

element with any additional data by using the Common Base Event data user exit (ubev_cbeData_user_exit).

Table 11-11 contains a description of the elements.

Table 11-11 elements

Element name Description Element usage

The 1- to 16-character name of this business event. One element

The UserTag that was passed for this business event. One element

The date and time that the business event occurred. This One element value is defined by the dateTime schema data type. The time is represented as hours, minutes, seconds, and microseconds.

event.

206 z/TPF Application Modernization using Standard and Open Middleware The name of the subsystem user that this business event was generated on. One element

Table 11-12 contains a description of the element.

Table 11-12 elements

Element name Description Element usage

The data structure for the business event. The name and Undefined number of value for the sub elements is defined by elements the business event specification.

11.8.4 Example

Example 11-5 shows a sample z/TPF business event in Common Base Event format.

Example 11-5 Sample z/TPF business event in Common Base Event format flightDelay V1 2011-11-28T15:04:44.609931 ABCD SSUNAME1 4567 47 JFK LAX 2011-11-28T14:00 2011-11-28T16:30

Chapter 11. Business event processing 207 11.9 Business event processing monitor

A business event processing monitor runs every second to monitor business event activity and the dispatch queue.

The business event processing monitor program handles the following tasks:  Verifies that ECBs that are pulling items from the dispatch queue are active. If an ECB is not active, the monitor program cleans up the control entries.  Determines the number of errors that occurred during the last minute. This value is calculated once a minute. For business events, an error is recognized when an event cannot be added to the dispatch queue. For business event dispatch adapters, an error is recognized when the data format program or the data transport program return an error.  If an error occurred in the last minute, the processing monitor sends a message that indicates what error occurred and the number of errors.  Checks the number of messages on each dispatch queue once a minute. If the number is larger than the QDEPTHWARN value that was specified on the ZBEVF command, the monitor sends a message to the console with the number of messages on the dispatch queue.

11.10 Enabling business event processing

Before you can use business events, you must configure and enable business event processing on the z/TPF system. Use the following steps to do this. 1. Define the business event processing format-2 global records: a. ZGLBL GLOBAL DEFINE IBEVCNTL LOC-64BIT PROT-YES IS-NO b. ZGLBL GLOBAL INITIALIZE IBEVCNTL SOURCE-ZERO SIZE-800 2. If there is not already a local WebSphere MQ queue manager defined on your z/TPF system, define the queue manager by entering the following command: ZMQSC DEFINE QMGR 3. Define the system default business event dispatch queue: a. ZMQSC DEFINE PROCESS-IBEV.DISPATCH.PROCESS APPLICID-BEVQ b. ZMQSC DEFINE QL-IBEV.UNORDERED.DISPATCH.QUEUE TRIGTYPE-FIRST PROCESS-IBEV.DISPATCH.PROCESS TRIGGER MAXDEPTH-0 4. Optional: Define a user-defined dispatch queue by entering the following command, where qlname is the local queue name: ZMQSC DEFINE QL-qlname TRIGTYPE-FIRST PROCESS-IBEV.DISPATCH.PROCESS TRIGGER MAXDEPTH-0 5. Enable business event processing on this processor by entering the following command: ZBEVF ENABLE This command enables business event processing only on the processor that you enter the command from. You must enter this command on each processor in a loosely coupled complex. 6. Optional: Set the number of ECBs that are used to remove items from the dispatch queue by entering the following command, where maxecbval is the maximum number of ECBs: ZBEVF SET MAXECBS-maxecbval

208 z/TPF Application Modernization using Standard and Open Middleware 7. Optional: Set the number of business events that can be called by one ECB in one second. Enter the following command, where maxeventval is the maximum number of events: ZBEVF SET MAXEVENTS-maxeventval 8. Optional: Set the number of errors that can occur for a business event dispatch adapter in a 1 minute time period before the dispatch adapter is undeployed. Enter the following command, where maxerrval is the maximum number of errors: ZBEVF SET MAXERRORS-maxerrval 9. Optional: Set the queue depth warning level for dispatch queues. Enter the following command, where qdepthval is the warning level: ZBEVF SET QDEPTHWARN-qdepthval

11.11 Using business event processing

This section describes how to define the business event deployment descriptors and update your applications to use business event processing on the z/TPF system.

11.11.1 Before you begin

Before you begin, ensure that the following two requirements are met:  Ensure that business event processing is enabled. For more information, see 11.10, “Enabling business event processing” on page 208.  Ensure that the z/TPF system is in NORM state.

11.11.2 Processing business events

Complete the following steps for each business event: 1. Create a business event specification and the associated business event dispatch adapter specification. You can use a text editor or the TPF Toolkit to create these XML files. Example 11-6 shows a sample business event specification for the case where an airline flight is delayed.

Example 11-6 Sample business event specification - flight delayed FlightDelay A flight departure was delayed. V1 QFLE

Chapter 11. Business event processing 209 Operations

Example 11-7 shows a sample business event dispatch adapter specification. The data that is associated with this business event is formatted with a custom format program and transmitted using a custom adapter program.

Example 11-7 Sample business event dispatch adapter specification Operations Inform operations about changes in flight status.

2. Update your application program to call the tpf_bev_signal function to indicate that this business event occurred. In the Example 11-8 on page 211, the name of the event to be processed is specified by the first parameter. The event name must be defined with the element in a business event specification that is deployed on the z/TPF system. The size of the data and a pointer to a structure containing the data for the event are passed in the second and third parameters. The fourth parameter is a pointer to a null-terminated 1- to 512-character string that can be used to identify the capture point of this business event. This pointer is passed to the enrichment program, if there is one defined, and to the event consumer. The enrichment program or the event consumer (or both) can perform different actions that are based on the value of the interceptName parameter.

210 z/TPF Application Modernization using Standard and Open Middleware Example 11-8 Application call to the tpf_bev_signal function bevSignalReturn = tpf_bev_signal(“FlightDelay”, // Signal the event sizeof(delayInfo), // Pass the structure (void *)&delayInfo, “Weather_Delay”); // Delay due to weather switch(bevSignalReturn) { case BEV_SIGNAL_NORMAL: sprintf(msg, "EVENT %s SIGNALED\n", event); wtopc_insert_header(&msg_hdr, "QFLY", 2, 'I', WTOPC_SYS_TIME); wtopc(msg, WTOPC_EBROUT, WTOPC_NO_CHAIN, &msg_hdr); break; case BEV_SIGNAL_NOT_ENABLED: sprintf(msg, "EVENTING IS NOT ENABLED\n"); wtopc_insert_header(&msg_hdr, "QFLY", 3, 'E', WTOPC_SYS_TIME); wtopc(msg, WTOPC_EBROUT, WTOPC_NO_CHAIN, &msg_hdr); break; case BEV_SIGNAL_EVENT_NOT_DEPLOYED: sprintf(msg, "EVENT %s IS NOT DEPLOYED\n", event); wtopc_insert_header(&msg_hdr, "QFLY", 4, 'E', WTOPC_SYS_TIME); wtopc(msg, WTOPC_EBROUT, WTOPC_NO_CHAIN, &msg_hdr); break; case BEV_SIGNAL_ENRICHMENT_PROG_NOT_AVAIL: sprintf(msg, "ENRICHMENT PROGRAM IS NOT AVAILABLE\n"); wtopc_insert_header(&msg_hdr, "QFLY", 5, 'E', WTOPC_SYS_TIME); wtopc(msg, WTOPC_EBROUT, WTOPC_NO_CHAIN, &msg_hdr); break; case BEV_SIGNAL_NOT_NORM_STATE: sprintf(msg, "SYSTEM IS NOT IN NORM STATE\n"); wtopc_insert_header(&msg_hdr, "QFLY", 6, 'E', WTOPC_SYS_TIME); wtopc(msg, WTOPC_EBROUT, WTOPC_NO_CHAIN, &msg_hdr); break; case BEV_SIGNAL_INVALID_PARAMETER: sprintf(msg, " interceptName PARAMETER IS NOT VALID\n"); wtopc_insert_header(&msg_hdr, "QFLY", 7, 'E', WTOPC_SYS_TIME); wtopc(msg, WTOPC_EBROUT, WTOPC_NO_CHAIN, &msg_hdr); }

3. Create an optional enrichment program, if required. The enrichment program must accept parameters as defined by the enrichment typedef (Example 11-9).

Example 11-9 Enrichment typedef #include typedef int (*enrichment)(char *eventname, void *data, char *intercept, struct tpf_bev_event_controls *controls);

To use an enrichment program, specify the four-character program name in the business event specification as shown in Step 1 of this procedure. If an enrichment program is defined for an event, the tpf_bev_signal function calls the specified program. When enrichment processing is completed, the enrichment program must call the tpf_bev_signal_enrichment_complete function to continue processing the event.

Chapter 11. Business event processing 211 Example 11-10 shows an enrichment program that changes the priority and expiration time for the associated business event.

Example 11-10 Enrichment program #include #include struct tpf_bev_data_format_user_data *userDataForFormatProg = NULL; struct tpf_bev_standard_format_user_data *userDataForStdFormat = NULL; if (strstr(intercept, “Weather_Delay”)) { controls->priority = 99; // Increase the priority to 99 controls->expiryTime = -1; // Indicate no expiration } /****************************************************************** Call Enrichment Complete ******************************************************************/ int enrComplete; enrComplete = tpf_bev_signal_enrichment_complete(eventname, data_size, data, intercept, controls, userDataForFormatProg, userDataForStdFormat);

switch(enrComplete) { case BEV_SIGNAL_NORMAL: sprintf(msg, "EVENT %s SIGNALED\n", event); wtopc_insert_header(&msg_hdr, "QFLE", 2, 'I', WTOPC_SYS_TIME); wtopc(msg, WTOPC_EBROUT, WTOPC_NO_CHAIN, &msg_hdr); break; case BEV_SIGNAL_NOT_ENABLED: sprintf(msg, "EVENTING IS NOT ENABLED\n"); wtopc_insert_header(&msg_hdr, "QFLE", 3, 'E', WTOPC_SYS_TIME); wtopc(msg, WTOPC_EBROUT, WTOPC_NO_CHAIN, &msg_hdr); break; case BEV_SIGNAL_EVENT_NOT_DEPLOYED: sprintf(msg, "EVENT %s IS NOT DEPLOYED\n", event); wtopc_insert_header(&msg_hdr, "QFLE", 4, 'E', WTOPC_SYS_TIME); wtopc(msg, WTOPC_EBROUT, WTOPC_NO_CHAIN, &msg_hdr); break; case BEV_SIGNAL_NOT_NORM_STATE: sprintf(msg, "SYSTEM IS NOT IN NORM STATE\n"); wtopc_insert_header(&msg_hdr, "QFLE", 6, 'E', WTOPC_SYS_TIME); wtopc(msg, WTOPC_EBROUT, WTOPC_NO_CHAIN, &msg_hdr); break; case BEV_SIGNAL_INVALID_PARAMETER: sprintf(msg, " interceptName PARAMETER IS NOT VALID\n"); wtopc_insert_header(&msg_hdr, "QFLE", 7, 'E', WTOPC_SYS_TIME); wtopc(msg, WTOPC_EBROUT, WTOPC_NO_CHAIN, &msg_hdr); } // end switch

The controls parameter is a pointer to the tpf_bev_event_controls structure that is defined in the tpf/ibev.h header file.

212 z/TPF Application Modernization using Standard and Open Middleware When the enrichment program calls the tpf_bev_signal_enrichment_complete function, the data that is defined in the tpf_bev_data_format_user_data structure is passed to the data format program for processing. If the business event dispatch adapter specification specifies a custom data format, the structure is passed to the custom data format program. For Common Base Event formatted output, the structure is passed to the Common Base Event data user exit (ubev_cbeData_user_exit). The tpf_bev_data_format_user_data structure (Example 11-11) is defined in the tpf/ibev.h header file.

Example 11-11 tpf_bev_data_format_user_data structure /**********************************************/ /* Structure passed to Data Format programs */ /* with additional format data (headers, etc) */ /* by the user defined enrichment program */ /**********************************************/ struct tpf_bev_data_format_user_data { int length; char data[]; };

You can use the enrichment program to pass data for Common Base Event elements and attributes that the z/TPF system does not populate by default. Define this additional data in the tpf_bev_standard_format_user_data structure. When the enrichment program calls the tpf_bev_signal_enrichment_complete function, the data that is defined in the tpf_bev_standard_format_user_data structure is passed to the z/TPF system to process. The tpf_bev_standard_format_user_data structure (Example 11-12) is defined in the tpf/ibev.h header file.

Example 11-12 tpf_bev_standard_format_user_data structure /************************************************/ /* Structure passed to the standard Data Format */ /* progs (done by the system), with additional */ /* format data (header info, etc), by the user */ /* defined enrichment program */ /************************************************/ struct tpf_bev_standard_format_user_data { int length; char data[]; };

The data parameter is a character string that contains all of the elements and attributes that you want to populate. For each element, use the following format: parent_element-{parent_element}element:value\0 For each attribute, use the following format: parent_element-{parent_element}attribute;value\0 The following example shows a data string that contains attributes for the root CommonBaseEvent element. CBE/CommonBaseEvent-severity;10\0CommonBaseEvent-priority;70\0 Example 11-13 on page 214 shows a data string that contains additional Common Base Event elements and attributes.

Chapter 11. Business event processing 213 Example 11-13 Data string with additional CBE elements and attributes CBE/contextDataElements-contextValue:contextValue\0contextDataElements-name;myC ontext\0 contextDataElements-type;String\0

Example 11-14 shows a data string that contains a mixture of data format types.

Example 11-14 Data string with a mixture of data format types CBE/extendedDataElements-values:edeValues\0WBE/sladifjasdofijaodsf\0 CBE/extendedDataElements-name;EDEdata\0extendedDataElements-type;string\0 extendedDataElements-children-values:childValue\0 extendedDataElements-children-name;childName\0extendedDataElements-children-typ e;long\0

If an enrichment program obtains any storage, such as ECB heap, the program is responsible for releasing that storage. When the enrichment program returns control to the tpf_bev_signal function, the function returns control to the program that signaled the event without any additional processing. If there is no enrichment program defined for an event, the tpf_bev_signal function processes the event. 4. Create an optional custom data format program, if required. To use a custom data format program, specify the four-character program name in the business event dispatch adapter specification, as shown in Step 1 of this procedure. The custom data format program must accept parameters as defined by the customDataFormat typedef (Example 11-15).

Example 11-15 customDataFormat typedef #include typedef int (*customDataFormat)(char *eventname, struct tpf_bev_info *ddn, void **return_pointer_to_formatted_data, struct tpf_bev_data_format_user_data *user);

The custom data format program must obtain an ECB heap buffer to contain the formatted data. Additionally, the custom data format program must save the pointer to the formatted data at the location specified by the return_pointer_to_formatted_data parameter. The ECB heap buffer is released by the business event dispatch queue handler program after the data is transmitted. In Example 11-16, the custom format program obtains ECB heap for the formatted data and returns an integer that contains the size of the formatted data.

Example 11-16 Custom format program obtains ECB heap // Obtain an ECB heap buffer that will contain the formatted data // The ECB heap buffer will be released by the dispatch queue handler program // after the data has been transmitted bufferPtr = malloc(sizeOfFormattedData); if (bufferPtr == NULL) { sprintf(msg, "ERROR OBTAINING ECB HEAP\n"); wtopc_insert_header(&msg_hdr, "QFLF", 1, 'E', WTOPC_SYS_TIME); wtopc(msg, WTOPC_EBROUT, WTOPC_NO_CHAIN, &msg_hdr); QFLF_returnValue = 0; // custom data format program encountered an error

214 z/TPF Application Modernization using Standard and Open Middleware } else { memcpy(bufferPtr, customFormatBuffer, sizeOfFormattedData); // Save the pointer to the formatted data at the location specified by the // third parameter *return_pointer_to_formatted_data = bufferPtr; QFLF_returnValue = sizeOfFormattedData; } return QFLF_returnValue; };

5. Create an optional custom dispatch adapter program, if required. To use a custom dispatch adapter program, specify the four-character program name in the business event dispatch adapter specification, as shown in Step 1 of this procedure. The custom adapter program must accept parameters as defined by the customAdapter typedef (Example 11-17).

Example 11-17 customAdapter typedef #include typedef int (*customAdapter)(int callReason, void *callStructure);

The custom adapter program gets called either to transmit data or to perform set up processing during cycle to NORM state. In Example 11-18, when the custom adapter program is called to transmit data, the callStructure is a pointer to the tpf_bev_ca_transmit structure defined in the tpf/ibev.h header file.

Example 11-18 Custom adapter program is called to transmit data if (callReason == bev_ca_transmit) { transmitStructure = (struct tpf_bev_ca_transmit *)callStructure; char *dataString = (char *)transmitStructure->formatted_data; event = transmitStructure->properties->event_name; persistence = transmitStructure->properties->event_persistence; expiry = transmitStructure->properties->event_expiry; priority = transmitStructure->properties->event_priority; dataLength = transmitStructure->formatted_data_length; userParm = transmitStructure->user_parm; /* Add code here to transmit data using an MQ queue and other transport */ // When callReason is bev_ca_transmit, the return from the custom // adapter program must be an integer that contains the number of // bytes that were transmitted return_val = dataLength; } // end if(callReason == bev_ca_transmit) return return_val; } // end QFLA

Chapter 11. Business event processing 215 6. Load all of the changes for this business event to the z/TPF system with the E-type loader or the image loader. Specifically, ensure that the following components are loaded to the system: – The business event specification. – The business event dispatch adapter specification. – The enrichment program, if used. – The custom data format program, if used. – The custom dispatch adapter program, if used. – All updated application programs that call the business event APIs. The business event dispatch adapter specification is automatically deployed the first time the file is loaded online. 7. Deploy the business event specification. Enter the following command, where bevname is the file name: ZMDES DEPLOY FILE-bevname.evspec.xml The business event specification is deployed only on the processor that you enter the ZMDES command on. You must enter this command for each processor in a loosely coupled complex.

11.11.3 Results

The business event is processed when the application program calls the tpf_bev_signal function.

11.11.4 What to do next

If you need to stop processing an individual business event after the event was deployed, you can undeploy the event. Enter the following command, where bevname is the file name: ZMDES UNDEPLOY FILEbevname.evspec.xml

If you need to stop processing an individual business event dispatch adapter, you can undeploy the dispatch adapter. Enter the following command, where bevdaname is the file name: ZMDES UNDEPLOY FILEbevdaname.evda.xml

If you need to stop processing for all business events on a processor, you can disable business event processing on that processor. Enter the following command: ZBEVF DISABLE

11.12 Removing a loosely coupled processor

When you remove a processor that uses business event processing from a loosely coupled complex, you must move the business event dispatch queue on that processor to another active processor: 1. If possible, stop network traffic to the processor that you are removing from the complex. The purpose is to stop inbound traffic that might be generating business events. 2. Cycle the z/TPF system to 1052 state by entering ZCYCL 1052. 3. Deactivate the processor by entering the ZPSMS command.

216 z/TPF Application Modernization using Standard and Open Middleware 4. Ensure that any business event deployment descriptors on the deactivated processor are deployed on the processor that you are moving the business event processing work to. Enter the ZMDES command with the DEPLOY parameter specified for any business event deployment descriptors that are not already deployed on the new processor. 5. Move the messages from the business event dispatch queue on the deactivated processor to another processor that is active by entering the ZMQSC MOVEMSGS command.

Chapter 11. Business event processing 217 218 z/TPF Application Modernization using Standard and Open Middleware Part 5

Part 5 Security

Part 5 of this book describes XML encryption and the WS-Security standard to provide message-level data security. We also discuss a way to set up and customize WS-Security on your system, using a sample WS-Security application for a secure Web service.

This part contains the following chapters:  Chapter 12, “z/TPF XML encryption” on page 221  Chapter 13, “z/TPF WS-Security wrapper” on page 229

© Copyright IBM Corp. 2013. All rights reserved. 219 220 z/TPF Application Modernization using Standard and Open Middleware 12

Chapter 12. z/TPF XML encryption

This chapter provides information about sending secure XML messages between web service consumers and providers implemented in z/TPF applications.

This chapter contains the following topics:  12.1, “Web services security” on page 222  12.2, “Data confidentiality for web services” on page 222  12.3, “WS-Security” on page 223  12.4, “Key aliases and client identification” on page 225  12.5, “SOAP message handler extension file” on page 225  12.6, “Schema” on page 227  12.7, “XML path language expressions supported by the z/TPF system” on page 227

© Copyright IBM Corp. 2013. All rights reserved. 221 12.1 Web services security

Transport-level security is provided by the z/TPF system through the use of the SSL protocol. This is a point-to-point solution where data that is encrypted by the communications layer at the sending node and decrypted by the communications layer at the receiving node flows across a network. Message-level security is required when the data itself must be protected during processing so that it is never exposed.

The WS-Security core specification defines the use of the XML Encryption (XMLENC) standard to provide for message-level data confidentiality. XMLENC defines a mechanism for encrypting and decrypting XML element content, entire XML elements, or entire XML documents. When XMLENC is used with WS-Security, the encrypted portions of a SOAP message are commonly identified by ReferenceList elements in the Security header block of that message. The receiving node must then process the EncryptedData elements that are indicated by the ReferenceList elements. The WS-Security SOAP message handler is a specific type of SOAP message handler that automatically performs the following operations:  Processes encrypted data in a received SOAP request/response  Encrypts user-specified portions of an outbound SOAP request/response.

For more information about the WS-Security Core Specification 1.1, see: http://www.oasis-open.org/committees/download.php/16790/wss-v1.1-spec-os-SOAPMessa geSecurity.pdf

For more information about the XML Encryption specification, see: http://www.w3.org/TR/xmlenc-co

12.2 Data confidentiality for web services

Protecting data in flight most often applies when data is flowing from one node to another across the network, preventing anyone in the network from being able to access the clear text data. The most common implementations of protecting data in flight are SSL and IPSec. With data confidentiality for web services, data is encrypted at the application or Simple Object Access Protocol (SOAP) level, above the transport layer. (Although you can achieve data confidentiality by using a secure transport such as HTTPS, which uses SSL, in this case the term data confidentiality for web services refers to the message-level security that is provided through XML encryption.) With both SSL and data confidentiality for web services, data in flight is protected (that is, encrypted while it is in the network). The difference is that with SSL, all data is in the clear when it reaches the remote application. However, with data confidentiality for web services, you can encrypt different parts of the message or document with different keys so that only parts of that document can be seen by different destinations.

For example, node A can encrypt parts of an XML document using key X and another part using key Y, and send the document to node B, which appends data to the document and forwards it to node C. Node B knows key X and can see parts of the document in the clear; however, node B cannot see the document parts that are encrypted by key Y. Node C knows key Y and can see parts of the document in the clear. While SSL only protects data in flight on a hop-by-hop basis, data confidentiality for web services can protect data in flight, end to end, in a distributed application environment.

Message-level security is achieved by updating your web services infrastructure (such as the web service deployment descriptor, SOAP message handler deployment descriptor, and SOAP message handler) to process encrypted data in a received SOAP request/response or to encrypt specific portions of an outbound SOAP request/response.

222 z/TPF Application Modernization using Standard and Open Middleware Data confidentiality for web services uses encryption to protect data (that would otherwise be in the clear) as it is being processed by the receiving node or an intermediary node, or when only part of the message data is encrypted. Data confidentiality for web services is centered around the following specifications:  XML Encryption Syntax and Processing  Web Services Security (WS-Security): SOAP Message Security 1.1  Organization for the Advancement of Structured Information Standards (OASIS) Web Services Interoperability (WS-I) Basic Security Profile 1.0

Data confidentiality for web services requires the use of symmetric keys. Refer to the z/TPF product Information Center for detailed information about enabling secure key management:

http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztpfdf .doc_put.cur/gtps7/sckymang.html

12.3 WS-Security

Chapter 3, “z/TPF SOAP processing” on page 33 describes general SOAP processing flow. In the flow shown in Figure 3-1 on page 34, you will see a block called SOAP message handler processing. The message handlers include the WS-Security SOAP message handler and the WS-Addressing SOAP message handler. The diagrams in Figure 12-1 and Figure 12-2 on page 224, along with the steps that follow them, explain processing that occurs in the WS-Security and WS-Addressing SOAP message handlers.

Figure 12-1 shows the components and flow of WS-Security SOAP message handler (program CWSS).

CWSS: CWSU: WSSE WS-Security tpf_soapGetClientId( ) Extension SOAP message Files handler WS-Security syntax checks deploy

WS-Security SOAP Message Handler control table extension program

CS09: XPath APIs tpf_soapMapKey( )

Non-displayable and XML encryption APIs encrypt/decrypt APIs

XML APIs

Figure 12-1 WS-Security diagram

Figure 12-2 on page 224 shows the WS-Addressing SOAP message handler (program CSOK).

Chapter 12. z/TPF XML encryption 223 CSOK: WS-Addressing XML APIs SOAP message handler

Figure 12-2 WS-Addressing diagram

For inbound SOAP provider messages, the SOAP handler calls each handler in the message handler chain sequentially: 1. The WS-Security SOAP message handler: – Finds the client identification. If the client ID is not already in the soapMsgCtx structure, the handler calls tpf_soapGetClientID() and then stores the ID in the SOAP message context, so it could be reused for outbound messages. – Performs additional syntax checks for WS-Security compliance. – Checks the WSSE extension file information in the control table to see whether the message contains any sections that are encrypted. – If there are encrypted sections to decrypt, the tpf_soapMapKey function in the SOAP WS-Security Key Mapping user exit (CSO9) is called to get the key names needed for decryption. – The decryption is handled in place using the XML encryption APIs. Any further operations on the SOAP consumer API handle from the soapMsgCtx structure operate on the decrypted SOAP message. 2. The WS-Addressing SOAP message handler simply returns because it does no processing for provider inbound requests. 3. The SOAP message handler calls the Web service wrapper program which processes the request. On return from the wrapper program the SOAP handler calls each handler in this message handler chain sequentially in reverse order: 4. WS-Addressing SOAP message handler The WS-Addressing SOAP message handler adds the wsa:From and wsa:Address elements with the client identification to the outbound message. 5. The WS-Security SOAP message handler: a. The WS-Security SOAP message handler checks the SOAP message handler extension file (if there is any) to identify any parts of the message to encrypt and what encryption parameters to use. b. For outbound messages, key aliases are specified in the SOAP message handler extension file. To retrieve the name of each key that is needed to encrypt fields in the outbound SOAP message, the tpf_soapMapKey function in the SOAP WS-Security Key Mapping user exit (CSO9) is called with the client system identifier (from SOAP message context) and a key alias (from the extension file). c. The SOAP response message is encrypted in place according to the extension information. Any further operations on the SOAP consumer API handle from the soapMsgCtx structure operate on the encrypted SOAP message. 6. The SOAP handler finishes processing the response.

224 z/TPF Application Modernization using Standard and Open Middleware 12.4 Key aliases and client identification

The WS-Security SOAP message handler uses keys in the z/TPF keystore to provide support for encryption or decryption of SOAP messages. The actual keys that are used for encryption often need to be changed. To avoid disruptive service-redeployment, the WS-Security SOAP message handler uses key aliases instead of z/TPF key names.

Key aliases are resolved into z/TPF key names based on the identity of the system that is sending a SOAP request. Encrypted inbound SOAP messages must include information about the identity of the sending system, so the WS-Security SOAP message handler can do the decryption.

For inbound messages:  The tpf_soapGetClientId function in the cwscue.c user exit is called to get the client system identifier before decrypting an inbound message. If the client system identifier is set in the SOAP message context prior to entering the WS-Security SOAP message handler, its value is used and the user exit is not called.  The tpf_soapMapKey function in the SOAP WS-Security Key Mapping user exit (CSO9) is called to get key names before decrypting an inbound message. This identifier is then stored in the SOAP message context, so it can be reused for outbound messages. For outbound messages, key aliases are specified in the SOAP message handler extension file. To retrieve the name of each key that is needed to encrypt fields in the outbound SOAP message, the tpf_soapMapKey function in the SOAP WS-Security Key Mapping user exit (CSO9) is called with the client system identifier (from SOAP message context) and a key alias (from extension file).

12.5 SOAP message handler extension file

The extension file for this SOAP message handler is identified in the Web service deployment descriptor. The values in the SOAP message handler extension file are unique to your organization and you will need to update the extension file for it to be usable.

The SOAP message handler extension file must be named according to the following format: /etc/tpf-ws/ext/soapMsgHandler/extensionFile.xml  soapMsgHandler is the 1- to 32-character, unique name of the SOAP message handler that the extension file is used with.  extensionFile is the 1- to 256-character, unique name of the extension file (252 characters for the name itself plus the four characters needed for the .xml suffix), which will be stored in the specified directory of the z/TPF file system.

Each SOAP message handler must define a unique format for the corresponding SOAP message handler extension file. A good basis for creating the extension file format is to use the base element SOAPMessageHandlerExtensionFile. The SOAPMessageHandlerExtensionFile root element is defined in the base/tpf-ws/schema/tpf_ws_dd_vn.xsd XML schema file, where n is the version number that is shipped with the z/TPF system.

Chapter 12. z/TPF XML encryption 225 12.5.1 SOAP message handler extension program

The SOAP message handler extension program processes data that is in a SOAP message handler extension file. The SOAP message handler extension file, in turn, provides service-specific input to a SOAP message handler.

The SOAP message handler extension program is called at different times during the processing of a provider Web service deployment descriptor to perform an action on the specified SOAP message handler extension file, or to provide information about the extension file to the z/TPF system. The structure of the SOAP message handler extension file is user-defined and is unique to each SOAP message handler. The extension file is optional; however, if it will be used, you must specify it in the deployment descriptor for each SOAP message handler in the SOAP message handler chain. Deployment descriptors for SOAP message handlers that use extension files must specify a SOAP message handler extension program.

The SOAP message handler extension program is called when the ZWSAT command is entered with one of the following parameters: ADD, DEPLOY, UNDEPLOY, REMOVE, or DISPLAY.

SOAP support uses the TPF_CALL_BY_NAME C function to call the 4-character z/TPF program name that is specified in the SOAP message handler deployment descriptor for a SOAP message handler. Processing is implemented in C shared objects (CSOs). CSOs must have a single entry point as defined in the makefile. The interface to the CSO must match the interface that is defined by the typedef that is used to define SOAP message handler extension programs. The format of the typedef is: typedef SOAP_MSGHDLR_RET (*smhextfn)(SOAP_MSGHDLR_TASK, struct __tpfSoapMsgCtx*, char**, int*, char**);

An explanation of the typedef is:  SOAP message handler extension programs must return an integer; this is defined by the SOAP_MSGHDLR_RET enumeration in the c_soap.h header file. In the case of an error, the errno value should be set to the appropriate error code.  The first parameter is an integer. It represents a task code (defined by the SOAP_MSGHDLR_TASK enumeration in the c_soap.h header file) that identifies whether the program is entered in response to a Web service deploy request, a Web service undeploy or remove request, or the ZWSAT command with the DISPLAY and EXTENSION parameters specified.  The second parameter is a pointer to a tpfSoapMsgCtx structure, which is defined in the c_soapctx.h header file.  The third parameter is a pointer to a character pointer and has a different meaning depending on the task code.  The fourth parameter is a pointer to an integer and has a different meaning depending on the task code.  The fifth parameter is a pointer to a character pointer that is to contain the address of an ECB heap storage buffer (obtained by malloc). On return, the ECB heap storage buffer contains a NULL-terminated string. The string specifies the error message that is included as part of the WSAT0080E message in response to the ZWSAT command with the DEPLOY, UNDEPLOY, or DISPLAY parameter specified. If no data is to be returned, this is set to NULL. If the value is set to NULL and MSGHDLR_RET_ERROR is returned, the errno value is used to determine the error text.

226 z/TPF Application Modernization using Standard and Open Middleware  The smhextfn pointer is a pointer to the function type and is passed to the TPF_CALL_BY_NAME macro. With this pointer and the four-character program name that implements the SOAP message handler, the TPF_CALL_BY_NAME macro returns a pointer to the function value that calls an enter with return (ENTRC linkage) to the specified program.

12.6 Schema

The schema defines the structure of the extension files for the WS-Security SOAP message handler. You can use it in most XML editors to help create valid SOAP message handler extension files. The elements in the schema are standard XML elements.

The schema file is located in the z/TPF file system, where n is the version number: xsi:schemaLocation="http://www.ibm.com/xmlns/prod/ztpf/soap/wsse/etc/tpf-ws/schema /tpf_wsse_ext_vn.xsd

12.7 XML path language expressions supported by the z/TPF system

You can specify fields in SOAP response messages to be encrypted using XML path language (XPath) notation to simplify configuration options and to allow for flexibility on a per-service basis. The z/TPF system supports the subset of XPath notation shown in Table 12-1.

Table 12-1 Node selection support Expression Description

elementname Select a node with name elementname

/ Select from the root node

// Select from the current node regardless of the location in the document.

* Select all of the descendants of the current node.

Predicates in XPATH notation are used to find:  A specific element.  A specific element that has a specific attribute.  A specific element that has a specific attribute that has a specific value.  Predicates are embedded in square brackets.

Table 12-2 on page 227 shows the predicate support in z/TPF.

Table 12-2 Predicate support Expression Description

elementname[n] Select the nth elementname of the current parent element node.

elementname[@attrname] Select the element node with the name elementname that has an attribute of attrname.

Chapter 12. z/TPF XML encryption 227 Expression Description

elementname[@attrname=' Select the element node named elementname that has an attribute of attrvalue'] attrname with a value of attrvalue.

For more information about the XPath language, go to the following website:

http://www.w3.org/TR/xpath

228 z/TPF Application Modernization using Standard and Open Middleware 13

Chapter 13. z/TPF WS-Security wrapper

The SOAP message handler provides data confidentiality for web services support that is transparent to the underlying services.

There are many ways to set up and customize WS-Security on your system. This chapter discusses in detail a sample WS-Security application for the Secure Web service CalculatorService. To download and use a WS-Security sample application, go to the following website:

http://www.ibm.com/software/htp/tpf/maint/toolsztpf.html

This chapter contains the following topics:  13.1, “Sample XML files” on page 230  13.2, “Client identification (cwscue.c)” on page 238  13.3, “Key mapping” on page 239  13.4, “SOAP message handler extension file” on page 240  13.5, “WS-Addressing SOAP message handler” on page 242  13.6, “SOAP message handler extension program processing for a Web service deploy request” on page 243  13.7, “WS-Security Deployment” on page 244  13.8, “Generating keys” on page 246  13.9, “Running the application” on page 246

© Copyright IBM Corp. 2013. All rights reserved. 229 13.1 Sample XML files

The following list provides sample XML files for the WS-Security application used to illustrate the concepts of the WS-Security wrapper application. These files will be referenced and explained in detail later in this chapter.

The files include:  SOAP provider files: – SOAP provider deployment descriptor: SecureCalculatorService.xml – SOAP message handler extension file for WS-Security: calculatorProvider_ext.xml  SOAP message handlers: – WS-Addressing SOAP Message Handler: WS-Addressing.xml – WS-Addressing Handler program: CSOK – WS-Security SOAP Message Handler: WS-Security.xml – WS-Security Handler program: CWSS  SOAP consumer files: – SOAP Consumer deployment descriptor: SecureCalculatorService_consumer.xml – SOAP message handler extension file for WS-Security: calculatorConsumer_ext.xml  Sample XML messages: – Consumer Secure Calculator request before encryption (after WS-Addressing) – Consumer Secure Calculator request after encryption – Provider Secure Calculator response before encryption – Provider Secure Calculator response after encryption

13.1.1 SOAP provider files

This section provides information about the files used by the web service provider for the Calculator Service web service.

SOAP provider deployment descriptor The SOAP provider deployment descriptor defines the attributes for the provider web service. Example 13-1 contains the SecureCalculatorService.xml SOAP provider descriptor that describes the SecureCalculatorService web service.

The descriptor includes pointers to the SOAP message handler for WS-Security, the SOAP message handler extension file for WS-Security (calculatorProvider_ext.xml), and the SOAP message handler for WS-Addressing.

Example 13-1 SecureCalculatorService.xml /CalculatorService CSOB

230 z/TPF Application Modernization using Standard and Open Middleware WS-Security WS-Addressing false SOAP1.1 add sub This a sample Web Service that implements a simple Calculator: see CalculatorService.wsdl for more details.

SOAP message handler extension file for WS-Security (provider) Example 13-2 contains the SOAP message handler extension file, calculatorProvider_ext.xml, for CalculatorService. This file identifies the WS-Security SOAP message handler and provides the XML encryption information for the SecureCalculatorService for the web service provider.

Example 13-2 calculatorProvider_ext.xml WS-Security LocalKeyAlias /Envelope/Body/addResponse /Envelope/Body/Fault/faultstring

Chapter 13. z/TPF WS-Security wrapper 231

13.1.2 SOAP message handlers

This section provides information about the SOAP message handlers used in the example and how they are defined.

SOAP message handler descriptor for WS-Addressing Example 13-3 contains the SOAP message handler descriptor, WS-Addressing.xml. This file defines the attributes for WS-Addressing.

Example 13-3 SOAP message handler descriptor for WS-Addressing WS-Addressing CSOK This is a message handler that provides WS-Addressing support

The WS-Addressing message handler provides the mechanism to identify the end points (consumers) that are sending web service requests and the provider that is sending web service responses.

SOAP message handler deployment descriptor for WS-Security Example 13-4 contains the SOAP message handler deployment descriptor WS-Security.xml. This file defines the attributes for WS-Security, including the SOAP message handler program (CWSS) and the SOAP message handler extension program (CWSX).

Example 13-4 SOAP message handler descriptor for WS-Security WS-Security CWSS CWSX This is a message handler that provides WS-Security support

232 z/TPF Application Modernization using Standard and Open Middleware

The SOAP message handler extension program, CWSX, is specified in the SOAP message handler deployment descriptor. The SOAP message handler deployment descriptor is used as is, meaning do not change anything in the deployment descriptor.

The WS-Security message handler program, CWSS, uses keys in the z/TPF keystore to provide support for encryption and decryption of SOAP messages.

13.1.3 SOAP consumer files

This section provides information about the consumer of the web service.

SOAP consumer deployment descriptor Example 13-5 contains the SOAP Consumer SecureCalculatorService_consumer.xml descriptor. This file defines the attributes for the consumer web service SecureCalculatorService. It includes information about the SOAP message handler for WS-Addressing, the SOAP message handler for WS-Security, and the SOAP message handler extension file for WS-Security.

Example 13-5 SOAP Consumer SecureCalculatorService_consumer.xml descriptor /CalculatorService QWC1 WS-Addressing WS-Security false SOAP1.1 SOAP1.2 add sub This a sample Consumer Web Service that calls a simple Calculator: see CalculatorService.wsdl for more details false ibm-1047 utf-8

Chapter 13. z/TPF WS-Security wrapper 233 127.0.0.1 1000 http://127.0.0.1/CalculatorService Content-Type: text/xml; charset=utf-8 soapAction: "" CalculatorQueue CalculatorAsyncReplyQueue CalculatorSyncReplyQueue http://127.0.0.1/CalculatorService QWC3 http://127.0.0.1/calcService

SOAP message handler extension file (consumer) Example 13-6 contains the SOAP message handler extension file for the consumer of CalculatorService. This file identifies the XML encryption information for the SecureCalculatorService for the consumer and defines what data should be encrypted.

Example 13-6 Web Service Consumer extension file for /CalculatorService WS-Security

234 z/TPF Application Modernization using Standard and Open Middleware LocalKeyAlias /Envelope/Body/add/value

13.1.4 Sample XML messages

The sample messages in this section will help you understand how WS-Security is used in the message flow between provider and consumer.

Consumer Secure Calculator request before encryption The SecureCalculatorService_consumer.xml descriptor Stub program QWC1 builds the calculator request. The WS-Addressing SOAP message handler adds addressing elements to the request for the consumer.

Example 13-7 shows a Secure Calculator request before encryption (after WS-Addressing).

Example 13-7 Secure Calculator request before encryption

http://www.ibm.com/localTPF/clientApplication http://example.com/addressing 6 77

Consumer Secure Calculator request after encryption The WS-Security SOAP message handler performs the encryption of the request based on the SOAP message handler extension file for the consumer and adds the security elements

Chapter 13. z/TPF WS-Security wrapper 235 to the consumer request. The request is sent to the provider, SecureCalculatorService Web service.

The WS-Addressing SOAP message handler does nothing for the provider on the consumer request. The WS-Security SOAP message handler performs the decryption of the consumer request for the provider based on the extension file of the consumer. The SecureCalculatorService wrapper program CSOB receives the request.

Example 13-8 shows a Secure Calculator request after encryption.

Example 13-8 Secure Calculator request after encryption http://www.ibm.com/localTPF/clientApplication

xmlns:wsa="http://www.w3.org/2005/08/addressing">http://example.com/addressing < /wsa:Action> LocalKeyAlias

xiEi/7N9+QvGISL/s335C9Weh+qLI2LTPfvd5a5IqQM= LocalKeyAlias

236 z/TPF Application Modernization using Standard and Open Middleware

xiEjAIbKqo7GISMAhsqqjhwqRol8l2D7FYmIXC4g6tQ=

13.1.5 CalculatorService provider response before encryption

The SecureCalculatorService.xml provider descriptor wrapper program CSOB builds the response. The WS-Addressing SOAP Message handler adds addressing elements to the response for the provider.

Example 13-9 shows a CalculatorService response before encryption (after WS-Addressing).

Example 13-9 CalculatorService response before encryption 9.57.13.48 http://example.com/addressing 83

13.1.6 CalculatorService provider response after encryption

The WS-Security SOAP message handler performs the encryption of the response based on the SOAP message handler extension file for the provider and adds the security elements to the response. The response is returned to the consumer.

The WS-Addressing SOAP message handler does nothing for the consumer on the provider response. The WS-Security SOAP message handler performs the decryption of the provider response for the consumer and returns to the consumer application.

Example 13-10 shows the CalculatorService response after encryption.

Example 13-10 CalculatorService response after encryption

Chapter 13. z/TPF WS-Security wrapper 237 9.57.13.48 http://example.com/addressing LocalKeyAlias

xi2fIsLHH4vGLZ8iwscfi0F9T2FpQUrjWk24IoQ37yIsbiQ5E0mHkBLFmmn1Eb78 5Y0vC1CFfCs PJom5Wr8qA==

13.2 Client identification (cwscue.c)

The web services client system identification user exit function tpf_soapGetClientID, in segment cwscue.c, is called as part of the WS-Security SOAP message handler processing. Key aliases are resolved into z/TPF key names based on the identity of the system that is sending a SOAP request. Encrypted inbound SOAP messages have to include the information about the sending system identity so that the WS-Security SOAP message handler can do the decryption. This identifier is then stored in the SOAP message context, so it can be reused for outbound messages.

It is up to the end-user to select and implement the client system identification mechanism to be used in your installation.

Users must code the user exit function tpf_soapGetClientId() to provide an identifier of the client system before decrypting an inbound message.

Helper functions TPF_SOAP_MSGCTX_GET_CLIENT_ID(ctx) and TPF_SOAP_MSGCTX_SET_CLIENT_ID(ctx, client_id) are provided to manually retrieve and set the client system identifier. The client_id must be a NULL-terminated string.

238 z/TPF Application Modernization using Standard and Open Middleware Example 13-7 on page 235 shows a type of client identifier that can be included in the XML request message. http://www.ibm.com/localTPF/clientApplication

The user exit (cwscue.c) uses the TPF XML API tpf_getElementsByTagName() to extract the “Address” element for the client identifier and return it to the WS-Security SOAP Message Handler who will use TPF_SOAP_MSGCTX_SET_CLIENT_ID(ctx, client_id) to set the identifier.

The value of element can be any client identifier name agreed upon between the client and provider.

13.3 Key mapping

The WS-Security SOAP message handler uses keys in the z/TPF secure key keystore to provide support for the encryption and decryption of SOAP messages. Key aliases, which are the key names that appear in actual SOAP message flows to and from z/TPF, are resolved into z/TPF key names based on the client identity of the system that is sending a SOAP request.

To get key names needed for decryption of inbound requests and encryption of outbound responses, a user exit tpf_soapMapKey(client_id, key_alias) in cso9.c is called with the client system identifier and a key alias name as parameters.

13.3.1 Decrypting inbound SOAP requests

For decrypting inbound SOAP requests, the key alias name is retrieved from the element in the request message. Example 13-11 shows the key name from Example 13-8 on page 236.

Example 13-11 Key name information LocalKeyAlias

13.3.2 Encrypting outbound SOAP responses

For encrypting outbound SOAP responses, key aliases are specified in the consumer SOAP message handler extension file (Example 13-6 on page 234) for CalculatorService. Example 13-10 on page 237 shows the encrypted response. Example 13-12 shows the key alias from the extension file in Example 13-6 on page 234.

Example 13-12 Key alias information >LocalKeyAlias

Chapter 13. z/TPF WS-Security wrapper 239 13.3.3 Mapping the key alias to real key name

To map the key alias to a real key name: 1. Generate the keys that the consumer and provider web services will use, and import the keys to the z/TPF secure key keystore and activate them. 2. The sample user exit cso9.c contains a table with a client identifier, key alias name, and the real key name (also called the z/TPF secure key keystore name). WSSE_clientID_lookup clientLookup[] = { {NULL, NULL, NULL}, {"http://example.com/axis2/clientApplication", "Axis2KeyAlias", "AXIS2KEY"}, {"http://www.ibm.com/localTPF/clientApplication", "LocalKeyAlias", "LOCALKEY"}, }; For example, the sample code maps the client identifier of http://www.ibm.com/localTPF/clientApplication and the key alias name of LocalKeyAlias to the keystore name of LOCALKEY. (LOCALKEY must exist in the z/TPF secure key keystore) 3. If you want to make changes to how the key alias is mapped to the real key name, edit the sample user exit code (cso9.c) to either change the current table to include your specific client identifiers and key alias names or to return the keystore name with a different method. 4. See the following item in the IBM TPF Product Information Center for more information about z/TPF Security. http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom .ibm.ztpf-ztpfdf.doc_put.cur%2Fgtps6mst.toc.html

13.4 SOAP message handler extension file

The extension file names for the WS-Security SOAP message handler are identified in the Web service deployment descriptor. The following extension file name specifications are taken from Example 13-1 on page 230 and Example 13-5 on page 233:  WS-SecurityWS-Security

The values in the SOAP message handler extension files are unique to your organization. The valid types are: Content, Element and Header.

The schema file for the extension files are placed in the z/TPF file system: /etc/tpf-ws/schema/tpf_wsse_ext_v1.xsd

The extension files for the Web Service are placed in the extension file directory for WS-Security:  /etc/tpf-ws/ext/WS-Security/calculatorConsumer_ext.xml  /etc/tpf-ws/ext/WS-Security/calculatorProvider_ext.xml

240 z/TPF Application Modernization using Standard and Open Middleware The next sections contain explanations for the sample extension files for this WS-Security application.

13.4.1 Consumer extension file

First examine the sample Consumer extension file (calculatorConsumer_ext.xml) for /CalculatorService (Example 13-6 on page 234):  Key aliases are assumed to match actual key names in the z/TPF secure key keystore.  Locate the OutFlow element (Example 13-13). This is used for non-fault responses. If the operation that was specified in the inbound SOAP request is add, then the Field elements under the EncryptionOutFlow will be used for encryption. In this case, the /Envelope/Body/add/value element is listed. It has an encryption type of Content, which means we will encrypt just the content of the element "value" but not the element tag name from its start to end tags. See Example 13-8 on page 236. The keyId of mykey1 maps to the ExistingKey element.

Example 13-13 Outflow element /Envelope/Body/add/value

13.4.2 Provider extension file

Now example the sample Provider extension file (calculatorProvider_ext.xml) for /CalculatorService (Example 13-2 on page 231). Note that:  Key aliases are assumed to match actual key names in the z/TPF secure key keystore.  Locate the OutFlow element (Example 13-14). This is used for non-fault responses. If the operation that was specified in the inbound SOAP request is add, the Field elements under the EncryptionOutFlow will be used for encryption. In this case, the /Envelope/Body/addResponse element is listed. It has an encryption type of Element, which means we will encrypt the content of the element addResponse and the element tag name from its start to end tags. The identity of the element itself is hidden. (Example 13-10 on page 237). The keyId of mykey1 maps to the ExistingKey element.

Example 13-14 Outflow element

Chapter 13. z/TPF WS-Security wrapper 241 /Envelope/Body/addResponse <

 Locate the Faultflow element (Example 13-15). This is used for fault responses. Notice that no Operation is listed. An Operation element without a name attribute, such as add serves, as a catch-all category for all operations not specified in the extension file. In this case, the /Envelope/Body/Fault/faulstring element is listed. It has an encryption type of Content, which means we will encrypt the content of the element faultstring but not the element tag name from its start to end tags. The keyId of mykey1 maps to the ExistingKey element.

Example 13-15 FaultFlow element /Envelope/Body/Fault/faultstring

13.5 WS-Addressing SOAP message handler

The sample WS-Addressing SOAP message handler for using WS-Addressing along with XML encryption is segment csok.c. It provides the mechanism to identify the consumer that is sending in Web service requests and the provider that is sending the Web service responses.

13.5.1 Outbound requests

The WS-Addressing handler will add the wsa-addressing elements, shown in Example 13-16, to the outbound consumer XML request. The elements are added after the WS-Security Header element (see Example 13-7 on page 235).

Example 13-16 wsa-addressing elements in outbound consumer XML request http://www.ibm.com/localTPF/clientApplication http://example.com/addressing

242 z/TPF Application Modernization using Standard and Open Middleware 13.5.2 Outbound responses

The WS-Addressing handler will add wsa-addressing elements, shown in Example 13-17, to the outbound provider XML Encryption responses. The elements are added after the WS-Security Header element (see Example 13-9 on page 237).

Example 13-17 wsa-addressing elements in outbound provider XML Encryption responses 9.57.13.48 http://example.com/addressing

13.5.3 Changing the wsa-addressing

To change the wsa-addressing elements: 1. Edit the user exit segment cwscue.c. 2. For outbound consumer requests, edit the code to add your own addressing information to be sent in the request. 3. For outbound provider responses, this sample message handler code uses the host IP address for the From Address. This can be changed to whatever the user desires.

13.6 SOAP message handler extension program processing for a Web service deploy request

The z/TPF system calls the deploy part of a SOAP message handler extension program when a Web service resource that includes this SOAP message handler in its SOAP message handler chain is being deployed.

This might occur in response to ZWSAT command processing when the DEPLOY parameter is specified or during z/TPF system restart when all of the resources that were previously deployed are being deployed again.

The SOAP message handler extension program can process the specified extension file, extract the information that it needs, and save that information in a location to be referenced at a later time by the SOAP message handler program. This interface permits the extension program to optionally return a pointer to data that will be stored in the corresponding web services deployment table (WSDT) entry for the Web service that is being deployed. The SOAP message handler can then access that data through the SOAP message context structure (tpfSoapMsgCtx).

Use the TPF_SOAP_MSGCTX_IS_EXT_PRESENT and TPF_SOAP_MSGCTX_GET_HDLR_EXT_FILE helper functions, which are defined in the c_soapctx.h header file, to determine if an extension file was specified for the Web service resource that is being deployed and to get a pointer to the file name, respectively.

The third and fourth input parameters of the typedef have the following meanings when called to perform a deploy action:  The third parameter is a pointer to a character pointer that is to contain the address of an ECB heap buffer (obtained by malloc) on return that specifies the data that is to be added to the deployed WSDT entry. If no data is to be returned, set this to NULL.

Chapter 13. z/TPF WS-Security wrapper 243  The fourth parameter is a pointer to an integer that is to contain the length of the ECB heap buffer specified on return of the third parameter. Set this to 0 if no data is to be returned.

After you code the function in this part, ensure that the return call back to the z/TPF system contains one of the following return codes:  MSGHDLR_RET_CONT Use this return when processing is successful and the deployment of the Web service resource should continue.  MSGHDLR_RET_ERROR Use this return when processing is not successful and the deployment of the Web service resource should not continue. You can set the errno variable to indicate the specific error that occurred.

13.6.1 SOAP message handler extension program for WS-Security (cwsx.c)

The CWSX extension program gets control when a Web service that uses a WS-Security SOAP message handler with an extension file is deployed or displayed (ZWSAT DEPLOY or ZWSAT DISPLAY). The following example shows how the extension program is defined from Example 13-4 on page 232: CWSX

After the extension program saves the extension data in a Web service’s WSDT entry, it will be available to the SOAP message handler using helper functions used to interact with the tpfSoapMsgCtx structure while processing Web service messages.

13.7 WS-Security Deployment

To deploy the WS-Security application, build and load the user exit code to your z/TPF system:  CSO9 (tpf_soapMapKey)  CWSU (cwscue.c – tpf_getSoapClientId)  CSOK (WS-Addressing Message Handler segment).

13.7.1 Deploy the WS-Security SOAP message handler

To deploy a SOAP message handler to the z/TPF system: 1. Load and activate the SOAP message handler program. Because this is simply another application, follow the same procedure for loading and activating any application. 2. Load and activate the SOAP message handler extension program. Because this is simply another application, follow the same procedure for loading and activating any application. 3. Load the SOAP message handler deployment descriptor for WS-Security (Example 13-4 on page 232) by FTPing the file in binary form to the z/TPF file system under the /etc/tpf-ws/ directory. 4. Activate the SOAP message handler deployment descriptor by entering the ZWSAT command with the DEPLOY parameter to deploy the SOAP message handler.

244 z/TPF Application Modernization using Standard and Open Middleware The TPF Toolkit provides an action to load the deployment descriptor file using FTP to send the file to the z/TPF file system. The TPF Toolkit can also activate the deployment descriptor by using the DEPLOY action for a selected Web service resource shown in the Remote Systems

13.7.2 Deploying the WS-Addressing.xml SOAP message handler

To deploy a SOAP message handler to the z/TPF system: 1. Load and activate the SOAP message handler program; because this is simply another application, follow the same procedure for loading and activating any application. 2. If there is one, load and activate the SOAP message handler extension program; again, because this is simply another application, follow the same procedure for loading and activating any application. 3. Load the SOAP message handler deployment descriptor for WS-Addressing (Example 13-3 on page 232) by FTPing the file in binary form to the z/TPF file system under the /etc/tpf-ws/ directory. 4. Activate the SOAP message handler deployment descriptor by entering the ZWSAT command with the DEPLOY parameter to deploy the SOAP message handler.

The TPF Toolkit provides an action to load the deployment descriptor file using FTP to send the file to the z/TPF file system. TPF Toolkit can also activate the deployment descriptor by using the DEPLOY action for a selected Web service resource shown in the Remote Systems Explorer (RSE).

13.7.3 Deploying the web service provider and consumer

The next step is to deploy the web service provider and consumer applications and their deployment descriptors.

To deploy a Web service to the z/TPF system: 1. Follow your normal procedure for loading and activating the web service provider application. 2. Load and activate the web service wrapper. Because this is simply another application, follow the same procedure for loading and activating any application. 3. Load the provider web service deployment descriptor (Example 13-1 on page 230) by FTPing the file in binary form to the z/TPF file system under the /etc/tpf-ws/ directory. 4. Activate the provider Web service deployment descriptor by entering the ZWSAT command with the DEPLOY parameter to deploy the Web service.

Important: You should validate the WSDL file and test the Web service before you deploy the Web service. TPF Toolkit can help you to do this.

To deploy a consumer web service to the z/TPF system: 1. Follow your normal procedure for loading and activating the application. 2. Load and activate the Web service stub. Because this is simply another application, follow the same procedure for loading and activating any application. 3. Load the consumer Web service deployment descriptor (Example 13-5 on page 233) by FTPing the file in binary form to the z/TPF file system under the /etc/tpf-ws/ directory.

Chapter 13. z/TPF WS-Security wrapper 245 4. Activate the consumer Web service deployment descriptor by entering the ZWSAT command with the DEPLOY parameter to deploy the Web service.

TPF Toolkit provides an action to load the deployment descriptor file using FTP to send the file to the z/TPF file system. TPF Toolkit can also activate the deployment descriptor by using the DEPLOY action for a selected Web service resource shown in the Remote Systems Explorer (RSE).

13.8 Generating keys

Generate and activate the key in the z/TPF secure key keystore using the following ZKEYS commands. Go to the IBM TPF Product Information Center for more details about the ZKEYS command:  ZKEYS GENERATE ENC-LOCALENC DEC-LOCALDEC CIPHER-AES128CBC NEW  ZFILE mkdir /your_backup_dir  ZKEYS BACKUP PATH-/your_backup_dir/your_backup_filename PASSWORD-your_backup_password  ZKEYS ACTIVATE ENC-LOCALENC DEC-LOCALDEC

13.9 Running the application

The WS-Security SOAP consumer sample application demonstrates the use of web services Security (XML Encryption) on z/TPF. See Chapter 8, “z/TPF SOAP consumer processing” on page 139 for information about how to create a SOAP consumer application or download and install the Sample SOAP Consumer Application for /CalculatorService from the following website: http://www.ibm.com/software/htp/tpf/maint/toolsztpf.html

You will also need to define a mechanism for activating the sample SOAP consumer application.

The application invokes the /CalculatorService sample Web service on z/TPF. The /CalculatorService exposes two operations: add and sub. You can specify which operation to invoke, along with the two values that are to be added or subtracted.

The expected input format for the sample SOAP consumer application is as follows: ZCALC operation VAL1-value1 VAL2-value2 [Transport-transport] [Mep-mep] [TImeout-to]

For example: ZCALC add VAL1-6 VAL2-77 TRANSPORT-HTTP MEP-SYNC

The response should look like this: CALC0100I 16.52.22 RESPONSE RECEIVED FOR /CalculatorService Synchronous call to add operation was successful HTTP transport was used Result of 100 plus 400 is 500 END OF DISPLAY

246 z/TPF Application Modernization using Standard and Open Middleware The fact that encryption was used is transparent to the application, so the results of running the command will not indicate that encryption was used in any way.

Chapter 13. z/TPF WS-Security wrapper 247 248 z/TPF Application Modernization using Standard and Open Middleware Part 6

Part 6 z/TPF in open systems

This part of the book describes porting open systems applications to z/TPF, the z/TPF Internet mail server, and additional examples of z/TPF in an SOA environment.

This part contains the following chapters:  Chapter 14, “Porting open system applications to a z/TPF system” on page 251  Chapter 15, “z/TPF Internet mail server” on page 263  Chapter 16, “z/TPF HTTP client support” on page 281  Chapter 17, “Additional examples of z/TPF in an SOA environment” on page 293

© Copyright IBM Corp. 2013. All rights reserved. 249 250 z/TPF Application Modernization using Standard and Open Middleware 14

Chapter 14. Porting open system applications to a z/TPF system

This chapter introduces the open system Internet protocols that the z/TPF system supports, which are the Internet servers and application programming interfaces (APIs) that the z/TPF system provides to ease the porting of open system applications to the z/TPF system. This chapter demonstrates the flexibility of the z/TPF system by discussing some of the open system middleware functions (OpenLDAP, MySQL) that are available on the z/TPF platform. It also discusses ASCII and EBCDIC character conversion while porting applications from an open system to a z/TPF system.

This chapter includes the following topics:  14.1, “Open system Internet protocols support” on page 252  14.2, “Lightweight Directory Access Protocol ” on page 258  14.3, “Structured Query Language” on page 259  14.4, “Character conversion” on page 260

© Copyright IBM Corp. 2013. All rights reserved. 251 14.1 Open system Internet protocols support

This section introduces the open system Internet protocols supported on a z/TPF system:  File Transfer Protocol (FTP)  Trivial File Transfer Protocol (TFTP)  Hypertext Transfer Protocol (HTTP)

Additionally, there are Internet servers, including FTP server, TFTP server, and HTTP server, on a z/TPF system. There is also FTP client support on a z/TPF system.

The z/TPF system also supports Secure Sockets Layer (SSL) to establish secure connections to and from a z/TPF system. The SSL support on the z/TPF system is based on openSSL version 0.9.7 open source package. The package can be downloaded from the following website: http://www.openssl.org/source/

See the NEW section on security for more details.

14.1.1 File Transfer Protocol client and server support

The FTP client on the z/TPF system allows you to transfer files to or from a remote server. This is done by using the ZFTPC DEFINE command to set up an FTP client profile. Then, specify options in the profile that are required to connect to a remote server and perform file transfers.

Use the ZFTPC ALTER command to change an FTP client profile. A default FTP client profile called TPFDEF is always available. The default transfer options are:  NETRC: ~/.netrc, which specifies the home directory (from the exported HOME environment variable).  PASSIVE: NO, which specifies that the sessions created will not use passive mode.  SSL: NO, which specifies that the connection will not use Secure Sockets Layer (SSL).  CREATEDIR: NO, which specifies that if directories do not exist, they will not be created.  APPEND: NO, which specifies that the files that are transferred will replace the existing ones.  TYPE: TEXT, which specifies that the data transfer type is text.  TIMEOUT: 300, which specifies that after 300 seconds, the file transfer will time out.

You can transfer files using the FTP client in single command mode or interactive mode. In single command mode, use the ZFTPC GET or ZFTPC PUT command, specifying the FTP client profile (optionally) and file information. In interactive mode, use the ZTPFC CONNECT command to connect to the remote server and get an FTP session identifier (ID). Then, use the ID and the ZFTPC GET or ZFTPC PUT command to get and put multiple files to or from the remote server. Use the ZFTPC EXIT command (or other commands) to end the FTP session.

Applications can use FTP client APIs on the z/TPF system to transfer single or multiple files in their applications to or from an FTP server that might be in another system. The FTP client is not shipped as part of the TPF base code. Instead, FTP client support depends on the libcurl library.

252 z/TPF Application Modernization using Standard and Open Middleware Setting up the libcurl library To set up the libcurl library, go to the following site, and click the Curl package link: http://www.ibm.com/software/htp/tpf/pages/ztpf.htm

Use the installation instructions in the readme.txt file included with this download to set up, compile, and load the libcurl library on your z/TPF system. Before you build the FTP client code, you must specify LIBCURL=YES for the CONFIG macro to enable the libcurl library for FTP client support. If you build CURL and the other new shared objects (CFTC, CFTF, and CTMW) without first setting the LIBCURL parameter and running SIP Stage 1 (to set the correct environment variable), the FTP client will not be enabled when you build the FTP client code.

To transfer a single file, call the tpf_ftpGet1 or tpf_ftpPut1 function.

Use the following steps to transfer multiple files: 1. Optionally call the tpf_ftpGetOpts or tpf_ftpSetOpts function to get or set the file transfer options for an FTP connection. 2. Call the tpf_ftpConnect function to connect to a remote FTP server. 3. Call the tpf_ftpGet or tpf_ftpPut function to transfer files to or from a remote FTP server.

Example 14-1 uses FTP client APIs to put a file (/u/myUserID/somefile.txt) from the file system to a remote FTP server at someftpsite.com. The file is placed on the remote FTP server in the /tmp directory with the same file name specified in the source path name. Then the application gets a file (/tmp/somefile1.txt) from the remote system and places it under the z/TPF system directory (/u/myUserID/) with the same name.

Example 14-1 Sample application using FTP client APIs LIBS := CTMW #include #include void FTPT() { int ftpSessID; struct t_ftpConn connectInfo = {0}; int rc; char *sourceFile = "/u/myUserID/somefile.txt"; char *destFile = "/tmp/"; char *sourceFile1 = "/tmp/somefile1.txt"; char *destFile1 = "/u/myUserID/"; struct t_ftpOpts ftpOptions; long timeoutInd; connectInfo.machine = "someftpsite.com"; connectInfo.username = "anonymous"; connectInfo.password = "[email protected]"; /****************************************************************/ /* Connect to the FTP server. */ /****************************************************************/ ftpSessID = tpf_ftpConnect (&connectInfo); if (ftpSessID == -1) { printf ("Error connecting to FTP server"); exit (0); }

Chapter 14. Porting open system applications to a z/TPF system 253 else { printf ("Connection established to FTP server"); } /****************************************************************/ /* Get the options for this FTP session. */ /****************************************************************/ rc = tpf_ftpGetOpts (ftpSessID, &ftpOptions, &timeoutInd); if (rc == -1) { printf ("Error getting options for FTP session"); tpf_ftpDisconnect(ftpSessID); exit (0); } else { if (ftpOptions & TPF_FTP_PASV) { /* Set options to be used on file transfers. */ /***************************************************************/ rc = tpf_ftpSetOpts (ftpSessID, (enum t_ftpOpts)(TPF_FTP_NOPASV)); if (rc == -1) { printf ("Error setting options for FTP session"); tpf_ftpDisconnect(ftpSessID); exit (0); } else { printf ("Options successfully set for FTP session\n"); } } } /****************************************************************/ /* Put the file to the FTP server. */ /****************************************************************/ rc = tpf_ftpPut (ftpSessID, sourceFile, destFile); if (rc == -1) { printf ("Error putting file"); tpf_ftpDisconnect(ftpSessID); exit (0); } else if (rc == -2) { printf ("Session was disconnected after transfer attempt"); } else { printf ("Put file"); } /****************************************************************/ /* Get the file from the FTP server. */ /****************************************************************/ rc = tpf_ftpGet (ftpSessID, sourceFile1, destFile1);

254 z/TPF Application Modernization using Standard and Open Middleware if (rc == -1); { printf ("Error getting file"); tpf_ftpDisconnect(ftpSessID); exit (0); } else if (rc == -2) { printf ("Session was disconnected after transfer attempt"); } else { printf ("Got file"); } /***************************************************************/ /* Disconnect from the FTP server./ /***************************************************************/ rc = tpf_ftpDisconnect(ftpSessID); if (rc == -1) { printf ("Error disconnecting from FTP server"); } else { printf ("Successfully disconnected from FTP server\n"); } }

To establish a secure FTP client session using SSL, you must create one or more FTP client configuration files for SSL and place them in the /etc/ssl/ftpc/ directory on the z/TPF system. The configuration files must use the following naming convention, /etc/ssl/ftpc/machine.conf. Example 14-2 shows the coding.

Example 14-2 Sample FTP client configuration file for SSL USESSL=try VERSION=TLSv1 CIPHER=RC4-MD5,RC4-SHA,DES-CBC-MD5,DES-CBC3-MD5,DES-CBC-SHA,DES-CBC3-SHA VERIFYPEER=1 CAINFO=/etc/ca/certauth.conf

In Example 14-2:  USESSL specifies whether the application session will use SSL. The value try indicates that the connection should be established using SSL. However, if the connection cannot be made secure with SSL, the z/TPF system will try to establish a connection that is not secure.  VERSION specifies the version of SSL that the z/TPF system will use. In this example, TLS version 1 is used.  CIPHER specifies the cipher list and indicates the preference order of ciphers that will be used for the SSL connection. Each cipher is separated by a comma.  VERIFYPEER specifies whether the peer SSL certificate will be verified by the z/TPF system and how it will be verified. The value 1 indicates that the peer certificate will be verified using the file name that is specified for the CAINFO parameter.

Chapter 14. Porting open system applications to a z/TPF system 255  CAINFO specifies the fully qualified path name of the file that contains one or more certification authority (CA) certificates. This is only required when the value 1 is specified for the VERIFYPEER parameter.

The FTP server in the z/TPF system is the Internet server application. On the z/TPF system, all Internet server applications are started and controlled by an Internet daemon. When the Internet daemon is started, a long-running process called the Internet daemon monitor is created. The primary functions of the Internet daemon monitor are to:  Start Internet daemon listeners as processes for Internet server applications.  Restart an Internet daemon listener if an error causes the listener process to end.

Tip: The Internet daemon monitor attempts to restart an Internet daemon listener a maximum of five times.

 Recycle all Internet daemon listener processes if the system activation number changes to allow an online program load (OLDR functions) to occur. Recycling includes stopping and then restarting listener processes without disrupting network traffic.

The Internet daemon listeners monitor Internet server applications, and create and monitor sockets for Internet server applications based on the process model defined for the Internet server application. Use the ZINET START command to allow the Internet daemon to start an Internet daemon listener process for the specified Internet server application. Use the ZINET STOP command to stop the Internet daemon from starting the Internet daemon listener processes for the specified Internet server application.

The FTP server communicates with the remote node on the well-known port 21. During this communication, the FTP server establishes two connections, one connection for control information (commands and responses) and the other for data transferred. The FTP client on the remote host is prompted for access information, such as login name and password. The FTP server authenticates users according to the following rules:  The login name must be in the etc/passwd database and cannot be a null password.  The login name must not be in the etc/ftpusers file.  If the user name is anonymous or ftp, an anonymous ftp account must be present in the password file. In this condition, the remote FTP client can log in by specifying any password.

14.1.2 Trivial File Transfer Protocol server support

The TFTP server is also a socket application on the z/TPF system, started by the Internet daemon. The TFTP server communicates with the client on the well-known port 69. Use the ZINET ADD command to add the TFTP server application to the Internet daemon.

The behavior of the TFTP server is controlled by the TFTP server configuration file /etc/tftp.conf, shown in Example 14-3.

Example 14-3 Sample TFTP server configuration file LOG = /tmp/tftp.log AUTH = 444 allow:/tmp deny:/tmp/tmp

256 z/TPF Application Modernization using Standard and Open Middleware In Example 14-3 on page 256:  LOG specifies the name of file where TFTP server records status lines. If it is not specified, the /tmp/tftp.log file is used.  AUTH specifies the file access permissions that are set for all files written by TFTP server. The access permissions must be three octal characters (0-7), representing owner, group, and other users respectively.  allow specifies a directory where files can be accessed (read or write). All subdirectories are also accessible unless it is specifically prohibited with a deny directive.  deny specifies the name of directory where files cannot be accessed. All subdirectories are also not accessible, unless there is an allow directive specifically for that subdirectory.

To transfer a file using the TFTP server, you can use the TFTP command that is appropriate on your own system. For example, use the TFTP command from a Windows NT system, by specifying the Internet address (IP) of the z/TPF system, the file to be transferred, and the file to be stored on the z/TPF system. The TFTP client is not provided on the z/TPF system.

14.1.3 Hypertext Transfer Protocol server support

An HTTP server is not provided as part of the base TPF system. However, using TPF Internet server support, an HTTP server can be installed on the TPF system, for example, the Apache 2.2 server. Through installing an HTTP server on the TPF system, Web pages can be deployed on the HTTP server, and then be retrieved by a Web browser, or a remote client, from the HTTP server on the TPF system.

Use the ZINET ADD S-APACHE command to add an Apache server to the Internet daemon, and start the server using the ZINET START S-APACHE command. Then you can request Web pages from the TPF system based on the HTTP server. Example 14-4 shows the command that starts the Apache server.

Example 14-4 Start Apache server using ZINET START ZINET START S-apache CSMP0097I 17.06.03 CPU-B SS-BSS SSU-HPN IS-01 INET0017I 17.06.03 SERVER APACHE STARTED+

Use the ZINET DISPLAY S-APACHE command to view the status of the Apache server, as shown in Example 14-5.

Example 14-5 Display status of Apache server using ZINET DISPLAY ZINET DISPLAY S-apache CSMP0097I 17.08.19 CPU-B SS-BSS SSU-HPN IS-01 INET0031I 17.08.19 START OF ZINET DISPLAY OF ACTIVE SERVER SERVER - APACHE PROCID - BACTIVATION - OPER PGM - CA2M PARM - PROTOCOL - PORT - 00000 MODEL - DAEMON SERVERRORS - 00000 SERVETIME - 00000 USER - nobody MAXPROC - 00001 TIMEOUT - 00000 STATE - NORM AORLENGTH - 00000 BACKLOG - 00000 IP - ANY SOCKET - 00000000/00000000 COUNT - 0000000023 TOTAL COUNT - 0000000023

END OF DISPLAY+

Chapter 14. Porting open system applications to a z/TPF system 257 14.2 Lightweight Directory Access Protocol

The LightWeight Directory Access Protocol (LDAP) is an industry standard mechanism to provide a basic directory structure for the storage of data. LDAP defines the means to read or update (write) data that is stored on the LDAP server, providing a commonly understood means to access data.

14.2.1 LDAP directories

An LDAP directory is a relatively simple database that contains both a piece of data and information about the data. Common examples of directories are a corporate-wide phone book, and a single sign-on mechanism (userID and password). Keep in mind that, while the directory is referred to as a database, it is a database of limited design — it is the protocol that suggests the format of the data and how it will be stored. For example, the LDAP data interchange format (LDIF) provides for a common format of the directory data. The data itself is organized as entries containing a collection of information. Each entry has a unique key called a distinguished name (DN) and a set of attributes that describe the data in that entry. The user therefore can build directory elements choosing a set of attributes for their particular needs.

To learn more about a specific implementation of LDAP and how LDIF is used, go to the following website: http://www.openldap.org

See the OpenLDAP Admin Guide for general information and examples.

14.2.2 Benefits of LDAP in a z/TPF environment

Using the single sign-on example is a good way to explain the potential role of LDAP on a z/TPF system. If you accept our earlier premises — that z/TPF is big, and fast, and good at processing transactions — you can understand why you might want to use z/TPF as the server providing authentication capabilities to a corporate network.

Most corporations these days have a plethora of systems, and each typically has its own userID and password mechanism built in. The challenge is that as the corporation implements more systems, an individual’s list of userIDs grows. Many of us have experienced this and wished for a means by which we can abide by corporate rules, but have just a single userID and password for multiple systems.

One component of this solution would be something that can manage the userID and password and serve up the validation quickly. This is the LDAP server on your z/TPF host. The issue now is that you want to communicate to this central host from any number of other systems, each of those other systems running any number of variations of operating systems (from any number of vendors). That is where SOA comes in — SOA’s purpose allows like and unlike systems to communicate.

Therefore, and again as an example, if you use LDAP on your z/TPF system to do the verification, and you SOA enable your z/TPF (and other) systems, you have a solution that allows you to roll single sign-on out to a large enterprise.

Using a standard protocol to access data can have many other benefits including access to data. Data stored on z/TPF that can easily be used by z/TPF applications and applications running on another platform. z/TPF applications can also access data on distributed platforms. These LDAP functions are enabled on z/TPF through OpenLDAP server and client

258 z/TPF Application Modernization using Standard and Open Middleware support. OpenLDAP is well-known in the industry. It is based on open source standard application programming interfaces (APIs) and works as a common data management system across platforms. The z/TPF system makes a high availability OpenLDAP server and allows for fast local response time for OpenLDAP client calls.

14.3 Structured Query Language

If you are familiar with SOA, you might be wondering why Structured Query Language (SQL) has worked its way into this chapter. SQL provides an interface to store data into a relational database. Although zTPF currently supports SQL where data is stored in a remote relational database using z/TPFAR support, it can be advantageous to use a solution where the relational database resides on z/TPF in a SOA environment.

14.3.1 LAMP

LAMP is an acronym for Linux, Apache, MySQL, and PHP (or PERL or Python). It is often used to described a combination of software that, while not developed together, provide basic application server functionality:  Linux is the platform.  Apache the means to serve (and request) data and functions.  MySQL is the means to store data in a relational database.  PHP/PERL/Python is the means to provide function (code).

While z/TPF is not considered to be an application server, it is an excellent transaction server. Nonetheless, there is often a requirement to provide basic application server function within even z/TPF.

z/TPF is not a Linux distribution. However, z/TPF is a platform that provides similar protocol functionality to Linux distributions, while maintaining the characteristics that have made z/TPF an industry standard high-end transaction server.

As previously mentioned, z/TPF supports the Apache Web server and as such provides support for the HTTP. In addition, the z/TPF base includes the z/TPF HTTP server as an alternative to the Apache HTTP server. The main purpose of the z/TPF HTTP server is to provide a simple network transport HTTP server to receive and forward messages (SOAP or other) to applications. z/TPF allows the user to code Common Gateway Interface (CGI) for the Web server using C/C++.

z/TPF provides the open source relational database MySQL. MySQL is a database server with the ability to access a relational database on the z/TPF system by using the Structured Query Language (SQL) application programming interfaces (APIs). z/TPF support for MySQL provides a database management system with querying and connectivity capabilities, as well as excellent data structure and integration with many different platforms. By using z/TPF support for MySQL you have the ability to port existing applications that use an SQL interface to the z/TPF system and to use a relational database on the z/TPF system for new applications. The MySQL server works in a client and server system. This system includes a multiple-threaded SQL server that supports varied back ends, different client programs and libraries, administrative tools, and many application programming interfaces.

Chapter 14. Porting open system applications to a z/TPF system 259 14.3.2 Benefits of SQL on z/TPF

Many open source packages expect data, for example configuration data, to reside in a SQL based database. Converting such an application to use a z/TPF native file access method, especially for rarely used data, such as configuration data, is challenging and lengthens the time to port the open source package to z/TPF. To fill this gap, MySQL has been ported to run on z/TPF.

This is, of course, not the only reason why a user might desire that some level of relational data reside on z/TPF. If a remote application requests data from z/TPF, and it is used to the data being stored in a relational manner, avoiding the cost of decomposing the structures into other formats to get the data on z/TPF would be desirable.

z/TPF is not designed to be an SQL server, and would not be expected to be able to compete with systems designed for this purpose. However, it is likely that there will be requirements, especially in an SOA environment, to provide access to such data in a relational format. If the data being requested is native to z/TPF because of the proximity to the application, exporting the data from z/TPF into a remote relational database, just to serve to yet another system, might not make sense — the issues with synchronization of distributed databases can prevent this from being a viable solution in a high demand environment.

In other words, there are situations in which it might make sense to allow storage of relational information within the z/TPF system itself, to reduce the complexity of a application solution. MySQL, an open source package, has been ported to z/TPF to provide such function.

14.4 Character conversion

This section discusses ASCII to EBCDIC character set conversion while porting open system applications to z/TPF. For example, the definition of the function fopen in stdio.h. is fopen(const char *filename, char *mode). The two parameters, filename and mode, are ASCII strings, while the z/TPF system expects an EBCDIC string. For this condition, character conversion is required.

Use the following steps for character conversion: 1. Using the function foobar (in foobar.h) as an example: a. Create the a2e wrapper of function foobar, atoe_foobar, which converts the parameter string from ASCII to EBCDIC and then call foobar. b. Create the header file for atoe_foobar, as shown in Example 14-6.

Example 14-6 Header file of atoe_foobar, the a2e wrapper of function foobar #include next #if defined(IBM ATOE) #if !defined(IBM ATOE STDIO) #define IBM ATOE STDIO

#ifdef cplusplus extern "C" { #endif int atoe foobar (char *); #ifdef cplusplus } #endif

260 z/TPF Application Modernization using Standard and Open Middleware #undef foobar #define foobar atoe foobar #endif #endif

2. Create the real implementation of atoe_foobar, the wrapper of function foobar, in atoe.c, as shown in Example 14-7.

Example 14-7 Implementation of atoe_foobar, the a2e wrapper of function foobar int atoe foobar (char *foo) { int ret; char *e; Log(1,"Entry: atoe foo\n"); e = a2e string((char *) foo); ret = foobar(e); free(e); return ret; }

In the implementation, the wrapper atoe_foobar finally calls the real function foobar and returns the result. The a2e_string is the function to convert the ASCII string to an EBCDIC string. The function a2e_string is based on the iconv character conversion function on the z/TPF system. 3. Finally, when porting the open system application to the z/TPF system, specify header file foobar.h as the header file of wrapper function atoe_foobar, instead of that of function foobar, to make sure that the wrapper function is called to do character conversion before the real function foobar is called.

Chapter 14. Porting open system applications to a z/TPF system 261 262 z/TPF Application Modernization using Standard and Open Middleware 15

Chapter 15. z/TPF Internet mail server

This chapter introduces the Internet mail server on the z/TPF system. Users, or mail clients, interact with the z/TPF Internet mail server to send and retrieve Internet mail. The z/TPF Internet mail server allows for a design point of up to millions of mailboxes.

The z/TPF Internet mail server support takes advantage of the high-performance, availability, and reliability characteristics of the z/TPF system to provide a high-volume, high-speed mail server that can scale up to handle large numbers of users and mail items. The z/TPF Internet mail servers can reduce the cost of ownership of a large Internet mail service with a single-image system, simplifying system management and operations.

This chapter contains the following topics:  15.1, “z/TPF Internet mail server overview” on page 264  15.2, “z/TPF Internet mail server configuration files” on page 266  15.3, “z/TPF Internet mail server administration” on page 270  15.4, “z/TPF Internet mail server client” on page 277

© Copyright IBM Corp. 2013. All rights reserved. 263 15.1 z/TPF Internet mail server overview

The z/TPF Internet mail server includes the SMTP server, IMAP server, and POP3 server and supports the following standard Internet protocols:  Simple Mail Transfer Protocol (SMTP)  Internet Message Access Protocol (IMAP) Version 4  Post Office Protocol (POP) Version 3

SMTP describes how mail message are delivered from one server to another. IMAP and POP describe how mail messages on the mail server are retrieved by the mail client. In other words, SMTP handles the Internet mails being sent to a server, and IMAP and POP handle the retrieval of these mails from the server.

These servers implement those standard Internet mail protocol on the z/TPF system and provide related services. z/TPF also provides mail API support. Figure 15-1 on page 265 shows the interrelationships of the actions and protocols that are involved when sending and receiving Internet mail on the z/TPF system.

264 z/TPF Application Modernization using Standard and Open Middleware Mail Client 1 Mail Client 2

Sends Reads mail mail

Internet mail Internet mail exchange name, exchange name, Remote such as tpf.com such as tpf.com server IMTP port 143 SMTP port 25 POP port 110 z/TPF

Accepts logon Receives and SMTP Remote examines mailbox forwards mail server server retrieves mail

Local delivery Mail Database

Remote Mail Mail Mail delivery Mail Mail items SMTP items items itemsMail items items

Remote Receives and server forwards mail

Remote delivery SMTP Mail Database

Remote Receives and server forwards mail

Figure 15-1 z/TPF Internet mail server overview

When sending mail to another user, the mail client (Mail Client 1 in Figure 15-1) must use SMTP to put mail in the Internet mail system. Typically, the mail client uses a mail server client program such as Microsoft Outlook, Netscape, or other client program. This client program connects to the SMTP server on the well-known port 25 and sends the mail. On the z/TPF system, the SMTP server is based on the Secure Mailer, also known as Postfix. For more information about Postfix, see the following website: http://www.postfix.org

When the SMTP server stores the mail, the server indicates to Mail Client 1 that it has received the mail so that the client can disconnect or send more mail. The SMTP server must determine if this mail is destined for a user on a local domain (where the SMTP server is running) or for a user on a remote domain. If the mail is for a user on the local domain, the SMTP server calls the local delivery function. If the mail is for a user on a remote domain, the

Chapter 15. z/TPF Internet mail server 265 SMTP server becomes an SMTP client and attempts to contact the server for that domain to transfer the mail item and delete it from local storage.

At some point, the receiving mail client (Mail Client 2) attempts to check the mail. Similarly to Mail Client 1 with SMTP, Mail Client 2 uses a mail server client program that connects to the IMAP server on well-known port 143, or to the POP server on well-known port 110, and retrieves the mail. On the z/TPF system, the IMAP and POP servers are based on the Cyrus project. For more information about the Cyrus project, go to the following website:

http://cyrusimap.web.cmu.edu/

POP retrieves the mail item, sends the mail to the user and, optionally, deletes the copy from the mail server to free the resources of the server. IMAP allows the client to keep the mail in mailboxes on the server, and provides operations for creating, deleting, and renaming mailboxes and other mail and mailbox management functions.

15.2 z/TPF Internet mail server configuration files

The configuration files control the behavior of the z/TPF Internet mail server. The following configuration files must be located in the basic subsystem (BSS):  /etc/postfix/main.cf, which specifies the configuration parameters for the SMTP server.  /etc/imapd.conf, which specifies configuration parameters for the IMAP and POP server.  /etc/tpf_mail.conf, which specifies z/TPF-unique configuration information.

The following configuration files are optional:  /etc/postfix/access, which specifies access list. The access list directs SMTP server to selectively accept or reject mails from specific host, domain, network, or mail address.  /etc/aliases, which must be located in BSS and specifies mail system owner and domain owner.

The following sections provides examples of the three configuration files and describes the parameters for the configuration files.

15.2.1 SMTP server configuration file

Example 15-1 shows the SMTP server configuration file, /etc/postfix/main.cf.

Example 15-1 Sample SMTP server configuration file mail_name = IBM TPFMail Box myhostname = tpfosa2h100.pok.ibm.com mydomain = pok.ibm.com mynetworks = 9.0.0.0/8 maximal_queue_lifetime = 4 minimal_backoff_time = 300 smtpd_client_restrictions = check_client_access smtpd_sender_restrictions = check_sender_access ignore_mx_lookup_error = yes smtpd_helo_required = no

Table 15-1 on page 267 describes the parameters for the SMTP server configuration file.

266 z/TPF Application Modernization using Standard and Open Middleware Table 15-1 SMTP server configuration file parameters Parameter Description

mail_name Can be any character string and specifies the mail system name. If you do not specify a value, mail_name is set to Postfix.

myhostname Specifies the host name of the z/TPF Internet mail server system, in fully qualified domain name format. This parameter is required.

mydomain Specifies the domain name of the z/TPF Internet mail server system. If you do not specify a value, the value is derived from the value of myhostname by stripping off the first component.

mynetworks Lists all of the networks that are attached to z/TPF Internet mail server system. The format is ipaddr/mask.

maximal_queue_lifetime Specifies the number of days a mail item can stay in the deferred queue before it is sent back as undeliverable. The default value is five days.

minimal_backoff_time Specifies the minimum amount of time between delivery attempts of a deferred mail item. The default value is 1000 seconds.

smtpd_client_restrictions Specifies the kind of restrictions you want to apply when the client connects. The value check_client_access checks the access list file (/etc/postfix/access) and accepts or rejects according to the setting in the access list.

smtpd_sender_restrictions Specifies the kind of restrictions you want to apply when client sends a MAIL FROM command. The value check_sender_access checks the access list file (/etc/postfix/access) and accepts or rejects the requests accordingly.

ignore_mx_lookup_error Specifies how you want delivery manager to handle errors from a mail exchange (MX) query. The value Yes ignores an MX query error and proceeds to search for an address record.

smtpd_hello_required Specifies whether or not the connecting client is required to send a HELLO (or EHLO) command at the beginning of a session. You can specify either yes (default) or no.

15.2.2 IMAP and POP server configuration file

Example 15-2 shows the IMAP and POP server configuration file, /etc/imapd.conf.

Example 15-2 Sample IMAP/POP server configuration files quotawarn: 90 timeout: 30 poptimeout: 1 popminpoll: 0 autocreatequota: 1000

Table 15-2 on page 268 describes the parameters for the IMAP and POP server configuration file.

Chapter 15. z/TPF Internet mail server 267 Table 15-2 IMAP/POP server configuration file parameters Parameter Description

quotawarn Specifies the percent of storage that can be used for a mailbox before the z/TPF mail server sends a warning message to the client. If you do not specify a value, quotawarn is set to 90.

timeout Specifies how long the IMAP server will wait before logging off because of inactivity. The default value is 30 minutes.

poptimeout Specifies how long the POP server will wait before logging off because of in activity. The default value is 10 minutes.

popminpoll Specifies the minimum amount of time the server forces user to wait to check mail before the last time mail was checked. The default value is 0 minutes.

autocreatequota Specifies the quota value or storage limit for a mailbox when it is created. The value is the maximum number of 4-k records that the mailbox can use. A quota value of 0 indicates that there is no storage limit. The default value is 256.

15.2.3 z/TPF-unique configuration information file

Example 15-3 shows the z/TPF-unique configuration information file, /etc/tpf_mail.conf.

Example 15-3 Sample tpf_mail.conf file, including z/TPF-unique configuration information MAX_HANGING_RECEIVE_MANAGERS: 300 MAX_LOCAL_DELIVERY_MANAGERS: 80 MAX_REMOTE_DELIVERY_MANAGERS: 10000 MAX_DEFERRED_DELIVERY_MANAGERS: 10000 AQ_POP_TIMER_INTERVAL: 2 DQ_POP_TIMER_INTERVAL: 60 DEFER_Q_BACKOFF: 1 MAIL_SSID: BSS MAIL_DOMAIN01: 249999991 tpfosa2h100.pok.ibm.com 9.57.13.228

Table 15-3 describes the configuration parameters in the /etc/tpf_mail.conf file.

Table 15-3 z/TPF-unique configuration file parameters Parameter Description

MAX_HANGING_RECEIVE_MANAGERS This is a decimal number and specifies the number of concurrent entry control blocks ECBs that can accept mail. The default value is 0, which means there is no limit and the z/TPF system doesn’t validate.

MAX_LOCAL_DELIVERY_MANAGERS This is a decimal number and specifies the number of concurrent ECBS that can deliver mail to local mail box.

MAX_REMOTE_DELIVERY_MANAGERS This is a decimal number and specifies the number of concurrent ECBS that can delivery mail to remote mail domains.

MAX_DEFERRED_DELIVERY_MANAGERS This is a decimal number and specifies the number of concurrent ECBS that can process items on the deferred mail queue.

268 z/TPF Application Modernization using Standard and Open Middleware Parameter Description

AQ_POP_TIMER_INTERVAL Specifies the maximum amount of time for the z/TPF system to acknowledge the receipt of mail items from a remote client. The minimum value is 1 second. This is a required parameter.

DQ_POP_TIMER_INTERVAL Specifies how often the z/TPF system will process the mail items in the deferred queue. The minimum value is 1 second. This is a required parameter.

DEFER_Q_BACKOFF Specifies the minimum amount of time the server will wait to deliver mail from deferred queue after a previous attempt failed.

MAIL_SSID Specifies the name of the z/TPF subsystem in which you want the z/TPF Internet mail servers to run. This is a required parameter.

MAIL_DOMAINxx Contains the value of the following format:  Prime domain ipaddr, where xx is the fixed record type associated with the domain.  Prime is a number to distribute user account across the database,  Domain indicates mail domain  ipaddr specifies one or more Internet Protocol (IP) addresses for the domain in dotted decimal format.

15.2.4 z/TPF mail server access list configuration file

Example 15-4 shows the z/TPF mail server access list configuration file, /etc/postfix/access.

Example 15-4 Sample /etc/postfix/access file, including access list configuration # ------# # Access List Configuration File # # File Name: /etc/postfix/access # www.greatstuff.com ACCEPT www.nogood.com REJECT

Each line of the access list configuration file /etc/postfix/access must be in the following format: pattern action

Where pattern matches a mail address, domain, or host address. The SMTP server performs the corresponding action.

Specify pattern in one of the following ways:  user@domain, which matches a specific mail address.  domain.name, which matches the domain name itself and any subdomains of that domain, either in host names or in mail addresses. Top-level domains (such as domains that end in .com or .org) will never be matched.  user@, which matches all mail addresses with the specified user part.  net.work.address, which matches any host address in the specified network. A network address is a sequence of one or more octets separated by a period (.). You can specify all or part of a network address.

Chapter 15. z/TPF Internet mail server 269 Specify one of the following possibilities for action:  ACCEPT, which indicates to accept mail from the address that matches the specified pattern.  REJECT, which indicates to reject mail from the address that matches the specified pattern.  DUNNO, which indicates to continue checking other restrictions specified for this area. See the smtpd_helo_restictions, smtpd_client_restrictions and smtpd_sender_restrictions parameters in the SMTP configuration file (/etc/postfix/mail.cf) for more information about other restrictions.

15.2.5 Aliases configuration file

Example 15-5 shows the /etc/aliases file, which includes the information about mail system owner and domain owner. To use the administrative mailboxes, you must define a mail user ID that is responsible for handling the administrative features. The mail user ID is identified to the z/TPF Internet mail server by defining an owner in the /etc/aliases file, as follows:

Example 15-5 Sample /etc/aliases file, including mail system owner and domain owner owner-mailadmin: mailboss owner-tpfdomain1.com: bossone owner-tpfdomain2.com: bosstwo

The following list describes the configuration parameters in the /etc/aliases file. Each line in the file contains the mail system owner or domain owner:  owner-mailadmin, which specifies the system administrator for the entire mail system. Define a mailowner mailbox in each main domain. A mail system administrator is not required, but if provided, only one, the last, is used.  owner-domainxxname, which specifies administrators for each mail domain, where domainxxname is the name of a mail domain. Enter an owner line for each mail domain that has an administrator. An administrator is not required for a mail docmain, but if provided, only one, the last, is used.

15.3 z/TPF Internet mail server administration

This section describes the z/TPF Internet mail server administration.

15.3.1 Controlling the z/TPF Internet mail server

Perform the following steps before starting the z/TPF Internet mail server: 1. Bring up your z/TPF system to NORM state and ensure that you have comms set up. 2. Enter ZMAIL START to start the z/TPF Internet mail server. 3. Enter ZMAIL STOP to stop the z/TPF Internet mail server. 4. Enter ZMAIL FLUSH to flush the z/TPF Internet mail server mail queue, that is, delete any mail that is in the active or deferred queues waiting to be delivered.

After being started, the Internet daemons of the z/TPF Internet mail server are displayed as shown in Example 15-6 on page 271.

270 z/TPF Application Modernization using Standard and Open Middleware Example 15-6 Display status of Internet daemons of z/TPF Internet mail server using ZINET DISP ZINET DISP S-POP3 C-F INET0014I 22.13.03 START OF ZINET DISPLAY OF FILE SERVER - POP3 PROCID - BACTIVATION - OPER PGM - CMNP PARM - PROTOCOL - PORT - 00000 MODEL - DAEMON SERVERRORS - 00000 SERVETIME - 00000 USER - nobody MAXPROC- 00001 TIMEOUT - 00000 STATE - NORM AORLENGTH - 00000 BACKLOG - 00000 IP - ANY END OF DISPLAY+

ZINET DISP S-IMAP C-F INET0014I 22.13.03 START OF ZINET DISPLAY OF FILE SERVER - IMAP PROCID - BACTIVATION - OPER PGM - CMNM PARM - PROTOCOL - PORT - 00000 MODEL - DAEMON SERVERRORS - 00000 SERVETIME - 00000 USER - nobody MAXPROC - 00001 TIMEOUT - 00000 STATE - NORM AORLENGTH - 00000 BACKLOG - 00000 IP - ANY END OF DISPLAY+

ZINET DISP S-SMTP C-F INET0014I 22.13.03 START OF ZINET DISPLAY OF FILE SERVER - SMTP PROCID - BACTIVATION - OPER PGM - CMNS PARM - PROTOCOL - PORT - 00000 MODEL - DAEMON SERVERRORS - 00000 SERVETIME - 00000 USER - nobody MAXPROC - 00001 TIMEOUT - 00000 STATE - NORM AORLENGTH - 00000 BACKLOG - 00000 IP - ANY END OF DISPLAY+

You can use ZMAIL STATUS to check the current status of Internet mail server, which also display the statistic information of Internet mail server. Example 15-7 shows that all of the servers are started.

Example 15-7 Display status of z/TPF Internet mail server using ZMAIL STAT ZMAIL STAT INET0031I 16.46.25 START OF ZINET DISPLAY OF ACTIVE SERVER SERVER - IMAP PROCID - B ACTIVATION - OPER PGM - CMNM PARM - PROTOCOL - PORT - 00000 MODEL - DAEMON _ SERVERRORS - 00000 SERVETIME - 00000 USER - nobody MAXPROC - 00001 TIMEOUT - 00000 STATE - NORM AORLENGTH - 00000 BACKLOG - 00000 IP - ANY SOCKET - 00000000/00000000 COUNT - 0000000002 TOTAL COUNT - 0000000002 END OF DISPLAY+

INET0031I 16.46.25 START OF ZINET DISPLAY OF ACTIVE SERVER SERVER - POP3 PROCID - B ACTIVATION - OPER

Chapter 15. z/TPF Internet mail server 271 PGM - CMNP PARM - PROTOCOL - PORT - 00000 MODEL - DAEMON _ SERVERRORS - 00000 SERVETIME - 00000 USER - nobody MAXPROC - 00001 TIMEOUT - 00000 STATE - NORM AORLENGTH - 00000 BACKLOG - 00000 IP - ANY SOCKET - 00000000/00000000 COUNT - 0000000002 TOTAL COUNT - 0000000002 END OF DISPLAY+

INET0031I 16.46.25 START OF ZINET DISPLAY OF ACTIVE SERVER SERVER - SMTP PROCID - B ACTIVATION - OPER PGM - CMNS PARM - PROTOCOL - PORT - 00000 MODEL - DAEMON _ SERVERRORS - 00000 SERVETIME - 00000 USER - nobody MAXPROC - 00001 TIMEOUT - 00000 STATE - NORM AORLENGTH - 00000 BACKLOG - 00000 IP - ANY SOCKET - 00000000/00000000 COUNT - 0000000002 TOTAL COUNT - 0000000002 END OF DISPLAY+

MAIL0001I 16.46.25 START OF RESPONSE FROM ZMAIL STAT TPF Internet Mail Server V5P00 The ACCEPT MAIL service has been started The DELIVER MAIL service has been started The READ MAIL service has been started END OF DISPLAY+

MAIL0001I 16.51.07 START OF RESPONSE FROM ZMAIL STAT TPF Internet Mail Server V5P00

Services ACCEPT DELIVER READpop READimap Started Yes Yes Yes Yes

Managers Local Remote Deferred Hanging _ Delivery Delivery Delivery Receive Max 10 10000 10000 100 Current 0 0 0 100

Incoming Accepted SMTP Bytes Active 0 Mail (sec) Transacts In Queue .0 5 0 0 Blocks 0 _ Deferred Reexamine HostRetry (Queue Deferred 0 Mail Msg(sec) (sec) Backoff) Queue .0 60 1 Blocks 0

Delivered Local Msg Local RemoteMsg Remote Bounced Mail Delivered Bytes Delivered Bytes Msgs 0 0 0 0 0

Saved POP3 POP3 IMAP IMAP SMTP Mail Commands Logins Commands Logins Ack

272 z/TPF Application Modernization using Standard and Open Middleware 0 0 0 0 0

Automated Reply Forward Discard Commands 0 0 0 0

mail()API Exist Read Write Get Put 0 0 0 0 0

Verbosity SYSLOG LOG DEBUG TRACECOMM TRACEDNS off off off off off END OF DISPLAY+

15.3.2 Managing client mailboxes

There are a number of ZMAIL commands that allow you to manage client mailboxes. With these commands you can:  Create a new user account  Create or delete a mailbox  Display the users for a mailbox  Display a list of mailboxes  Display or set the storage available for a mailbox  Change the name of a mailbox  Set or change the access control list for a mailbox

For example, after the z/TPF Internet mail server is started, you can erase the contents of the z/TPF Internet mail server queue; therefore, any mail that is waiting to be delivered is removed, as shown in Example 15-8.

Example 15-8 Flush mails in z/TPF Internet mail server ZMAIL FLUSH MAIL0001I 10.23.46 START OF RESPONSE FROM ZMAIL flush Active Queue has been flushed Deferred Queue has been flushed END OF DISPLAY

Next, you can create a new mailbox with an account named kate, for example. A ZMAIL LISTMAILBOX command (ZMAIL LM) is entered to verify that the mailbox was created. You can specify as many as 30 characters for an account name, as shown in Example 15-9.

Example 15-9 Create mailbox in z/TPF Internet mail server ZMAIL CM kate MAIL0003I 15.00.31 cm COMPLETED SUCCESSFULLY. NO OUTPUT TO DISPLAY ZMAIL LM kate MAIL0001I 15.01.35 START OF RESPONSE FROM ZMAIL lm kate.inbox END OF DISPLAY

You can then create submailboxes for the account. The submailbox is hierarchical. A ZMAIL LISTMAILBOX command (ZMAIL LM) is entered to verify that the submailboxes were created, as shown in Example 15-10 on page 274.

Chapter 15. z/TPF Internet mail server 273 Example 15-10 Create submailbox in z/TPF Internet mail server ZMAIL CM kate.inbox.work MAIL0003I 15.00.31 cm COMPLETED SUCCESSFULLY. NO OUTPUT TO DISPLAY

ZMAIL CM kate.inbox.work.project1 MAIL0003I 15.01.00 cm COMPLETED SUCCESSFULLY. NO OUTPUT TO DISPLAY

ZMAIL CM kate.inbox.play MAIL0003I 15.01.30 cm COMPLETED SUCCESSFULLY. NO OUTPUT TO DISPLAY

ZMAIL LM kate MAIL0001I 15.01.55 START OF RESPONSE FROM ZMAIL lm kate.inbox kate.inbox.work kate.inbox.work.project1 kate.inbox.play END OF DISPLAY

You can change the password of the created mailbox. The password can be a one to eight-character password. It can consist of any character allowed by the computer room agent set (GRAS) terminal, as shown in Example 15-11.

Example 15-11 Change password in z/TPF Internet mail server ZMAIL CM kate MAIL0003I 15.00.31 cm COMPLETED SUCCESSFULLY. NO OUTPUT TO DISPLAY

ZMAIL PASSWORD kate kate MAIL0003I 15.00.31 password COMPLETED SUCCESSFULLY. NO OUTPUT TO DISPLAY

You can also set the access control list (ACL) for the mailbox. Example 15-12 shows that account somebody is given look and read access to the created mailbox. A ZMAIL LISTACLMAILBOX command can be used to verify the updated access rights for the given mailbox.

Example 15-12 Set mailbox access control list (ACL) in z/TPF Internet mail server ZMAIL SETACLMAILBOX kate somebody lr MAIL0003I 13.11.31 sam COMPLETED SUCCESSFULLY. NO OUTPUT TO DISPLAY

ZMAIL LISTACLMAILBOX kate MAIL0001I 13.11.31 START OF RESPONSE FROM ZMAIL listaclmailbox kate lrswipcda somebody lr END OF DISPLAY

Finally, you can set the storage limits for various points in the mailbox, as shown in Example 15-13 on page 275. Quota is the storage limit for this resource. A quota value of 0 indicates that there is no storage limit. It is the maximum number of 4-KB pool records that the mailbox (or mailboxes in the hierarchy) can use. If you specify a value that is below the amount of storage currently being used, the next mail item will be rejected. Subsequent mail will be rejected until the amount of storage being used falls below the new quota. The first mail item that causes the quota to be exceeded will be accepted and any mail following that will be rejected. A notification mail can be sent as quota warning mail.

274 z/TPF Application Modernization using Standard and Open Middleware Example 15-13 Set mailbox quota in z/TPF Internet mail server zmail lm tpfuser MAIL0001I 10.05.30 START OF RESPONSE FROM ZMAIL lm tpfuser.inbox tpfuser.inbox.work.project1 tpfuser.inbox.work.project2 tpfuser.inbox.play tpfuser.inbox.todo END OF DISPLAY

zmail setquota tpfuser 1000 MAIL0001I 10.05.49 START OF RESPONSE FROM ZMAIL setquota STORAGE 0/1000 END OF DISPLAY

zmail sq tpfuser.inbox.work 5000 MAIL0001I 10.06.20 START OF RESPONSE FROM ZMAIL sq STORAGE 0/5000 END OF DISPLAY

zmail sq tpfuser.inbox.play 3000 MAIL0001I 10.06.20 START OF RESPONSE FROM ZMAIL sq STORAGE 0/3000 END OF DISPLAY

If there are multiple mail domains defined, you can enter the ZMAIL ADMIN command or the ZFILE export command to set the MAILDOMAIN environment variable followed by regular ZMAIL commands. See 15.3.3, “z/TPF Internet mail server email administration” on page 275 for more information about the ZMAIL commands.

15.3.3 z/TPF Internet mail server email administration

z/TPF Internet mail server support using administrative mail IDs to manage mail domains. To use the administrative mailboxes, you must define a mail user ID that is responsible for handling the administrative features.

The email must be in plain text. The text of the email must contain only the specified commands, up to 1000 lines per email. At least one blank line must follow the commands. For example, the following configuration was defined for an administrative email:  A mailbox was created for a mail administrator named admin, which is the overall administration mailbox, using the ZMAIL CREATEMAILBOX command.  A password was defined for the mail administrator account using the ZMAIL PASSWORD command.  A mailbox was created for a user account named fay using the ZMAIL CREATEMAILBOX command.  In the /etc/aliases configuration file, the following fields were defined: – The owner-mailadmin field was defined as mailmeister. – The owner-domain field was defined as tpfosah21.pok.ibm.com for the mail domain and admin as the mail administrator.

Example 15-14 on page 276 shows that the auto-reply message is changed from active to not active for the account named fay.

Chapter 15. z/TPF Internet mail server 275 Example 15-14 z/TPF Internet mail server email administration Administrative email Contains:

From: [email protected] To: [email protected] Subject: reset reply

reset fay faypw reply

Response email Contains:

From: [email protected] Date: Wednesday, April 09, 2006 9:51 AM To: [email protected] Subject: Re: reset reply

Response to command: "reset fay ******** reply" issued by [email protected] on Wed Apr 9 15:59:11 2006 GMT

Account: [email protected]

Information: Test newinfo

Auto-reply is not active.

Defined Auto-reply message is: I'm out of the office at this time. I'll return your message when I return on May 8, 2006. In my absense, contact Larry Smith for assistance. Thank you. -Fay

Discard incoming mail is active. Starting date and time: Thu May 1 00:00:00 2006 GMT (not started) Ending date and time: Thu May 8 00:00:00 2006 GMT (not ended)

Mail-forwarding is active. Starting date and time: Thu May 1 00:00:00 2006 GMT (not started) Ending date and time: Thu May 8 00:00:00 2006 GMT (not ended) Forward-To: [email protected]

Quota warning is sent at 90 percent full.

If multiple administrator commands are sent in one email, separate replies are sent. For example, if you send an email to the z/TPF system with 10 administrator commands, the z/TPF system will send back 10 reply e-mails (one for each command) rather than one email with all 10 replies in it.

276 z/TPF Application Modernization using Standard and Open Middleware 15.4 z/TPF Internet mail server client

Users, or mail clients, can interact with the z/TPF Internet mail server on the z/TPF system by doing one of the following:  Write an application program on a non-z/TPF system, based on the standard Internet mail protocol, that is, SMTP, POP, or IMAP, and interact with the z/TPF Internet mail server on the z/TPF system.  Configure mail clients, such as Netscape and Microsoft Outlook, to point to the z/TPF Internet mail server on the z/TPF system.  Write an application program using the mail function provided, to access mails from the z/TPF system.

A single dot on a line (\n.\n) in your mail message specifies the end of the message. If you want to include a line in your message that contains just a single dot, code 2 dots as (\n..\n).

Example 15-15 provides an example of an Internet mail message being processed. In this example:  An Internet mail message is built in a temporary file named /temp/file.  An Internet mail message is sent to the users at addresses [email protected] and [email protected].  The z/TPF Internet mail server is checked for incoming mail and, if found, stores the mail in a file named /temp/mailin.

Example 15-15 Processing mail message

/* Build an Internet mail message & Send an Internet mail message */

#define _POSIX_SOURCE #include #include #include #include

#define ERROR -1 #define OK 0

int build_message(char *mail_message);

void main() { int rc=0; char *rcpt[3]; char mail_message[] = "/temp/file"; char readmail_message[] = "/temp/mailin"; char dmn[] = "tpf.com"; char uid[] = "curly"; char pw[] = "shemp3";

rcpt[0]="[email protected]"; rcpt[1]="[email protected]";

Chapter 15. z/TPF Internet mail server 277 rcpt[2]=(char*)NULL;

if((rc=build_message(mail_message)) == OK) { mail(‘w’,rcpt,mail_message,dmn,uid,(char*)NULL,rc); if(rc==0)printf("Message sent\n"); else { printf("Message not sent\n"); } } else { printf("ERROR OCCURRED: CHECK ERRNO"); }

mail(‘e’,(char*)NULL,(char*)NULL,dmn,uid,pw,rc);

if (rc==0) { mail(‘r’,(char*)NULL,readmail_message,uid,pw,rc); } }

int build_message(char *mail_message) { FILE* in;

char content[]="Dear Moe\n\nHow’s it going.\n\nRegards Curly.\n"; int ret=OK;

if((in=fopen(mail_message,"w"))==(FILE*)NULL) { fprintf(stderr,"Can°Øt open message file: %s.\n",mail_message); return(ERROR); }

fprintf(in,"%s",content); return OK;

}

Example 15-16 on page 279 shows how you can process an Internet mail message using file addresses on the z/TPF database. In this example:  An Internet mail message is built in a file record on the z/TPF database.  An Internet mail message is sent to the users at addresses [email protected] and [email protected].  The z/TPF Internet mail server is checked for incoming mail and, if found, stores the mail in a file on the z/TPF database. The file address where the mail is stored is returned in rc.

278 z/TPF Application Modernization using Standard and Open Middleware Example 15-16 Processing mail message using file address on z/TPF database #define _POSIX_SOURCE #include #include #include #include

#define ERROR -1 #define OK 0 int build_message(char *);

void main() { int rc=0; char *rcpt[3]; char mail_message[16]; char dmn[] = "tpf.com"; char uid[] = "curly"; char pw[] = "shemp3";

rcpt[0]="[email protected]"; rcpt[1]="[email protected]"; rcpt[2]=(char*)NULL;

mail_message[0]='\0';

if((rc=build_message(mail_message)) == OK) { mail('p',rcpt,mail_message,dmn,uid,(char*)NULL,rc); if(rc==0)printf("Message sent\n"); else{ printf("Message not sent\n"); } } else{ printf("ERROR OCCURRED: CHECK ERRNO"); }

mail('e',(char*)NULL,(char*)NULL,dmn,uid,pw,rc); if (rc==0) { mail('g',(char*)NULL,(char*)NULL,uid,pw,rc); } }

int build_message(char *msg_FA) { unsigned int fa; message_record *msgrec;

fa = getfc(D8, GETFC_TYPE0, "\xFC\x60", /

Chapter 15. z/TPF Internet mail server 279 (int)(GETFC_BLOCK+GETFC_FILL),GETFC_NOSERRC,0x00);

sprintf(msg_FA,"%d",fa);

ecbptr()->ebcid8 = 0XFC60; msgrec = ( message_record *) ecbptr()->ebccr8;

if (msgrec == NULL) return (ERROR);

msgrec->MR0RID = 0XFC60; strcpy(&msgrec->msg_data,"Hi! How are you today?\n"); return OK; }

The function mail in z/TPF system can be used as a means for your z/TPF applications to send/receive information, for example:  Send direct customer notifications, such as airline schedule changes, hotel room upgrades, credit card security warnings, fare base changes, and so on.  Set up business-to-business messaging, such as host-to-host traffic, AVS messages (airline advisory messages), and queue-placed passenger name records (PNRs).  Enhance enterprise resource planning functions, such as enabling email for crew bidding and crew scheduling.  Create push model architecture for your enterprise to effectively share information stored on the z/TPF system.

280 z/TPF Application Modernization using Standard and Open Middleware 16

Chapter 16. z/TPF HTTP client support

The z/TPF system provides the ability for applications to initiate Hypertext Transfer Protocol (HTTP) requests as a client to HTTP servers running on another platform. The infrastructure for the z/TPF HTTP client is built on libCURL version 7.19.7.

z/TPF relies on libCURL to handle the protocol layer and transmittal of HTTP requests and responses. z/TPF builds on libCURL to provide an easy to use interface that shields an application from the need to understand the more complicated details of the HTTP protocol, for example, managing TCP/IP connections.

This chapter contains the following topics:  16.1, “Support overview” on page 282  16.2, “Application programming interfaces” on page 283  16.3, “Using the APIs” on page 284  16.4, “Examples” on page 287

© Copyright IBM Corp. 2013. All rights reserved. 281 16.1 Support overview

This section gives an overview of the support the z/TPF HTTP client provides. This support includes connection modes, response modes, and the HTTP client daemon.

16.1.1 Connection modes

z/TPF HTTP client support allows an application to initiate an HTTP request with three connection methods:  ECB single request mode ECB single request mode should be used when an application needs to send a single request to an HTTP server. This mode automatically establishes a new HTTP session with the HTTP server, sends the request, receives the response and ends the HTTP session.  ECB multiple request mode ECB multiple request mode should be used when an application needs to send multiple requests to the same HTTP server from the same ECB. This mode is more efficient than single request mode because it reuses a persistent connection to an HTTP server and thus avoids the need to renegotiate the connection after each request has been completed.  Shared session request mode As more and more z/TPF users begin using HTTP as a message transport, they might want to establish persistent pipes to the most frequently accessed remote systems. HTTP itself is a simple request/reply protocol that is not generally considered chatty. However, there is still some amount of overhead involved with repeatedly creating and ending new TCP/IP sessions for single requests and replies. When HTTPS is used to create secure communication sessions, the SSL handshake dramatically increases this overhead. Rather than having many instances of the application (each in a different ECB) send requests to the same HTTP server, it is better to use shared sessions. Shared session mode allows multiple ECBs to use the same TCP/IP connection to send requests to the same HTTP server. This mode sends requests over a persistent connection, called a shared session, that multiple ECBs can use. It is more efficient than an ECB single request or multiple request mode because each ECB does not need to establish its own connection to the HTTP server. From an application perspective, no changes are needed to take advantage of shared sessions.

16.1.2 Response modes

In addition to the three connection methods, the z/TPF HTTP client provides two message exchange patterns. Applications have the option of receiving a response to an HTTP request in a synchronous manner, where the response is delivered to the ECB that initiated the request. This mode is the traditional request/reply nature of HTTP. Alternatively, z/TPF also provides the unique ability to deliver an HTTP response asynchronously. When this option is used, a new ECB is created when the HTTP response is received and it is that ECB, not the ECB that initiated the request, that receives the response.

16.1.3 HTTP client daemon

In order for an application to use shared sessions and make asynchronous requests, the z/TPF HTTP client daemon must be running on the z/TPF system. Details about how to

282 z/TPF Application Modernization using Standard and Open Middleware configure and operate the HTTP client daemon are outside the scope of this document. For more information, see the TPF Product Information Center at the following website: http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp

However, it is important to understand the function and purpose of the HTTP client daemon.

Certain design limitations exist because libCURL is used as the underlying protocol library. In particular, libCURL stores all of its control information, such as socket descriptors, transfer state information, and so on, in ECB heap storage (CURL handle). The nature of ECB heap storage makes it impossible to share a CURL handle among multiple processes. However, note that the CURL handle can be shared by multiple threads in a process. With EBC multiple request mode, there is one CURL handle for every HTTP client handle that is initialized by the application. However, because an application can use the same HTTP client handle to perform transfers to different HTTP servers, there might be more than one TCP/IP socket associated with each CURL handle. The result, however, is that the socket remains linked to a single process.

Without drastically changing the ported libCURL code to use a different control storage mechanism (for example, system heap instead of ECB heap) and to make use of TPF-unique APIs for receiving responses (such as activate_on_receipt), or writing a TPF-unique HTTP protocol interpreter, an HTTP client daemon has been created that enables both shared HTTP client sessions and asynchronous HTTP client response processing. For shared session support, the HTTP client daemon ECBs own the CURL handles and thus can allow application ECBs to use them. For asynchronous support, the HTTP client daemon ECBs wait on and process the HTTP response.

The HTTP client daemon is a multi-process, multi-threaded, long-running program that handles HTTP client requests on behalf of an issuing application. Each individual daemon process “owns” a subset of CURL handles, and thus owns the underlying sockets. When an ECB issues a request to an HTTP server that has a shared session or makes an asynchronous request, or both, the HTTP conversation between client and server takes place in the HTTP client daemon, not the calling or asynchronous ECB.

In order to provide for maximum request throughput, the HTTP client daemon uses the libCURL multi interface. The ECB single and multiple request modes make use of the libCURL easy interface. With the libCURL easy interface, ECBs are blocked when the HTTP request is made and until a response is received, or a timeout occurs. With the libCURL multi interface, the ECB is not blocked when the HTTP request is made. Control is returned and another request can be made. This allows a single ECB to have multiple requests processed simultaneously. Users of the multi interface are then able to poll the library to determine when any of the requests have completed. The HTTP client daemon takes advantage of this capability to allow its threaded processes to simultaneously process multiple requests at one time. Not only does this allow multiple shared sessions to send and receive HTTP messages at the same time, it also allows asynchronous processing without blocking the daemon or the calling ECB.

16.2 Application programming interfaces

There are five z/TPF unique C/C++ application programming interfaces (APIs) that an ECB uses to make an HTTP request:  tpf_httpInitHandle

Chapter 16. z/TPF HTTP client support 283 The tpf_httpInitHandle function creates an HTTP client handle that is used by the application and the HTTP client infrastructure to identify an HTTP session and its associated resources.  tpf_httpPerform The tpf_httpPerform function sends an HTTP request to a remote HTTP server using a persistent connection that was previously established by either the first call to this function or by the HTTP client daemon. This function is passed three input parameters: the HTTP client handle, a pointer to a complete t_httpRequest structure, and a pointer to a pointer to a t_httpResponse structure.  tpf_httpEnd The tpf_httpEnd function ends a persistent HTTP client connection with a remote HTTP server.  tpf_httpGetOpts The tpf_httpGetOpts function returns the options that were set for a previously established, persistent HTTP client handle. It returns connection information that was set by the tpf_httpInitHandle function and requests information for the last tpf_httpPerform request that was made.  tpf_httpPerform1 The tpf_httpPerform1 function sends HTTP client request to a remote HTTP server. The function establishes an HTTP connection, performs the request, and ends the connection.

16.3 Using the APIs

This section discusses using the HTTP client APIs.

16.3.1 Single ECB request mode

An ECB can send a single HTTP request by calling the tpf_httpPerform1 function. This function creates the HTTP client handle, submits the HTTP request, processes the HTTP response and ends the HTTP client handle. This function is intended to be used when an ECB does not need to send multiple requests to the same remote destination. The client handle that is created is not returned to the application. It is for one-time use and all resources, including the TCP/IP socket connection, are cleaned up when the request is completed. This function calls the tpf_httpInitHandle, tpf_httpPerform and tpf_httpEnd C/C++ functions on behalf of the application.

16.3.2 Multiple ECB request mode

When a single ECB is used to send multiple requests to the same HTTP server (whether using shared sessions or not), use the following steps: 1. Create an HTTP session by calling the tpf_httpInitHandle function. This function returns a handle that is used as input to all subsequent functions involving this HTTP session. 2. Send a request to an HTTP server by calling the tpf_httpPerform function. This call is then repeated to send additional requests. If a t_httpResponse structure is returned to the application, use the free function to release the malloc storage.

284 z/TPF Application Modernization using Standard and Open Middleware 3. End the HTTP session by calling the tpf_httpEnd function. This function closes the connection to the HTTP server and release the resources that are associated with the HTTP session. 4. To verify the options used for an HTTP request that was made with the HTTP client handle, call the tpf_htttpGetOpts function to view the current settings for the HTTP client handle. Use the free function to return the malloc storage that was obtained for the t_httpOpts structure.

16.3.3 Shared sessions

When the HTTP client daemon is enabled, an application can further exploit the benefits of persistent connections beyond those of the ECB multiple request method. This is done through the use of shared sessions. The infrastructure is such that the existence and use of shared sessions is transparent to the application, so there are no options or extra steps required for an application to make use of shared sessions. As such, the benefits from using shared sessions can be realized immediately, without any code changes to existing applications.

The EBC single use and ECB multiple use methods for initiating an HTTP request can take advantage of z/TPF shared session support. The HTTP client daemon is configured to establish and maintain persistent connections to the destinations that are listed in what is known as the shared session file.

When an ECB makes an HTTP request to a destination that is listed in the shared session file, the HTTP client passes the request to the HTTP client daemon to use one of the persistent shared sessions rather than creating a new connection for that ECB. This is true regardless of the API (tpf_httpPerform or tpf_httpPerform1) that was used to make the request. In other words, all shared sessions are owned by the HTTP client daemon and are persistent. Whether the application calls tpf_httpPerform1 for ECB single request mode or makes repeated calls to tpf_httpPerform when using ECB multiple request mode, if the HTTP client daemon is enabled and the destination is in the shared session file, the request will be routed to the daemon and will use a persistent shared session.

Therefore, using a shared session is not controlled by the application making the request but rather by the z/TPF HTTP client support code. To determine if the requested destination matches one with a shared session, the following steps are taken during the call to the tpf_httpPerform function: 1. The query portion of the request URL is removed. This removal is done because query information typically changes on each request to an HTTP server and as such is not allowed in the URLs listed in the shared session file. 2. The abridged request URL is then compared to the URLs for the shared sessions. 3. If no match is found, the relative URI is then stripped from the request URL. 4. The truncated request URL (which now only contains the host and optionally the port, user name, and password) is compared with the URLs of the shared session. 5. A match is considered found in steps 2 or 4 only if the user name and password, netrc files and redirect authorization match.

If a proxy is used for the HTTP request, the previous steps use the proxy URL rather than the final destination URL of the request because z/TPF connects to the proxy, not the final destination URL.

Chapter 16. z/TPF HTTP client support 285 16.3.4 Asynchronous responses

An application receives an HTTP response asynchronously by using the request APIs (tpf_httpPerfrom and tpf_httpPerform1) and specifying HTTP_ASYNC as the value for the responseType parameter in the t_httpRequest structure. The calling application must specify the name of the program that is to receive control when the response is received in the 4-byte asyncProgram field in the t_httpRequest structure. The I-stream where this ECB will be created can be selected by the calling application by setting the asyncIS field in the t_httpRequest structure to the I-stream affinity.

Optionally, the calling application can pass a block of data to the asynchronous ECB. This is done by passing a pointer to the data (along with its length) using the asyncData and asyncDataLength parameters in the t_httpRequest structure, respectively. When the request is scheduled to be sent, control is returned immediately to the calling application so that processing can continue without blocking for the request to be sent or for the response to be received. This enables the application to proceed with other processing. When the HTTP response is received, a new ECB is created on the I-stream specified by the calling ECB or as selected by the z/TPF scheduler. If there is an error sending the HTTP request or processing the HTTP response, or if the HTTP server returns an error, only the asynchronous ECB will be made aware, not the calling EBC.

Processing for the asynchronous application is implemented in C shared objects (CSOs). As such, the application must have a single entry point as defined in the program’s makefile. This interface to the CSO must match the interface that is defined by the typedef statement that is used by the HTTP client support code. The format of the typedef is typedef int (*httpAsyncfn)(t_httpAsyncParms *) where:  httpAsyncfn is a pointer to a function. This pointer, along with the four-character program name contained in asyncProgram, is passed by the HTTP client code to the TPF_CALL_BY_NAME macro. The macro returns a pointer to a function that calls an enter with return linkage (ENTRC linkage) to the specified program. Because the application is entered with return linkage, it is important that the application exits rather than return from its mainline code path. Otherwise, unexpected behavior might occur.  The parameter that is passed as input to the function (and thus to the asynchronous application) is a pointer to a t_httpAsyncParms structure. The t_httpAsyncParms structure contains the HTTP response and information about the HTTP request.

All asynchronous requests are fulfilled by the HTTP client daemon. Calling the tpf_httpInitHandle function will still create an HTTP client handle to be used on subsequent calls to tpf_httpPerform. However, every call to tpf_httpPerform where responseType is HTTP_ASYNC will pass the request to the HTTP client daemon. This means that a persistent connection is not created for repeated use by the ECB. Therefore the only time a persistent connection is used for an asynchronous request is when there is a shared session to the destination.

If no shared session is established to the HTTP server, the HTTP client daemon will create new, single-use connections for each asynchronous request. Although the connection is not persistent or shared for use by other ECBs, it still uses the libCURL multi interface so that it does not block the HTTP client daemon thread from handling the request. It also allows the thread to continue processing multiple requests simultaneously.

286 z/TPF Application Modernization using Standard and Open Middleware 16.4 Examples

Figure 16-1 on page 287 shows the flow of an application that will receive the response asynchronously. The calling application passes to the API both the request and optional data that is to be given to the ECB that receives the response. The API code passes all the information to the libCurl process that handles the communications with the remote HTTP server. When the libCurl process receives the response, a new ECB is created with the response and the optional data, and control is given to the Async application identified by the calling application in the initial request.

Calling User Async Application Exits Application User data Resp and Async Data API Code Master Process Async Req ECB block Req block Worker Process Worker Process

Master Master Thread Thread

Worker Worker Worker Worker Thread Thread Thread Thread

Figure 16-1 HTTP client application flow

Example 16-1 shows how to use the ECB multiple request mode APIs for both synchronous and asynchronous response modes.

Example 16-1 Using the ECB multiple request mode APIs #include #include

int rc = 0; t_httpHandle httpHandle = 0; t_httpHeader headerStruct = {0}; char *headerPtr = NULL; t_httpConn connectParms = {HTTPC_CONNECT_DEFAULT_2}; t_httpRequest requestParms = {HTTPC_REQUEST_DEFAULT_2}; t_httpResponse *response = NULL; t_httpOpts *httpOptions; char headerBuffer[1024], dataBuffer[1024]; . . /***************************************************/ /* Setup HTTP connection parameters request. */ /***************************************************/

Chapter 16. z/TPF HTTP client support 287 connectParms.connectVersion = HTTPC_VERSION_2; connectParms.connectTimeout = 5; connectParms.connectTimeoutInterval = HTTPC_MILLI; connectParms.netrc = "/.netrc"; connectParms.proxy = “someproxy.com”; connectParms.proxyPort = 2020; connectParms.proxyUserPassword = "test:test"; connectParms.httpVersion = HTTP_ANY;

/***************************************************/ /* Initialize HTTP Client Session. */ /***************************************************/ httpHandle = tpf_httpInitHandle (&connectParms);

if (httpHandle == TPF_HTTP_ERROR) { printf (“Error initializing HTTP handle - %d\n”, errno); exit (0); } else { printf (“Handle initialization successful\n HTTP Handle - %ul\n”, httpHandle); }

/***************************************************/ /* Setup HTTP PUT request. */ /***************************************************/

// Setup Headers and Data headerPtr = headerBuffer; headerStruct = headerPtr;

headerPtr->headerLength = sizeof(“Expect: 100-Continue”); strcpy(headerPtr->headerValue, “Expect: 100-Continue”);

// Bump to next header starting point headerPtr += (sizeof(int) + headerPtr->headerLength); headerStruct = headerPtr;

headerPtr->headerLength = sizeof(“Test: Some Header Value”); strcpy(headerPtr->headerValue, “Test: Some Header Value”);

strcpy(dataBuffer, “TEST DATA”);

requestParms.requestVersion = HTTPC_VERSION_2; requestParms.requestType = HTTP_PUT; requestParms.url = “http://user:[email protected]:220/putpage”; requestParms.requestTimeout = 10; requestParms.requestTimeoutInterval = HTTPC_MILLI; requestParms.maxRedirects = -1; requestParms.redirectAuthorization = AUTH_SEND; requestParms.responseType = HTTPC_SYNC; requestParms.data = dataBuffer;

288 z/TPF Application Modernization using Standard and Open Middleware requestParms.dataLength = strlen(“TEST DATA”); requestParms.headerList = headerBuffer; requestParms.headerNum = 2;

/****************************************************/ /* Perform HTTP PUT request. */ /****************************************************/ rc = tpf_httpPerform (httpHandle, &requestParms, NULL); if (rc < 0) { printf (“Error performing HTTP request - %d\n”, errno); exit (0); } else { printf (“HTTP request successful”); free(response); }

/***************************************************/ /* Get the options for this HTTP connection. */ /***************************************************/ rc = tpf_httpGetOpts (httpHandle, &httpOptions); if (rc == TPF_HTTP_ERROR) { printf (“Error getting HTTP connection options - %d\n”, errno); exit (0); } else { printf (“HTTP options successful”); free(httpOptions); }

/***************************************************/ /* Setup HTTP GET request. */ /***************************************************/ requestParms.requestVersion = HTTPC_VERSION_2; requestParms.requestType = HTTP_GET; requestParms.url = “http://user:[email protected]:220/getpage”; requestParms.requestTimeout = 10; requestParms.requestTimeoutInterval = HTTPC_MILLI; requestParms.headerList = NULL; requestParms.headerNum = 0; requestParms.data = NULL; requestParms.dataLength = 0 requestParms.maxRedirects = -1; requestParms.redirectAuthorization = AUTH_SEND; requestParms.responseType = HTTPC_ASYNC; memcpy(requestParms.asyncProgram,"ABCD",4); requestParms.asyncIS = 0; requestParms.asyncData = “async data”; requestParms.asyncDataLength = strlen(“async data”);

Chapter 16. z/TPF HTTP client support 289 /***************************************************/ /* Perform HTTP GET request. */ /***************************************************/ rc = tpf_httpPerform (httpHandle, &requestParms, &response); if (rc == TPF_HTTP_ERROR) { printf (“Error performing HTTP request - %d\n”, errno); exit (0); } else { printf (“HTTP request successful”); } . . . tpf_httpEnd(httpHandle); . . .

Example 16-2 shows how to use the ECB single request mode API.

Example 16-2 Using the ECB single request mode API int rc = 0; t_httpHandle httpHandle = 0; t_httpConn connectParms = {HTTPC_CONNECT_DEFAULT_2}; t_httpRequest requestParms = {HTTPC_REQUEST_DEFAULT_2}; t_httpResponse *response = NULL; . . . connectParms.connectVersion = HTTPC_VERSION_2; connectParms.connectTimeout = 5; connectParms.connectTimeoutInterval = HTTPC_MILLI; connectParms.netrc = NULL; connectParms.proxy = NULL connectParms.proxyPort = 0; connectParms.proxyUserPassword = NULL; connectParms.httpVersion = HTTP_ANY;

/***************************************************/ /* Setup HTTP GET request. */ /***************************************************/ requestParms.requestVersion = HTTPC_VERSION_2; requestParms.requestType = HTTP_GET; requestParms.url = “http://user:[email protected]:220/getpage”; requestParms.requestTimeout = 10; requestParms.requestTimeoutInterval = HTTPC_MILLI; requestParms.headerList = NULL; requestParms.headerNum = 0; requestParms.data = NULL; requestParms.dataLength = 0; requestParms.maxRedirects = -1;

290 z/TPF Application Modernization using Standard and Open Middleware requestParms.redirectAuthorization = AUTH_SEND; requestParms.responseType = HTTPC_SYNC;

/***************************************************/ /* Perform HTTP GET request. */ /***************************************************/ rc = tpf_httpPerform1 (&connectParms, &requestParms, &response); if (rc == TPF_HTTP_ERROR) { printf (“Error performing HTTP request - %d\n”, errno); exit (0); } else { printf (“HTTP request successful”); free(response); } . .

Chapter 16. z/TPF HTTP client support 291 292 z/TPF Application Modernization using Standard and Open Middleware 17

Chapter 17. Additional examples of z/TPF in an SOA environment

This chapter describes additional examples of z/TPF in an SOA environment. Such examples can fall into two categories, those for existing solutions and those for new installations. This differentiation is due to the presence of existing applications and the steps necessary to Web enable them.

This chapter contains the following topics:  17.1, “z/TPF, SOA, and existing applications” on page 294  17.2, “The value of SOA” on page 294  17.3, “z/TPF, SOA, and new applications” on page 295  17.4, “z/TPF and SOA summary” on page 297

© Copyright IBM Corp. 2013. All rights reserved. 293 17.1 z/TPF, SOA, and existing applications

One of the main purposes of this book is to demonstrate methods to SOA-enable your z/TPF based applications. The business value of this cannot be understated. For most existing TPF customers, the TPF systems of today are their mainline, critical path business systems. The functions provided by these systems and the applications that implement those functions are key business assets. Any attempt to replace them with totally new solutions represents immense cost and risk. For many, TPF is hosting key travel reservation or banking functions. Users and customers of these systems depend on these functions to do their jobs and complete daily tasks, such as using a credit card or reserving a flight. Over the years that these enterprises have used TPF, these core functions hosted on TPF have increased in functionality but have not fundamentally changed.

For example, the basic steps required to make a reservation or to validate and authorize the use of a credit card are largely the same as they were 20 years ago. What has changed is how users or customers access these systems, or how they can exploit the additional functionality that has been added to the system. For most z/TPF users, the majority of their application development work over the past 20 years has been in validation and methods to access functionality, not the core functions themselves.

Aside from accessing the functions, the applications that provide the functionality can be further divided into two groups. Those that are relatively static (few changes over time) and those that are dynamic (frequent changes). Another consideration is the frequency of data updates. Applications that modify data often have to be in the same server as the data.

Solutions, such as z/TPF, provide high value because of their speed, reliability, and scalability of accessing and modifying data and the ability to handle immense amounts of network traffic. Solutions, such as WebSphere, provide high value in presentation services, portals and in general the personalization and delivery of data. WebSphere comes with powerful tooling to aid in the delivery of complex business logic to market quickly. In the example used in this IBM Redbooks publication, the relatively static functions or functions that cause a lot of data updates would reside on z/TPF and the complex business logic, presentation services and dynamic (often changing) functions on WebSphere. So the question is that of how SOA can make it easier to combine these profiles and take maximum advantage of each.

17.2 The value of SOA

The challenges TPF users face today are of external access methods; the retrieval and presentation of the data are tightly tied together. For example, in reservation systems the most common way to create, update, or delete data is through line mode commands. These are not explicitly data manipulation commands, but this is in effect what happens in the creation, modification, and cancellation of a reservation.

Attempts to modernize this interface have largely resulted in sophisticated client software (or mid-tier servers) that emulate the flow and logical process of a human user. This is in part due to the fact that there is still a complete set of presentation logic in the TPF systems themselves. The client code must still share the functions with human users operating on green screens. To properly address this, the core functions on TPF have to be separated from any presentation logic. Instead, these core functions would be presented to the network directly as SOA services.

To implement such a solution, the presentation logic is largely removed from TPF to WebSphere, on which portal code (for example) becomes a consumer of the z/TPF-based

294 z/TPF Application Modernization using Standard and Open Middleware services. The value of this approach is that there can be any number of consumers of the services who might use the service (data) in any number of ways, including the combination of services to create new business value.

In the new configuration, the core functions that require the speed and reliability of z/TPF can still run there while new and relocated business functions on WebSphere can interact with them seamlessly. Functions that have supported the business for years through line mode commands are now available as reusable services without high risk major rewrites or migrations. WebSphere-based applications benefit, and z/TPF provides a highly reliable and fast source of corporate data and functions, improving the overall speed and reliability of WebSphere itself.

This is an ideal state. The core data and relatively static functions are on a highly reliable server, such as z/TPF, while the volatile logic is on a highly flexible platform, such as WebSphere. Both technologies are used to their maximum value, and the loose coupling of web services (SOA) allows each technology to continue to provide value in unique ways.

17.2.1 A word about z/TPF

In the previous section, we mentioned both TPF and z/TPF. At this time, the majority of TPF customers have migrated to the z/TPF system and are looking at implementing SOA. z/TPF provides for the refactoring of existing assembler programs into reusable service objects. Customers can take multiple 1KB or 4KB assembler segments and combine them into a single library (shared object) with little or no code changes. This aids in regrouping functions into identifiable libraries, which in turn can be SOA-enabled, as described in this document or moved out of z/TPF as in the example or presentation logic.

17.3 z/TPF, SOA, and new applications

z/TPF can contribute greatly to the success of an SOA implementation, but the considerations and approach are different than when there is an existing application and database. With an existing application, the primary focus is on how to exploit that application with a minimum or changes and risk to that investment. In a new design effort, the primary focus is the value that the z/TPF architecture itself brings to the table.

17.3.1 z/TPF value

The most outstanding characteristics of a z/TPF solution are reliability, speed, and a scalability that translates into price performance. z/TPF scales vertically rather than horizontally, which yields dividends in cost per unit of work as volume increases. This is because the same physical infrastructure, cooling, power, and people can be made to do more work.

Analogous to vertical scaling, z/TPF can provide a single image database (single copy) of immense scale. This can greatly simplify operations and security over distributed data bases necessary with UNIX based solutions. This again leads to better price performance and overall system performance (low latency). Some would be concerned with this approach as a single point of failure; however, this is where z/TPF's most important attribute comes into play: reliability.

z/TPF outperforms even fault tolerant products for overall availability. This is not only because z/TPF has many fault tolerant features (and the System z box itself) but is also due to the fact

Chapter 17. Additional examples of z/TPF in an SOA environment 295 there are many features that avoid outages for common maintenance. For example, entire application packages can be loaded and removed while messages are in flight.

Databases and even network configurations can also be changed without an outage. Truly going the distance, you can even migrate from TPF to z/TPF without and outage. As a result many existing customers report overall availability numbers from a low of 97.8% to as much as 99.999%. In practice, it is extremely rare for distributed data bases to reach these kinds of numbers.

17.3.2 z/TPF and new designs

So the question remains on how to exploit the z/TPF qualities of service in a new SOA effort where there are no limitations from previous implementations. The overall approach is to exploit these heavy lift capabilities of z/TPF while keeping most of the business logic on application servers, such as WebSphere. Infrastructure services, such as network handling, security, and directories all would do well on a z/TPF server. They exploit the I/O handling capabilities of the z box and z/TPF to deliver great price performance with high reliability. Remember that unlike application based services, if these core infrastructure services are not available, the entire solution is down. There are other cost of doing business services that must be provided, such as email and other messaging and queuing services that too can exploit the I/O capabilities on z/TPF to great advantage and drive down costs.

Such services can be provided, leaving the application servers free to focus on high-value business logic. That in itself should be of great value to the enterprise but there is nothing there specific to an SOA architecture. To look into SOA, there are two more areas (of many) to consider:  Using z/TPF as a centrally located database  Using z/TPF as a centrally located logging facility

To consider using z/TPF as a central database, it might be best to simply give an example. This is not an attempt to make z/TPF the database of record or anything but an OLTP database. Instead, this is focused on situations in which a single copy of transient data is required. Consider a large financial institution that has many product portfolios in addition to simple savings and checking accounts. The customer might have in fact thousands of products with the bank after you consider all financial services, including stocks and mutual funds. The status of these accounts and their relationship to each other is currently impossible for a bank to track in real-time.

The complexity of the relationship between all these products should be handled in an application server, such as WebSphere, but the real-time status of these accounts can be in a z/TPF database, possibly exposed to the network as a Service Data Object (SDO). This allows the many application servers to easily access and update the status of the customer. The highly available nature of z/TPF ensures the accuracy of this database. While not directly considered a web services technology and part of SOA, this customer record can also be put in a high speed Lightweight Directory Access Protocol (LDAP) server on z/TPF to achieve the same result. An LDAP access might not be as transparent to a J2EE based application as SDO; however, wrapped as a session bean in WebSphere, it might be just as effective. The choice of SDO or LDAP is an implementation choice.

Using z/TPF as a central logging facility is similar in many ways to the central database example. In this case, the issue is that there might be a large number of servers, and an even greater number SOA based services, involved in a providing for a customer's request. Keeping track of this complexity for the purpose of licensing (billing) and problem

296 z/TPF Application Modernization using Standard and Open Middleware determination can be a daunting task. z/TPF is one of very few solutions that withstand the I/O rate of potentially thousands of services logging checkpoints and status to a central facility.

This can immensely improve problem determination, which in turn improves the quality of the overall solution. LDAP again might be a good choice. A high-volume directory structure would simplify this process. The relationship to SOA is that SOA promotes an increase of identifiable and callable services that are by definition loosely coupled together. Because the relationship between services is generally stateless and transient, it becomes difficult or impossible to infer relationships for the purpose of problem determination or licensing. A central logging capability allows an SOA based infrastructure to grow larger and more complex than would be otherwise possible. There is a related area to this known as compliance checking. This also might benefit greatly from a central repository of status.

17.4 z/TPF and SOA summary

z/TPF is a facilitator of an SOA implementation, whether by providing standards based access to existing applications or data or by providing high volume infrastructure to allow an SOA infrastructure to scale larger than it otherwise can. Inside z/TPF itself, work would be done in a fairly traditional TPF way for the purposes of speed and scale. The external view of z/TPF as a service is completely standard.

One can consider this as a programmable black box that can provide many services at an extreme rate or scale, thereby relieving bottlenecks in the overall architectural design. z/TPF itself is not positioned as another application server for general business logic development. In most cases, only a small specialty team works with z/TPF to provide a high-volume solution to the rest of the teams working with more common environments, such as IBM CICS® or WebSphere.

Having made that statement, it should be made clear that customers with existing large investments in applications on TPF should only consider moving those applications off z/TPF when there is a clear business value. z/TPF vastly improves the application development tooling by making it common with Linux, which in turn also alleviates concerns over a future skill base. The low cost solution for supporting the existing TPF application is to move it to z/TPF rather than to any other server.

Chapter 17. Additional examples of z/TPF in an SOA environment 297 298 z/TPF Application Modernization using Standard and Open Middleware Part 7

Part 7 Appendixes

© Copyright IBM Corp. 2013. All rights reserved. 299 300 z/TPF Application Modernization using Standard and Open Middleware A

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system

This appendix shows how to use the TPF Toolkit to create projects, to create files for use in the project, how to build files containing code for execution, and how to deploy the executables to the runtime environment. The development application is IBM TPF Toolkit version 4.0.0.

This appendix includes the following topics:  Figure A-1 on page 302  “Creating a book project” on page 303  “Creating the directory and source files using the shell” on page 308  “Adding content to the files” on page 312  “Creating the makeTPF configuration and control files” on page 322

© Copyright IBM Corp. 2013. All rights reserved. 301 Basic work environment

Figure A-1 shows the basic work environment used for the techniques illustrated in this book.

WebSphere z/TPF Linux Application Server

IBM Network

Developer Developer Workstation Workstation

Figure A-1 Work environment

In Figure A-1:  z/TPF This is the z/TPF system where the example Web Service is running. For the purpose of this book, the z/TPF system is running in a virtual machine under IBM z/VM®.  Linux The z/TPF development environment is running on a System z mainframe system. It is used to build the applications that are being loaded onto z/TPF for execution.  WebSphere Application Server This is the production runtime server that is running the Web Service consumer (client) for the book examples. Besides the IBM WebSphere Application Server, the PHP runtime environment is also run here.  Developer Workstation The developer workstation is running IBM TPF Toolkit to develop, build, and debug the z/TPF example applications. It connects to the Linux build environment for building applications and it connects to the z/TPF system for debugging. The developer workstation also runs the IBM Rational® Application Developer to develop and test the Web Service consumer examples in this book. After the code is finalized, it is packaged and deployed to the WebSphere Application Server for production use.

302 z/TPF Application Modernization using Standard and Open Middleware The following systems were used to create the examples in the book:  The z/TPF system we used ran as a z/VM guest system using VPARS version 53. The z/VM version used is z/VM Version 5 Release 4.0, service level 1112 (64-bit). The z/TPF version we used was z/TPF Enterprise Edition 1.1 PUT 9.  The Linux system we used also ran as a z/VM guest on z/VM Version 5 Release 4.0, service level 1112 (64-bit). The Linux distribution we used is SUSE Linux Enterprise Server 10 (s390x), Service Pack 2.

Creating a book project

In this example, the first step is to create a project to hold the artifacts for the application. Use the following steps to create a z/TPF project: 1. Start the TPF Toolkit, and open the TPF perspective in the Toolkit by navigating to Window  Open Perspective  Other  TPF Toolkit, as shown in Figure A-2 and Figure A-3 on page 304. Click OK.

Figure A-2 Opening a perspective

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 303 Figure A-3 Selecting a perspective

2. To start a new project, select File  New  Project to open the menu shown in Figure A-4. Select Project under TPF, and click Next.

Figure A-4 Selecting a new project wizard

304 z/TPF Application Modernization using Standard and Open Middleware 3. In the New TPF Project panel: a. Name the project (book in this example). b. Select the remote working directory on the Linux server where the maketpf control and config files are to be stored. In this project, it is the directory /home/jwisnie/book/. The TCP/IP host name of the Linux system is linuxtpf.pok.ibm.com. This results in a remote working directory of: \\linuxtpf.pok.ibm.com\home\jwisnie\book c. Select the applicable Target Environment. A Target Environment defines what system the software is built for and which source image you want to build against. In this example, a set of Target Environments are predefined as CUR_BAS [current], as shown in Figure A-5. d. Click Next.

Figure A-5 Creating a new project in the new project wizard

Each project requires filters to display the files that belong to it. e. Enter the name for the filter, for example, Book Files.

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 305 f. Initialize the filter with the filter criteria by clicking Add in the New TPF Project Filter Wizard, as shown in Figure A-6.

Figure A-6 Naming a new filter

306 z/TPF Application Modernization using Standard and Open Middleware g. Specify a project base directory for a path. Choose to see all files by specifying an asterisk for a file name pattern, and select the check box to include all subfolders, as shown in Figure A-7. Click OK.

Figure A-7 Adding a new filter

h. The new filter string is now complete. Click Finish to complete the process of setting up filter strings for the book project.

The project set up is complete and the project is displayed in the TPF Project Navigator tab, as shown in Figure A-8.

Figure A-8 Created TPF Project

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 307 Creating the directory and source files using the shell

The next task is to create the source files for the application on the operating system. The TPF Toolkit provides a shell for working with remote systems, such as Linux: 1. Open a shell to a system by first opening the Remote System Explorer perspective by choosing Window  Open Perspective  Other  Remote System Explorer, as shown in Figure A-9. Click OK.

Figure A-9 Open Remote System Explorer Perspective

308 z/TPF Application Modernization using Standard and Open Middleware 2. In the Remote Systems tab, expand the linux connection, right-click Shells, and choose Launch Shell, as shown in Figure A-10.

Figure A-10 Launch Shell for Linux from the Remote System view

Figure A-11 shows the shell.

Figure A-11 A Linux Shell

In the Linux shell, you can create directories, move files, and so on. Figure A-12 on page 310 shows the soa subdirectory that was created.

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 309 Figure A-12 Linux Shell usage

Folders can also be created using the File  New  Folder menu options.

310 z/TPF Application Modernization using Standard and Open Middleware 3. Select the File  New  File menu option to create files to add to the project. Select the soa directory as the parent folder and specify the following file names: – cha0.c – cha0.mak – cha1.mak – gettime.cpp – gettime.h – outputcatcher.cpp Figure A-13 shows the creation of the files. Click Next.

Figure A-13 Create files

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 311 4. Select the Book Files filter, and click Finish. Figure A-14 shows the selection of the filter.

Figure A-14 Choose files filter

The files created are automatically opened in the editor without any content. Each file type is opened in different type of editor, indicated by the icon shown next to the file name in the tab at the top of the view. Each editor does appropriate syntax highlighting, type ahead, and a variety of other features unique to each file type. Figure A-15 shows the created files.

Figure A-15 Created empty files

Adding content to the files

Now that the files are created, you can enter the content into them. This example illustrates a web service application shown in Figure A-16 on page 313. This section contains the content of the files for the web service.

312 z/TPF Application Modernization using Standard and Open Middleware HTTP SOAP SOAP getTime getTime Request Request Web cha0.c APACHE TCP/IP Services Daemon CHA0(tpfSoapMsgCtx*) Handler HTTP SOAP SOAP getTime getTime Response Response getTimeAndBuildResponse() Create SOAP response Call gettime() Complete SOAP response

gettime() Register Program 4E0000,, CHA1 System Command Message Route command Routing Processor ZDTIM Service CHA1() Create event Format ZDTIM output Wait Post event Return ZDTIM output outputcatcher.cpp gettime.cpp

Figure A-16 Application Flow cha0.c

The CHA0 entry point in cha0.c is the main entry point of the web service application. CHA0 is called from the Apache server through the web services handler. Add the code to cha0.c, as shown in Example A-1.

Example A-1 cha0.c 1 #include /* TPF SOAP support */ 2 #include /* TPF XML APIs */ 3 #include /* tpfSoapMsgCtx structure */ 4 #include 5 6 7 int CHA0 (tpfSoapMsgCtx *msgCtx) 8 { 9 xmlNodesArray *xptr = NULL; 10 XMLHandle inputHandle = msgCtx->request_handle.xml_handle; 11 12 if(tpf_xml_positionAfterElementTagName(inputHandle,"Body") != 0) 13 return ErrorReplyNeeded; 14 15 xptr = tpf_xml_getNextElement(inputHandle, TYPE_TEXT); 16 if (xptr == NULL || xptr->returnCode != 0 || xptr->nodesArraySize == 0) 17 return ErrorReplyNeeded;

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 313 18 19 if ((strcasecmp(xptr->nodesArray[0].nodeName, "getTime") == 0)) 20 { 21 if(getTimeAndBuildResponse(&msgCtx->response_handle.xml_handle) == 0) 22 return ErrorReplyNeeded; 23 msgCtx->response_handle.type = TPF_HDL_RESP; 24 return SendReply; 25 } 26 return ErrorReplyNeeded; 27 }

The code performs the following operations:  Line 7 CHA0 receives a soap message input.  Lines 12-17 returns an error if the soap message is not properly formatted.  Line 19 and 26 returns an error is the soap message is not for a getTime request.  Line 21 and 22 calls getTimeAndBuildResponse in gettime.cpp to perform the getTime request function and returns an error if the return value from getTimeAndBuildResponse is an error.  Line 23 and 24 returns a response indicating that the getTime service was processed successfully. gettime.h

Example A-2 shows the code for the gettime.h header file. The code declares the getTimeAndBuildResponse function.

Example A-2 gettime.h 1 #ifndef gettime_h 2 #define gettime_h 3 4 #include 5 6 #ifdef __cplusplus 7 extern "C" 8 #endif 9 int getTimeAndBuildResponse(XMLHandle* h); 10 11 #endif gettime.cpp

The code for the gettime.cpp file is shown in Example A-3. The code implements the core functionality of the web service application.

Example A-3 gettime.cpp 1 #include 2 #include 3 4 int getTime(char*& systemHeapArea, int & numberOfPages, char heapToken[8]); 5 char* getHours(const char* const s);

314 z/TPF Application Modernization using Standard and Open Middleware 6 char* getMinutes(const char* const s); 7 char* getSeconds(const char* const s); 8 9 int getTimeAndBuildResponse(XMLHandle* h) { 10 11 int numberOfPages; 12 char heapToken[8]; 13 char* systemHeapArea; 14 15 // Build XML and SOAP headers for the output of the SOAP message 16 tpf_xml_initialize_handle(h, NO_PARSER, 0); 17 tpf_xml_createXMLstructure(*h, "1.0", 819, "ISO-8859-1", STANDALONE_YES, 2, 18 "Web Service Wrapper Sample", "getTimeResponse"); 19 tpf_xml_appendElement(*h, 0, "Envelope", 0, "SOAP-ENV", 20 "http://schemas.xmlsoap.org/soap/envelope/", 0); 21 tpf_xml_appendElement(*h, "Envelope", "Body", 0, "SOAP-ENV", 22 "http://schemas.xmlsoap.org/soap/envelope/", 0); 23 tpf_xml_appendElement(*h, "Body", "getTimeResponse", 0, "ns1", 24 "http://9.57.13.89/getTime", 0); 25 26 // Get the current time and put it in the output of the SOAP message 27 if(getTime(systemHeapArea,numberOfPages,heapToken) == 0) 28 return 0; 29 tpf_xml_appendElement(*h, "getTimeResponse", "hours", 30 getHours(systemHeapArea), 31 "ns1", "http://9.57.13.89/getTime", 0); 32 tpf_xml_appendElement(*h, "getTimeResponse", "minutes", 33 getMinutes(systemHeapArea), 34 "ns1", "http://9.57.13.89/getTime", 0); 35 tpf_xml_appendElement(*h, "getTimeResponse", "seconds", 36 getSeconds(systemHeapArea), 37 "ns1", "http://9.57.13.89/getTime", 0); 38 39 //clean up our system heap usage 40 rsysc(systemHeapArea,numberOfPages,heapToken); 41 return 1; 42 } 43 44 int getTime(char*& systemHeapArea, int & numberOfPages, char heapToken[8]) { 45 46 // Register the terminal and CHA1 to Program Command Routing Service (PCRS) 47 int lniata = 0x004E0000; 48 pcrs_input pi; 49 pi.operation = PCRS_REGISTER; 50 pi.lniata = lniata; 51 strncpy(pi.pgm_name, "CHA1", sizeof "CHA1"); 52 PCRS_RC rc; 53 rc = tpf_pcrs(&pi); 54 if(rc != PCRS_OK) { 55 if(rc != PCRS_LNIATA_ALREADY_REG) { 56 return 0; 57 } 58 } 59

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 315 60 // Instruct PCRS to run the ZDTIM command to get the system time 61 pi.operation = PCRS_ROUTECMD; 62 pi.command = "ZDTIM"; 63 pi.cmd_len = strlen("ZDTIM"); 64 rc = tpf_pcrs(&pi); 65 if(rc != PCRS_OK) { 66 return 0; 67 } 68 69 // Create a core block event for Data Level 10 to signal completion of CHA1 70 ev0bk event; 71 memcpy(event.evnbkn, "CHAL", sizeof "CHAL"); 72 memcpy(event.evnbkn+sizeof "CHAL", &lniata, sizeof lniata); 73 if(evntc(&event, EVENT_CB_DA, 'Y', 0, EVNTC_NORM) != 0) { 74 return 0; 75 } 76 77 // Wait for CHA1 to complete. Once complete, unregister from the PCRS 78 if(evnwc(&event, EVENT_CB_DA) != 0) { 79 pi.operation = PCRS_UNREGISTER; 80 rc = tpf_pcrs(&pi); 81 return 0; 82 } 83 pi.operation = PCRS_UNREGISTER; 84 rc = tpf_pcrs(&pi); 85 if(!levtest(DA)) { 86 return 0; 87 } 88 89 // Retrieve the pointer to system heap, the number of pages, the heap token 90 // and the length of the command output from Data Level 10 of the ECB 91 char* levelA = reinterpret_cast(ecbptr()->ce1cra); 92 memcpy(&systemHeapArea, levelA, sizeof systemHeapArea); 93 memcpy(&numberOfPages, levelA + sizeof systemHeapArea, sizeof numberOfPages); 94 memcpy(heapToken, 95 levelA + sizeof systemHeapArea + sizeof numberOfPages, 96 sizeof heapToken); 97 relcc(DA); 98 return 1; 99 } 100 101 // Search for the output message in the ZDTIM result and return the hours 102 char* getHours(const char* const s) { 103 char* p = strstr(s, "DTIM0001I") + 10; 104 *(p+2) = 0; 105 return p; 106 } 107 108 // Search for the output message in the ZDTIM result and return the minutes 109 char* getMinutes(const char* const s) { 110 char* p = strstr(s, "DTIM0001I") + 13; 111 *(p+2) = 0; 112 return p; 113 }

316 z/TPF Application Modernization using Standard and Open Middleware 114 115 // Search for the output message in the ZDTIM result and return the seconds 116 char* getSeconds(const char* const s) { 117 char* p = strstr(s, "DTIM0001I") + 16; 118 *(p+2) = 0; 119 return p; 120 }

In Example A-3 on page 314, the gettime.cpp file performs the following operations:  Lines 9-42 implements the getTimeAndBuildResponse function.  Lines 16-24 creates the SOAP response.  Lines 27 and 28 calls the gettime function to issue the ZDTIM and an error is returned if the gettime function returns an error.  Lines 29-37 adds the result to the response by calling the getHours, getMinutes, and getSeconds functions to retrieve the values from the ZDTIM output.  Lines 40 and 41 clean up the environment and returns success.  Lines 44-99 implements the gettime function.  Lines 47-58 registers program CHA1 and LNIATA 4E0000 with PCRS.  Lines 61-67 routes the ZDTIM command to PCRS.  Lines 78-82 creates an event to wait for the response from ZDTIM to be posted by CHA1.  Lines 83-87 unregisters program CHA1 and LNIATA 4E0000 with PCRS.  Lines 91-96 set up the return values for getTimeAndBuildResponse to operate on.  Lines 97 and 98 clean up the environment and returns success.  Lines 102-120 implement the getHours, getMinutes, and getSeconds functions to process the ZDTIM out and return the desired values. chao.mak

Example A-4 shows the code for the cha0.mak file. The code defines how maketpf builds the CHA0 CSO.

Example A-4 cha0.mak 1 ####################################################################### 2 # Define shared object name 3 ####################################################################### 4 5 APP := CHA0 6 APP_ENTRY := CHA0 7 APP_EXPORT := ENTRY 8 9 # XML APIs 10 LIBS := CXAP 11 # tpf_soap_build_fault_ext 12 LIBS += CWSA 13 14 ####################################################################### 15 # Environments needed for build 16 #

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 317 17 # NOTE: You may need to update the maketpf_env list to add 18 # environment(s) that are unique to your configuration. 19 ####################################################################### 20 21 maketpf_env := drvs 22 maketpf_env += base_rt 23 maketpf_env += system 24 maketpf_env += filesys 25 26 TPF_DRIVER := soa 27 28 ####################################################################### 29 # Segments to be compiled with g++ compiler 30 ####################################################################### 31 32 C_SRC := cha0.c 33 CXX_SRC := gettime.cpp 34 35 ####################################################################### 36 # Include maketpf build rules 37 ####################################################################### 38 39 include maketpf.rules

In Example A-4 on page 317:  Lines 5-7 declare the CSO name, main entry point, and entry point type.  Lines 10-12 declare the libraries that the CHA0 must link to.  Lines 21-24 declares the maketpf environment (for example the directory locations).  Line 26 declares the driver name to be used by the drvs maketpf environment.  Lines 32 and 33 declare the source files that need to be built in CHA0.

The outputcatcher.cpp file

The outputcatcher.cpp file defines the CHA1 function, which receives the output from PCRS and copies it into a system heap block for CHA0 to process. Example A-5 shows the code.

Example A-5 outputcatcher.cpp 1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 11 extern "C" void CHA1() { 12 // If Data Level 0 in the ECB does not exist exit the program 13 if(!levtest(D0)) { 14 exit(0); 15 } 16

318 z/TPF Application Modernization using Standard and Open Middleware 17 // Retrieve the ZDTIM output from Data Level 0 18 am0sg* omsg = reinterpret_cast(ecbptr()->ce1cr0); 19 int lniata = omsg->am0lit; 20 int magic = 5; // sizeof am0sg::am0lit + 21 // sizeof am0sg::am0np1 + 22 // sizeof am0sg::am0np2 23 24 // Place the ZDTIM output into an output stream 25 std::ostringstream os; 26 os.write(&(omsg->am0txt) , omsg->am0cct-magic); 27 28 // Process additional command output messages and store in the output stream 29 if(reinterpret_cast(omsg->am0fch) != 0) { 30 unsigned int* fileAddress = reinterpret_cast(omsg->am0fch); 31 char fileId[2]; 32 memcpy(fileId,omsg->am0rid, sizeof fileId); 33 relcc(D0); 34 35 while(fileAddress != 0) { 36 omsg = reinterpret_cast 37 (find_record(D0, const_cast(fileAddress), fileId, 38 '\0', NOHOLD)); 39 if(omsg == 0) { 40 fileAddress = 0; 41 } else { 42 os.write(&(omsg->am0txt), omsg->am0cct-magic); 43 } 44 if(fileAddress != 0) { 45 fileAddress = reinterpret_cast(omsg->am0fch); 46 memcpy(fileId, omsg->am0rid, sizeof fileId); 47 } 48 crusa(1,D0); 49 } 50 } 51 52 // Initialize the number of pages of memory and the heap token and retrieve 53 // the pointer to the system heap 54 int numberOfPages = (os.rdbuf()->str().size() + _4K_SIZE) / _4K_SIZE; 55 char heapToken[8] = { 'T', 'O', 'O', 'L', 'K', 'I', 'T', '0'}; 56 char* systemHeapArea = reinterpret_cast 57 (gsysc(numberOfPages, heapToken)); 58 if(systemHeapArea != 0) { 59 cinfc(CINFC_WRITE,CINFC_CMMHEAP); 60 memcpy(systemHeapArea,os.rdbuf()->str().c_str(),os.rdbuf()->str().size()); 61 // remove nulls in ZDTIM output to allow for C string manipulation 62 for (unsigned int i=0; istr().size(); i++) { 63 if (systemHeapArea[i] == 0) { 64 systemHeapArea[i] = 1; 65 } 66 } 67 keyrc(); 68 69 // Put the pointer to the system heap, the number of pages, the heap token 70 // and the length of the command output into Data Level 10 in the ECB

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 319 71 char* levelA = reinterpret_cast(getcc(DA,GETCC_TYPE,L4)); 72 memcpy(levelA, &systemHeapArea, sizeof systemHeapArea); 73 memcpy(levelA + sizeof systemHeapArea, 74 &numberOfPages, 75 sizeof numberOfPages); 76 memcpy(levelA + sizeof systemHeapArea + sizeof numberOfPages, 77 heapToken, 78 sizeof heapToken); 79 int lengthOfMessage = os.rdbuf()->str().size(); 80 memcpy(levelA + sizeof systemHeapArea + sizeof numberOfPages + 81 sizeof heapToken, &lengthOfMessage, sizeof lengthOfMessage); 82 83 // Post the event to signal the completion of CHA1 84 ev0bk event; 85 memcpy(event.evnbkn, "CHAL", sizeof "CHAL"); 86 memcpy(event.evnbkn+sizeof "CHAL", &lniata, sizeof lniata); 87 postc(&event, EVENT_CB_DA, 0); 88 } 89 exit(0); 90 }

In Example A-5 on page 318:  Lines 11-90 defines the CHA1 function.  Lines 13-15 ensures a response is present to process.  Lines 18-26 moves the response into an ostringstream for ease of processing.  Lines 29-50 processes any message chain, adds the additional text to the ostringstream object, and cleans up the input blocks.  Lines 54-57 allocates a system heap block.  Lines 59-67 writes the ZDTIM response message into the system heap block.  Lines 71-81 gets a core block and builds a response to pass to CHA0 by way of an ECB data level.  Lines 84-87 defines and post the event back to CHA0.  Line 89 exits the CHA1 ECB.

The chai.mak file

The cha1.mak file defines how maketpf builds the CHA1 CSO. Example A-6 shows the code.

Example A-6 cha1.mak 1 ####################################################################### 2 # Define shared object name 3 ####################################################################### 4 APP := CHA1 5 APP_EXPORT := ENTRY 6 APP_ENTRY := CHA1 7 8 9 10 ####################################################################### 11 # Environments needed for build

320 z/TPF Application Modernization using Standard and Open Middleware 12 ####################################################################### 13 maketpf_env := drvs 14 maketpf_env += base_rt 15 maketpf_env += system 16 17 TPF_DRIVER := soa 18 19 ####################################################################### 20 # CPP segments 21 ####################################################################### 22 CXX_SRC := outputcatcher.cpp 23 CXXFLAGS_CHA1_outputcatcher := -fno-strict-aliasing 24 25 26 27 ####################################################################### 28 # Include maketpf build rules 29 ####################################################################### 30 include maketpf.rules

In Example A-6 on page 320:  Lines 4-6 declare the CSO name, main entry point, and entry point type.  Lines 13-15 declares the maketpf environment (for example the directory locations).  Line 17 declares the driver name to be used by the drvs maketpf environment.  Lines 22 declares the source file that needs to be built in CHA1.  Line 23 turns off a compile option ensures casting operations are of the like type and size. This allows casting from 4 byte pointers to 8 byte pointers without the compiler issuing a warning.

Saving the files

After copying the content into the empty files, save each file. Figure A-17 on page 322 shows one of the files with content.

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 321 Figure A-17 Editor with content

Creating the makeTPF configuration and control files

The z/TPF build mechanism MakeTPF is used to build the code in the files for deployment. The makefiles for shared objects can be created through the TPF Toolkit, or manually. In this example, the makefiles were manually created, as shown in Example A-4 on page 317 and Example A-6 on page 320.

Updating the target environment properties

The target environment can provide many default settings for your build. For example, our CUR_BAS target environment provides the location of the TPF source code as /ztpf/cur. This is the TPF_ROOT in the maketpf.cfg file. The target environment properties page allows you to switch to another target environment. To view or change the target environment: 1. Right-click the book project, and select Properties.

322 z/TPF Application Modernization using Standard and Open Middleware 2. In the project’s properties menu, select Target Environments, as shown in Figure A-18.

Figure A-18 Selecting Target Environments

Creating the MakeTPF configuration file

Next the MakeTPF configuration file has to be created. The configuration file is used to define the build space and to identify:  The root directory names where the application and z/TPF code reside. You can specify multiple root directory names and each one is concatenated. The files are pulled on a top-down, first-found basis.  The z/TPF system or subsystem being built.  User overrides to compile, assemble, and link flags.

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 323  User overrides to process options, such as whether to keep clean listings.

To create the MakeTPF configuration file: 1. Right-click the book project, and select Properties. 2. In the project’s properties menu, select TPF Make Configuration, as shown in Figure A-19. The settings from this dialog go to the maketpf.cfg file on the Linux system, in the book directory as specified by the remote working directory we specified when creating the project.

Figure A-19 Creating the MakeTPF configuration

324 z/TPF Application Modernization using Standard and Open Middleware The TPF Source location /ztpf/cur is already set in the background because the target environment was selected when the project was created. Since this project will not create or modify any z/TPF system code, the TPF Source field can be left blank. The order in which the directories are specified is also the search order. 3. Enter BSS as the Basic sub-system Name for the local TPF test system. 4. Select the Application tab to specify the location of the application source files. Here the order is relevant again, but for this example, there is only one location to look for source files and it is the project’s directory, /home/jwisnie/book. The target environment will append /ztpf/curdrv to the application source directory list, as shown in Figure A-20.

Figure A-20 Setting the application Source directory in the MakeTPF configuration

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 325 5. Select the Build Options tab to override the default build options, as shown in Figure A-21. YES is selected for the verify link references setting to ensure that you know at compile time if function calls cannot be resolved properly, The compile option -O0 is specified for both C and C++ programs. This setting specifies that the programs are compiled without optimization, allowing full use of the debugger.

Figure A-21 Specifying build options

326 z/TPF Application Modernization using Standard and Open Middleware 6. Switch to the LoadTPF Options tab to specify the options used to load files to the z/TPF from the Linux system. In this example, the Loadset Name is labwork, the Loadfile Name is jwisnie.oldr, and the Destination directory location on z/TPF is /tmp, as shown in Figure A-22.

Figure A-22 Specifying the load options

7. Select the Advanced tab. Specify the z/TPF test system’s TCP/IP address by assigning it to the variable LOADTPF_IP, as shown in Figure A-23 on page 328.

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 327 Figure A-23 Specifying the test system’s TCP/IP address

8. Click OK to store the settings into the proj.maketpf.cfg file. The TPF Toolkit will generate the maketpf.cfg file from the proj.maketpf.cfg file at build time.

Creating the MakeTPF control file

The final step is to create the MakeTPF control file: 1. To create the MakeTPF control file, right-click the book project, and select Properties. In the project’s properties menu, select TPF Make Build List, as shown in Figure A-24 on page 329. The control file is named maketpf.cntl and is located alongside maketpf.cfg in

328 z/TPF Application Modernization using Standard and Open Middleware the project's remote working directory. The makeTPF control file lists all program segments (shared objects) that belong to a project and the build command builds the shared object in the order specified by the control file.

Figure A-24 Creating the MakeTPF control file

2. Create the entries in the MakeTPF control file. Click the Add, select Create new entry, and click Next, as shown in Figure A-25 on page 330.

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 329 Figure A-25 Creating a new MakeTPF control file entry

3. In the program description menu, specify the shared object’s name. In this example, CHA0 is specified first (Figure A-26), and then later the process is repeated for CHA1. Click Next.

Figure A-26 Creating CHA0 in the maketpf control file

4. In the Program build information menu, specify the Makefile for the shared object (/home/jwisnie/book/soa/cha0.mak). Click Next. 5. In the Program load information menu, as shown in Figure A-27 on page 331, Debug trace is selected, so programs can be debugged later. Select the Restricted Macros and Key0 Macro to allow the program to write to system heap.

330 z/TPF Application Modernization using Standard and Open Middleware Figure A-27 Specifying the program load information

6. Click Finish to complete the set up of the MakeTPF control file. 7. Repeat this procedure starting with step 2 to add CHA1. 8. When both control files are created, as is shown in Figure A-28 on page 332, click OK.

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 331 Figure A-28 Completing the MakeTPF control file

Example A-7 shows the actual content of the MakeTPF control file, maketpf.cntl.

Example A-7 MakeTPF control file contents

1. # MAKETPF CONTROL FILE VERSION 2 INTRODUCED IN PJ31515 2. CHA0;APP;soa/cha0.mak;1;ALL;OBJ;TPF_SBALL;LOADONLINE;STUB;DEMAND;DEBUG;;NONE;;;N OBPAUTH;RESTRICT;NOMONTC;KEY0;NOCMB;;;;;;;;;;;;;;;

332 z/TPF Application Modernization using Standard and Open Middleware 3. CHA1;APP;soa/cha1.mak;1;ALL;OBJ;TPF_SBALL;LOADONLINE;STUB;DEMAND;DEBUG;;NONE;;;N OBPAUTH;RESTRICT;NOMONTC;KEY0;NOCMB;;;;;;;;;;;;;;;

Building the programs

The next step is to build the project: 1. Right-click the book project, and select Build using MakeTPF and Build (Compile and Link), as shown in Figure A-29.

Figure A-29 Building the project

2. Diagnose any build errors. When a build error occurs, the Remote Error List is updated with a list of the errors as shown in Figure A-30 on page 334. Clicking an error automatically opens the source file and shows the location of the errors. In this example, a semicolon was removed to produce an error.

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 333 Figure A-30 Build error

It can be helpful to read the output from maketpf itself. The output of maketpf is in the Remote Console, as shown in Figure A-31.

Figure A-31 Build error shown in the remote console

Loading the programs onto the z/TPF system

To transfer the programs to be loaded from Linux to z/TPF, use the loadtpf utility: 1. Invoke the utility by right-clicking the book project. Select Load using LoadTPF, as shown in Figure A-32 on page 335.

334 z/TPF Application Modernization using Standard and Open Middleware Figure A-32 Starting the load of the project

2. Switch over to the z/TPF system to finish the load and activate the shared objects. The TPF Toolkit has a 3270 emulator that is available by clicking Host Connection Emulator Session from the tool bar, as shown in Figure A-33.

Figure A-33 Starting the 3270 emulator

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 335 3. In the pop-up box, set the Host Name to your TPF System, set the code page to the appropriate selection, and set the session name to an identifiable value, as shown in Figure A-34. Click Finish.

Figure A-34 Configuring the 3270 emulator

336 z/TPF Application Modernization using Standard and Open Middleware 4. Click Finish to start the emulator, shown in Figure A-35.

Figure A-35 The 3270 emulator

Notice the Host Properties tab in the lower-left corner of Figure A-35. This allows you to disconnect your session, reconfigure the session, and so on. 5. Confirm that the loadset has been FTPed to our test system. Figure A-36 shows the ZFILE command output that shows that the transferred file containing the shared objects (named jwisnie.oldr) arrived in directory /tmp on z/TPF.

Figure A-36 ZFILE Is command

Appendix A. Using the IBM TPF Toolkit to build projects and load them to the runtime system 337 6. To load the programs from the file jwisnie.oldr, create a data definition name (ddname) for the file using the ZDSMG command, as shown in Figure A-37.

Figure A-37 ZDSMG command

7. After that, the programs can be loaded and activated, and they are available to be used on the z/TPF system, as shown in Figure A-38.

Figure A-38 ZOLDR commands

338 z/TPF Application Modernization using Standard and Open Middleware B

Appendix B. Using the IBM TPF Toolkit web services tooling to create and deploy a web service

The TPF Toolkit comes with Web Service Tools to aid in developing, deploying, and testing web service applications for z/TPF. This appendix tells you how to create a web services Descriptor Language (WSDL) file, a deployment descriptor, and how to deploy and test a web service. This discussion is based upon the tutorial "Developing web services applications with IBM TPF Toolkit" in the TPF Toolkit help documentation that is included in the TPF Toolkit. This discussion will start where Appendix A, “Using the IBM TPF Toolkit to build projects and load them to the runtime system” on page 301 ends.

This discussion assumes that the Apache 2.2.9 HTTP Server is installed and running on z/TPF, as described in Chapter 4, “The z/TPF communications bindings” on page 55 and at the following website: http://tpf.ncsa.illinois.edu/download/readme-ztpfapache2.html

This discussion also assumes that the z/TPF debugger daemon is running, as described at the following website: http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztpfdf .doc_put.cur/gtpd3/d3tconnection.html

This appendix contains the following topics:  “Creating the WSDL file” on page 340  “Creating the provider web service deployment descriptor file” on page 347  “Deploying the provider web service” on page 351  “Testing the provider web service” on page 355

© Copyright IBM Corp. 2013. All rights reserved. 339 Creating the WSDL file

The WSDL file is the base file required for web services applications. It provides the standard specification for describing the inputs and outputs of this Web Service. Use the following steps to create a WSDL file. 1. Right-click the book project, and select New  WSDL File, as shown in Figure B-1.

Figure B-1 New WSDL file

2. Select the book folder so that the new WSDL file is at the same location as the maketpf.cfg and maketpf.cntl files are located. Enter getTime.wsdl in the File Name field, as shown in Figure B-2 on page 341. Click Next.

340 z/TPF Application Modernization using Standard and Open Middleware Figure B-2 WSDL Wizard

Appendix B. Using the IBM TPF Toolkit web services tooling to create and deploy a web service 341 3. On the TPF Filter page, select the Book Files filter, and click Next. 4. On the Options page, specify http://9.57.13.89/getTime/ in the Target Namespace field, where 9.57.13.89 is the IP address of the z/TPF system the web service will be running on. Leave all of the other values with the defaults as shown in Figure B-3. Click Finish.

Figure B-3 WSDL options

5. The getTime.wsdl file is created and opened in the WSDL Editor. The WSDL is an XML file. Click the Source tab at the bottom of the WSDL editor to view the XML source. The Design tab of the WSDL editor presents the WSDL definition in a graphical interface that can be edited, as shown in Figure B-4.

Figure B-4 WSDL Editor

Select the getTimeSoap port in the getTime service object (click the box inside the object on the far left). Modify the Address to be http://9.57.13.89/getTime. You can edit in the GUI interface or in the properties pane shown in Figure B-5 on page 343.

342 z/TPF Application Modernization using Standard and Open Middleware Figure B-5 Edit the getTime Service

6. Change the NewOperation operation in the getTime port type object to getTime by selecting NewOperation with the gear icon next to it inside the object on the far right, as shown in Figure B-6.

Figure B-6 Edit the operation in the port type object

7. Change the input part name parameters in the getTime port type object to getTimeRequest by selecting the text parameters in the input row of the object on the far right. Change the output part name parameters in the getTime port type object to getTimeResponse by selecting the text parameters in the output row of the object on the far right. Figure B-7 on page 344 shows the result of these changes.

Appendix B. Using the IBM TPF Toolkit web services tooling to create and deploy a web service 343 Figure B-7 Edit the input and output part name

8. In the WSDL Editor, click the arrow beside the input line. A new edit window opens for the Online Schema of gettime.wsdl showing the gettime input element, as shown in Figure B-8.

Figure B-8 Edit input schema

344 z/TPF Application Modernization using Standard and Open Middleware 9. Right-click the sequence icon ( ) in the getTimeType graphic, and select Delete. The result is shown in Figure B-9.

Figure B-9 Result of editing the input schema

10.Select the gettime.wsdl tab to return to the WSDL Editor. In the WSDL Editor, click the arrow beside the output line. A new edit window opens for the Inline Schema of gettime.wsdl, showing the getTimeResponse output element shown in Figure B-10.

Figure B-10 Edit output schema

11.In the WSDL Schema Editor, select the out element in the getTimeResponseType graphic, and change the Name field name from out to hours.

Appendix B. Using the IBM TPF Toolkit web services tooling to create and deploy a web service 345 12.Right-click the hours element, and select insert Element  After. A new element called NewElement is added to getTimeResponseType. The name appears highlighted, so you can edit the name of the new element. Change the name to minutes. 13.Right-click the minutes element, and select insert Element  After. A new element called NewElement is added to getTimeResponseType. Change the name to seconds. The result is shown in Figure B-11.

Figure B-11 Result of output schema edit

14.Select the gettime.wsdl tab to return to the WSDL Editor. Click the binding graphic (the small icon in the center of the WSDL editor), and change the Name field to tpfservice, as shown in Figure B-12.

Figure B-12 Result of editing the binding

346 z/TPF Application Modernization using Standard and Open Middleware 15.Save the getTime.wsdl file. Exit the getTime.wsdl and Inline Schema of getTime.wsdl files in the editor view.

Creating the provider web service deployment descriptor file

A provider Web service deployment descriptor (dd) defines the routing mechanism and other processing information, including the list of SOAP message handlers, that is required to take a Web service request received by the SOAP support and presents it to a z/TPF application for processing. Use the following procedure to create a provider Web service deployment descriptor.

Appendix B. Using the IBM TPF Toolkit web services tooling to create and deploy a web service 347 1. Right-click the getTime.wsdl file in the TPF Project Navigator pane, and select Web Services  Create provider deployment descriptor, as shown in Figure B-13.

Figure B-13 Create provider deployment descriptor

348 z/TPF Application Modernization using Standard and Open Middleware 2. On the File page of the New Provider Web Service Deployment Descriptor Wizard, type gettime_dd.xml as the file name, as shown in Figure B-14. Click Next.

Figure B-14 Name the provider deployment descriptor

3. Select the Book Files filter, and then click Next.

Appendix B. Using the IBM TPF Toolkit web services tooling to create and deploy a web service 349 4. On the Deployment Descriptor page, specify CHA0 as the wrapper program, ensure that only SOAP1.2 and BP1.1_SSBP1.0 are checked, and then click Finish, as shown in Figure B-15.

Figure B-15 Complete the provider deployment descriptor

The deployment descriptor is now created and you can deploy the web service.

350 z/TPF Application Modernization using Standard and Open Middleware Deploying the provider web service

Deploying a web service on z/TPF makes that web service available for use. Use the following procedure: 1. Right-click getTime_dd.xml, and select Web Services  Transfer to TPF  Target Environment for Web Services, as shown in Figure B-16.

Figure B-16 Transfer the deployment descriptor to z/TPF

2. Depending on how you set up your target environment, you might be prompted for the IP address of the z/TPF test system. Provide that IP address, if necessary. Specify the user ID and password of that z/TPF test system, if prompted. The Remote Console displays the result of the Transfer to TPF action, as shown in Figure B-17 on page 352.

Appendix B. Using the IBM TPF Toolkit web services tooling to create and deploy a web service 351 Figure B-17 Result of transferring the deployment descriptor to z/TPF

3. Switch from the Remote System Explorer perspective to the Remote Explorer view. Expand the connection to the z/TPF test system, and expand the Provider web services subsystem and the All Provider Web Services filter. The /getTime web service that you just transferred displays, as shown in Figure B-18.

Figure B-18 /getTime web service in the Remote Explorer

352 z/TPF Application Modernization using Standard and Open Middleware 4. Right-click the /gettime web service, and select Add, as shown in Figure B-19.

Figure B-19 /getTime add

5. The Remote Console at the bottom of the window indicates that the ADD action has been scheduled, as shown in Figure B-20 on page 354. The 3270 console shows the results of the ADD as follows: WSAT0037I 16.40.05 ADD OF /getTime SCHEDULED FOR PROCESSOR B+ WSAT0017I 16.40.05 WEB SERVICE /getTime ADDED SUCCESSFULLY ON PROCESSOR B AS REQUESTED BY B+.

Appendix B. Using the IBM TPF Toolkit web services tooling to create and deploy a web service 353 Figure B-20 /getTime add result

6. Right-click the /gettime web service, and select Deploy. The Remote Console indicates that the Deploy action has been scheduled, as shown in Figure B-21 on page 355. The 3270 console shows the results of the Deploy as follows: WSAT0037I 16.47.20 DEPLOY OF /getTime SCHEDULED FOR PROCESSOR B+ WSAT0001I 16.47.20 WEB SERVICE /getTime DEPLOYED SUCCESSFULLY ON PROCESSOR B AS REQUESTED BY B+

354 z/TPF Application Modernization using Standard and Open Middleware Figure B-21 /getTime deploy result

Testing the provider web service

You can test the web service application after it has been deployed. Use the following procedure: 1. Switch to the TPF Toolkit perspective. Right-click the getTime.wsdl files, and select Web Services  Test with Web Services Explorer action. The Web Service Explorer view displays, as shown in Figure B-22 on page 356.

Appendix B. Using the IBM TPF Toolkit web services tooling to create and deploy a web service 355 Figure B-22 Web Service Explorer

2. Click WSDL Page ( ) on the Web Services Explorer tool bar to show the WSDL page. 3. In the Navigator pane of the Web Services Explorer view, select the WSDL Main node. Open WSDL appears in the Action pane, as shown in Figure B-23.

Figure B-23 Web Service Explorer WSDL Page button

4. Click the Browse text link. In the WSDL Browser dialog, perform the following actions: a. In the Category dropdown list, select Workspace WSDL documents.

356 z/TPF Application Modernization using Standard and Open Middleware b. In the Workspace Projects dropdown list, select RemoteSystemsTempFiles. c. In the WSDL URL dropdown list, select platform:/resource/RemoteSystemsTempFiles//home//book/ getTime.wsdl. d. Figure B-24 shows the results. Click Go.

Figure B-24 WSDL Browser dialog

The WSDL URL field in the Open WSDL page is now populated with the value, as shown in Figure B-25.

Figure B-25 Open WSDL page

Appendix B. Using the IBM TPF Toolkit web services tooling to create and deploy a web service 357 5. Click Go in the Actions pane of the Open WSDL page. The Navigator pane populates with the service, binding, and operations details of the web service on your z/TPF system. 6. Expand the tpfservice binding, and select the getTime operation. A page appears where you can invoke a WSDL Operation. See Figure B-26.

Figure B-26 Page to invoke a WSDL Operation

7. Because the web services application accesses system heap storage, the shared objects require KEY0 and RESTRICT authority. When you created the maketpf.cntl file in “Creating the MakeTPF control file” on page 328, you specified KEY0 and RESTRICT. However, you did not build and load a new IPAT. As such, the shared objects were Online Loaded as unallocated programs and they do not have the required access permissions. In order to test the application, you need to alter the PAT table to grant our applications KEY0 and RESTRICT authority. Issue the following commands from a z/TPF terminal with CRAS authority: ZAPAT CHA1 KEY0 RESTRICT COPY-CORE ZAPAT CHA0 KEY0 RESTRICT COPY-CORE 8. The web service application also uses LNIATA 4E0000 through the PCRS interface. Issue the following command to provide CRAS authority to LNIATA: ZACRS REP A01 4E0000 CPUID-B TYPE-CRT 9. Activate the LNIATA terminal 4E0000 by dialing into your z/TPF sessions using another 3270 terminal and issuing LOGI SMPB (you might need to issue #cp def graf 8B and ZRIPL your z/TPF session prior to issuing LOGI SMPB on the second z/TPF terminal). Figure B-27 on page 359 shows the Web Services Explorer with a Prime CRAS 3270 terminal and the dialed in terminal using LNIATA 4E0000 in the TPF Toolkit Editor view.

358 z/TPF Application Modernization using Standard and Open Middleware Figure B-27 Web Services Explorer and z/TPF 3270 terminals

10.Click Go in the Invoke a WSDL Operation pane in the Actions Pane. The response from the web service is displayed in the Status pane as shown in Figure B-28 on page 360.

Appendix B. Using the IBM TPF Toolkit web services tooling to create and deploy a web service 359 Figure B-28 WSDL execution results

360 z/TPF Application Modernization using Standard and Open Middleware C

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools

This appendix contains information helpful in diagnostic situations.

This appendix contains the following topics:  “z/TPF debugger registration” on page 362  “The z/TPF debugger interface” on page 384  “z/TPF Debugger problem determination methodology example” on page 388  “Using the z/TPF Debugger dump viewer to debug application dumps” on page 394  “The ECB Monitor subsystem” on page 400  “The ECB Launcher subsystem” on page 404  “The IBM TPF Toolkit and the z/TPF Performance Analyzer” on page 409  “The IBM TPF Toolkit and the z/TPF Code Coverage Tool” on page 414

© Copyright IBM Corp. 2013. All rights reserved. 361 z/TPF debugger registration

The z/TPF Debugger is ECB (process/thread) centric. This means that when you use the z/TPF Debugger, you are debugging an ECB regardless of which programs the ECB executes (as opposed to debugging a program regardless of which ECBs execute that program). As such, of the registration process as a selection process of which ECB will be debugged. For example, if program ABCD is registered, the first ECB that executes program ABCD will start the debugging process and the registration entry will be moved to an active state. Other ECBs that execute program ABCD will not be impacted by the debugger until the first ECB that executed program ABCD is exited and the registration entry becomes inactive. At which point, the first ECB to enter program ABCD will start a separate debugger session using the previously inactive registration entry. Understanding the debugger registration is critical to successfully using the z/TPF Debugger.

Due to the nature of how SOA applications are started (typically as a created ECB instead of through the typical communication methods: LNIATA, LU, or TCP/IP), when registering an SOA application for debugging use the asterisk (*) for the LNIATA for the TPF Terminal. When registering with a four-character program name, this form is registration is call registration by program name meaning that the TPF Terminal type is not considered when selecting and ECB for debugging. It might be helpful to think of the TPF Terminal as an ECB filter similar to how the conditional registration feature filters ECB. The TPF Terminal might say only debug this ECB if the TPF Terminal came from LNIATA 010000; whereas, conditional registration can say only debug this ECB if the condition is true where the value in CE1CR0 is equal to 0 at the time program ABCD was entered.

Building on the example from IBM TPF Toolkit Web Services Tooling, we review several different methods for registering the z/TPF Debugger to debug our web service application. The z/TPF debugger provides 6 different forms of registration: program, function, macro, system error, CTEST and user defined.

Registering by program

Use the following steps to register the z/TPF Debugger by program: 1. In the Remote System Explorer perspective in the Remove System view, expand the TPF connection and the Debug subsystem. 2. Create a new registration entry by right-clicking the Debug subsystem and then clicking New  New Session, as shown in Figure C-1 on page 363.

362 z/TPF Application Modernization using Standard and Open Middleware Figure C-1 Create new debug registration entry

3. This opens a New Debug Registration Session window, as shown in Figure C-2 on page 364, where you can perform the following actions: a. In the Terminal Name field, enter an asterisk (*) for the LNIATA. b. In the Select a registration type field, select Program. c. In the Registration Information text box, enter the application entry point CHA0, and click Add. d. Click Next.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 363 Figure C-2 Debug registration entry

4. Specify a Session label that will appear below the debug subsystem after the registration entry is created. Enter a meaningful label, such as labwork, and then click Next, as shown in Figure C-3 on page 365.

364 z/TPF Application Modernization using Standard and Open Middleware Figure C-3 Debug registration session label

5. The Remote debug information locator page allows you to tell z/TPF where the debug information should be automatically FTPed from. Debug information tells the debugger where variables are located in memory, where in the assembler instructions lines of source code start and end, and more. Since the code is built and loaded with debug information (the NODEBUG option was not specified, debug information is loaded to the system. To confirm that debug information is loaded to z/TPF for a particular program, enter zddbg disp dbginfo-XXXX where XXXX is the four-character program name and a debug file exists for the program you will debug. See Figure C-4 on page 366 for an example.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 365 Figure C-4 Debug information

6. Leave the default settings on the Remote debug information locator page, and click Next. Use the Source Lookup page (Figure C-5) to specify the location of the C/C++ source files for the debugger. Click Add, choose TPF Project, and select the book project. Click Finish.

Figure C-5 Source Lookup

7. Right-click the labwork registration entry, and then select Register, as shown in Figure C-6 on page 367. You might need to define and start the debugger daemon on z/TPF. Instructions for this are at the following website: http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztp fdf.doc_put.cur/gtpd3/d3tconnection.html

366 z/TPF Application Modernization using Standard and Open Middleware Figure C-6 Register the debugger

The result of the register action displays on the Remote Console, as shown in Figure C-7 on page 368. You can also use the zddbg disp all command to view the state of the registration table.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 367 Figure C-7 Register response

8. The debugger is now registered and you can start the web service application. Start the application exactly as described in “Testing the provider web service” on page 355, by clicking Go in the Web Services Explorer Actions pane. The z/TPF Debugger starts as shown in Figure C-8 on page 369.

368 z/TPF Application Modernization using Standard and Open Middleware Figure C-8 Debugger

Registering by function

Registration by function allows you to specify a function name so that when that function is executed, the debugger will start on that ECB. For example, if you want the debugger to start when the getTime function in object gettime.o in module CHA0 is called. To register by function: 1. In the Remote System view in the Remote system explorer, right-click the labwork registration entry and select Cancel Registration. 2. Right-click the labwork debug registration entry in the debug subsystem and choose Properties to edit the registration entry. Do the following: a. Since you are debugging a web services application, type an asterisk (*) in the Terminal Name field for the LNIATA. b. Specify the registration type, function name, module name, and object name, as shown in Figure C-9 on page 370, and click OK.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 369 Figure C-9 Register by function

3. Right-click the labwork registration entry, and select Register. Start the web service application, and the debugger will start the desired location, as shown in Figure C-10 on page 371.

370 z/TPF Application Modernization using Standard and Open Middleware Figure C-10 Register by Function debugger session

Registering by macro

Registering by macro allows you to specify an SVC macro name and one or more program names such that when that macro is executed from the program specified, the debugger will start on that ECB. For example, if you want the debugger to start when the gsysc macro was issued from CHA1. To register by macro: 1. In the Remote System view in the Remote system explorer, right-click the labwork registration entry, and choose Cancel Registration. 2. Right-click the labwork debug registration entry in the debug subsystem, and select Properties to edit the registration entry. Do the following: a. Since you are debugging a web services application, type an asterisk (*) in the Terminal Name field for the LNIATA. b. Specify the registration type, SVC macro name, and program name, as shown in Figure C-11 on page 372, and click OK.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 371 Figure C-11 Register by Macro

3. Right-click the labwork registration entry, and select Register. 4. Start the web service application, and the debugger will start the desired location as shown in Figure C-12 on page 373.

372 z/TPF Application Modernization using Standard and Open Middleware Figure C-12 Register by Macro debugger session

Registering by system error

Registering by system error allows you to specify a system error number and optionally a program name and object name such that when that system error occurs from the program specified, the debugger will start on that ECB. For example, if you want the debugger to start when an OPR-3 dump occurred from CHA0.

In this example, cha0.c on line 13 has been modified as shown in Figure C-13 to cause an OPR-3 dump. Module CHA0 has been rebuilt and loadTPF is used to load the code in loadset OPR3DUMP.

Figure C-13 cha0.c modified to cause an OPR-3 dump

To register by system error: 1. In the Remote System view in the Remote system explorer, right-click the labwork registration entry, and select Cancel Registration. 2. Right-click the labwork debug registration entry in the debug subsystem, and select Properties to edit the registration entry. Do the following: a. Since you are debugging a web services application, type an asterisk (*) in the Terminal Name field for the LNIATA.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 373 b. Specify the registration type, system error number, and module name, as shown in Figure F-11, and click OK.

Figure C-14 Register by System error

3. Right-click the labwork registration entry, and select Register. 4. Start the web service application, and the debugger will start the desired location, as shown in Figure C-15 on page 375.

374 z/TPF Application Modernization using Standard and Open Middleware Figure C-15 Register by System Error debugger session

Registering by ctest

The ctest function is a special function on z/TPF that allows you to start the debugger wherever and whenever you need. For example, if you only wanted to start the debugger when a particular error path is taken. You can code the ctest function on that path, build and load your code, register for IBM_ctest and start your application. The debugger will start when the ctest function is called. This ctest feature can be useful for situations where other registration types fail to debug the desired ECB. For example, suppose the CHA0 module is kicked off 1,000 times a second and you want to debug the ECB that takes a particular error path which occurs infrequently. The ctest feature allows you to debug only the ECB you are interested in. For this example, we have modified cha0.c on line 13, as shown in Figure C-16 on page 376 to call ctest. The module CHA0 has been rebuilt and loadTPF is used to load this code in the loadset CTEST.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 375 Figure C-16 cha0.c modified to call ctest

To register by ctest: 1. In the Remote System view in the Remote system explorer, right-click the labwork registration entry, and select Cancel Registration. 2. Right-click the labwork debug registration entry in the debug subsystem, and select Properties to edit the registration entry: a. Do not specify the Terminal Name when registering by ctest. b. In the Select a registration type field, type IBM_CTEST as shown in Figure C-17. c. The ctest registration entries provide no other filtering mechanisms and as such, some limitations on use are imposed. Click OK.

Figure C-17 Register by ctest

376 z/TPF Application Modernization using Standard and Open Middleware 3. Right-click the labwork registration entry, and choose Register. 4. Start the web service application and the debugger will start at the line following the call to ctest, as shown in Figure C-18.

Figure C-18 Register by ctest debugger session

Registering by user-defined

The user-defined registration type is the most flexible form of registration because it is entirely up to the user how this registration type operates. The user-defined registration type is similar to ctest in that you must make a change to your code to implement it. However, performance sensitive macros are provided to allow the user defined registration code changes to persist in production code. As such, the user-defined registration entries can persist to provide powerful debugging points in your code. For example, if you have a separate system that talks to z/TPF by way of your own proprietary protocol. You can create a user-defined registration entry type to test for parameters specific to your protocol. An example and explanation of this form of registration is at:

http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztpfdf .doc_put.cur/gtpd3/d3tusrdefreg.html

The following procedure shows a quick example of the changes to use registration by user-defined in the web services book project.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 377 Modify the customDebugRegTypes.xml file to define the registration name and parameter types that the user will use at registration time: 1. From the TPF Toolkit menu, select File  Open File. Navigate to the %TPFSHARE%\Debug Registration\directory, for example, C:\Program Files\IBM\TPF Toolkit V40\Config\TPFSHARE\Debug Registration. 2. Select the customDebugRegTypes.xml file. This file defines the registration name and parameter types that the user will use at registration time. In Example C-1, lines 3-7 declare the new user defined registration type named CHA0 Web Services, which takes a single parameter that represents the Service Name.

Example C-1 customDebugRegTypes.xml 1 2 3 4 101 5 CHA0 Web Services 6 Service Name 7 8

3. Save the customDebugRegTypes.xml file and restart the TPF Toolkit. 4. You can now register the debugger for our user-defined registration type. In the Remote System view in the Remote system explorer, right-click the labwork registration entry, and select Cancel Registration. 5. Right-click the labwork debug registration entry in the debug subsystem and select Properties to edit the registration entry. Do the following: a. Do not specify the Terminal Name for registering by user-defined. b. Specify the registration type and service name, and then click OK, as shown in Figure C-19 on page 379.

378 z/TPF Application Modernization using Standard and Open Middleware Figure C-19 Register by user defined

6. Define a handler function, which compares the input registered by the user with the state of the program. The user-defined support provides a number of options for defining the handler function (four character program name, C/C++ function interface, assembler or C/C++ code interface, and so on). For simplicity, use the predefined cdbxud.c interface. Perform the following actions: a. In the book root directory, create a base/rt folder. b. Copy the cdbxud.c file into the base/rt directory. 7. Modify cdbxud.c, as shown in Example C-2 on page 380. The cdbxud.c file defines how the registration input is compared to the state of the program. If a satisfactory match is found, this function returns TRUE indicating that the debugger should start debugging the ECB. The struct tpf_UserDefRegTypStruct input parameter is provided for the application to provide specific details regarding the state of the application (for example, the value in a variable). Comparison tests can be made against anything including the content of the ECB, system heap, and other application and system state data. The struct itbpentry input is a pointer to the registration entry and provides this function with detail regarding what was registered. Lines 95-96 were added to compare the Service Name registered by the user to the service name found in the web service request (by way of the struct tpf_UserDefRegTypStruct input).

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 379 Example C-2 customDebugRegTypes.xml

79 80 unsigned int cdbxud_user_exit(struct tpf_UserDefRegTypStruct* UDRT_ptr, 81 struct itbpentry* tbu_entry) 82 { 83 unsigned rc = FALSE; /* set default return to false */ 84 85 if((UDRT_ptr == NULL) || (tbu_entry ==NULL)) 86 { 87 return rc; 88 } 89 90 switch(UDRT_ptr->udrt_id) 91 { 92 case 101: 93 { 94 // Checks for ID 101 95 if (strcmp((char *)UDRT_ptr->udrt_parm1, (char *)tbu_entry->itbp_udrt_parmValue[0]) == 0) 96 rc = TRUE; 97 // If passes checks, then set rc = TRUE 98 break; 99 } 100 101 default: 102 // incorrect id 103 break; 104 } 105 106 return rc; 107 }

8. Modify the build environment so that you can build the CDBX user exit. Since you are now building a TPF segment (CDBX), add the directory to the TPF Source in our maketpf.cfg file. Perform the following actions: a. To modify the MakeTPF configuration file, right-click the book project, and select Properties. b. In the project’s properties menu, select TPF Make Configuration. c. Modify the TPF Source location in the TPF System tab to include the build directory /home/jwisnie/book, as shown in Figure C-20 on page 381.

380 z/TPF Application Modernization using Standard and Open Middleware Figure C-20 maketpf.cfg updated for CDBX

9. Modify the maketpf build list to include CDBX by performing the following actions: a. Select TPF Make Build List. b. Click Add. c. Select Extract from existing control files, and choose scan for all known control files. d. From the tpf_app_base_ux.cntl file, select the module CDBX, and click Finish, as shown in Figure C-21 on page 382.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 381 Figure C-21 Selecting CDBX for the build list

10.Click OK to close the properties window. 11.Modify cha0.c to call the user-defined handler with your specified input. In Example C-3 on page 383: – Line 5 is included to give the program access to the user defined macros, function interface, and so on. – Line 22-23 and 29 add a call to the performance sensitive macro that tests if any 101 user defined registration entries exist on the system. If they do not, this block of code is skipped. – Line 24 declares the temporary user-defined input structure that will be passed to the code added in cdbxud.c. – Line 25 sets the passed-in input id to 101. – Line 26 sets the function that will handle doing the comparison between the state of the application and the registration entry as defined in cdbxud.c.

382 z/TPF Application Modernization using Standard and Open Middleware – Line 27 sets the first parameter to the name of the web service. – Line 28 calls the user defined registration handler to perform the comparison that has been defined.

Example C-3 cha0.c 1 #include /* TPF SOAP support */ 2 #include /* TPF XML APIs */ 3 #include /* tpfSoapMsgCtx structure */ 4 #include 5 #include 6 7 int CHA0 (tpfSoapMsgCtx *msgCtx) 8 { 9 xmlNodesArray *xptr = NULL; 10 XMLHandle inputHandle = msgCtx->request_handle.xml_handle; 11 12 //CTEST 13 ctest(NULL); 14 15 if(tpf_xml_positionAfterElementTagName(inputHandle,"Body") != 0) 16 return ErrorReplyNeeded; 17 18 xptr = tpf_xml_getNextElement(inputHandle, TYPE_TEXT); 19 if (xptr == NULL || xptr->returnCode != 0 || xptr->nodesArraySize == 0) 20 return ErrorReplyNeeded; 21 22 if(tpf_UserDefRegTypPerfCheck(101)) 23 { 24 struct tpf_UserDefRegTypStruct temp = {0}; 25 temp.udrt_id = 101; 26 temp.udrt_funcptr = (tpf_UserDefRegTypUserExit *) cdbxud_user_exit; 27 temp.udrt_parm1 = (void*)xptr->nodesArray[0].nodeName; 28 tpf_UserDefRegTypHandler(&temp); 29 } 30 31 if ((strcasecmp(xptr->nodesArray[0].nodeName, "getTime") == 0)) 32 { 33 if(getTimeAndBuildResponse(&msgCtx->response_handle.xml_handle) == 0) 34 return ErrorReplyNeeded; 35 msgCtx->response_handle.type = TPF_HDL_RESP; 36 return SendReply; 37 } 38 return ErrorReplyNeeded; 39 }

Notice in the customDebugRegTypes.xml, cdbxud.c and cha0.c files, each modification made used the ID number 101. These ID numbers are used to differentiate one user-defined registration type from another and ties all of these components together to implement a unique user-defined registration type. 12.The last change required is to the cha0.mak file. Since CHA0 will now need to make calls to CDBX, CDBX must be added to the LIBS declaration in the make file. Modify Line 12 as shown in Example C-4 on page 384 to add CDBX to the LIBS list.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 383 Example C-4 modification to cha0.mak 12 LIBS += CWSA CDBX

13.Build and load the project. Right-click the labwork registration entry, and select Register. 14.Start the web service application and the debugger will start at the line following the call to tpf_UserDefRegTypHandler(&temp), as shown in Figure C-22.

Figure C-22 Register by user defined debugger session

The z/TPF debugger interface

The z/TPF debugger is equipped with a variety of standard IBM debugger views and TPF specific views to aid in debugging a problem. The most commonly used IBM debugger views on the z/TPF Debugger are:  Editor view: Shows the C/C++ source code, assembler listing view for assembler code, or the disassembled code for C/C++ or assembler code. From this view, you can set breakpoints, perform execute actions, create variable monitors to view values, create memory monitors to view the contents of memory, and so on.

384 z/TPF Application Modernization using Standard and Open Middleware  Variables view: For C/C++, this view shows the values of variables that are currently in scope. For assembler, this view shows the register contents, expressions, and macro parameters for the next line to be executed. Values can be modified from this location.  Monitors view: Shows the variable, register, arithmetic expression, or global symbol that have been selected for monitoring by the user. Values can be modified from this location.  Registers view: Shows the values of the general, control, floating, and PSW registers.  Breakpoints view: Allows the user to set a variety of breakpoints: line, address, function, storage change, and load (when a shared object is entered) breakpoints. TPF SVC Macro and Macro group breakpoints are also supported.  Modules view: Allows the user to view all the shared object, objects, and functions that the debugger is currently aware of. You can also set breakpoints from this view.  Memory view: Allows users to view the contents of memory mapped as hexadecimal, ASCII, EBCDIC, XML (TPFXMLGEN can provide XML maps of structures and DSECTs), and so on.  Debug view: Provides execute-type functionality, such as execute (step, run, and so on). This view also allows you to see all of the threads in your application, select a thread to work with and more. This view shows you the stack frame for each thread and allows you to select a thread to see the variables associated with it. The stack frame display has been enhanced for TPF to show the optimization and debug information options used to build an object and the loadset that contains the module. The debug view also provides TPF specific functionality such as step debug and manipulating trace log.  Debug console: Provides a command interface to the debugger engine. z/TPF commands can pass through to the system message processor. The debugger engine also provides an array of commands to aid in the debugging of applications. A list of commands and extensive help is available by entering the help command. For example: – ECBTrace allows you to see the ECB trace you see in the z/TPF dumps. – ECBHEap provides statistics and counts of memory usage to aid in the detection of memory leaks and other problems. – GETCC, RELCC, ATTAC, DETAC, and FLIPC commands to issue these macros on behalf of the application. – TPFMEmfill to populate memory from file. – STEPDebug allows you to manage the step debug list. Step debug allows you to select the programs you want to debug and when you press the step into button in the debug view (with the step filter button active) the debugger will not stop in programs outside of your step debug list.

The z/TPF debugger also provides a variety of TPF specific views:  ECB view: Shows the contents of the ECB in a searchable tree, a hex dump similar to that seen in TPF dumps, and an EBCDIC translation. See Figure C-23 on page 386.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 385 Figure C-23 ECB View

 Data level and DECB view: Shows the contents of the ECB data level and DECBs, as shown in Figure C-24.

Figure C-24 Data Level View

 ECB Summary view: Shows a summary view of the current instruction being executed, operands for those instructions, register values, work areas, data levels and more, as shown in Figure C-25 on page 387.

386 z/TPF Application Modernization using Standard and Open Middleware Figure C-25 ECB Summary View

 SW00SR View: Shows the current state of the SW00SR block attached to your ECB. This view shows a great deal of information available from the ZUDFM command but in an XML based customizable view and even a full XML mapping of the SW00SR. The core block pane is particularly useful as it provides a mapping of the individual LRECs in a block as shown in Figure C-26 on page 388.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 387 Figure C-26 SW00SR View

 TPF Malloc view: Shows all allocated and changed and some free malloc blocks. This view is useful in traversing and searching the content of malloc blocks, where malloc blocks were allocated from, the sizes of malloc blocks, corrupted malloc blocks and so on.  DETAC view: Shows the value of all the blocks that have had a DETAC macro issued.  Record hold view: Shows all of the records currently held by the debugged ECB.  ALASC view: Shows the value of ALASC blocks.

z/TPF supplies the Non-Displayable ECB Storage (NDSPC) feature to allow you to prohibit users from seeing sensitive information. In all views of the debugger, any storage area marked as not displayable will not be shown to the user but the user is allowed to modify the content. z/TPF Debugger problem determination methodology example

A frequent use of the debugger is to determine the cause of a problem where the location of the problem in the code is unknown. The code coverage tool discussed in “The IBM TPF Toolkit and the z/TPF Code Coverage Tool” on page 414 can be used to see all of the code that is executed when a test case is run. The code coverage tool only shows if a function or a line of code has been executed. The code coverage tool does not show the path taken through the code although in some instances, the path through the code can be inferred.

z/TPF provides the trace log feature to determine the path through the code at the assembler entry point, C/C++ function and z/TPF macro level. Using the code coverage tool and trace log tool simultaneously can help you to learn a great deal about the path through the code and possibly the source of the problem. The following steps provide an example use of the trace log tool from the debugger: 1. Register the debugger to start debugging the application, as described in IBM TPF Toolkit and in “z/TPF debugger registration” on page 362. You might need to increase the number of how many trace logs can be active on the system at one time by issuing ZASER TRLOG-x where x is the number of trace logs that can be active.

388 z/TPF Application Modernization using Standard and Open Middleware 2. In the Debug view, click the Start Trace Log Collection icon, as shown in Figure C-27.

Figure C-27 Debug view with Start Trace Log Collection button

3. In the dialog that displays, specify the location where the trace log report is to be stored, as shown in Figure C-28. Click OK.

Figure C-28 Specify the Trace Log report location

The Debug Console view (available from the menu Window  Show View  Debug Console) shows the name and location of the trace log report file that will be generated, as shown in Figure C-29.

Figure C-29 Debug Console shows Trace Log report name and location

4. In the Breakpoints view (available from the menu Window  Show View  Breakpoints), ensure there are no breakpoints, or disable all breakpoints by clicking Skip All Breakpoints.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 389 5. In the Debug view, click Resume to run the application to completion. The TPF Console will display a message indicating that the trace log report has been generated, as shown in Figure C-30.

Figure C-30 TPF Console shows Trace Log report is generated

6. The TPF Toolkit provides an FTP File viewer for the z/TPF HFS file system. This viewer is available from the Remote System Explorer perspective as the Files subsystem under the TPF connection. The Files subsystem can be used to explore, view, and modify files on the z/TPF HFS file system including logs generated by Web Service requests. Use the Files subsystem to open the trace log report file. Switch to the Remote System Explorer perspective, and expand the Files subsystem to the location where the trace log report is located. Double-click the trace log .report file to open it, as shown in Figure C-31 on page 391.

390 z/TPF Application Modernization using Standard and Open Middleware Figure C-31 Open the Trace Log report

7. The TPF Toolkit FTPs the file to your workstation and then opens the Trace Log Report Parser with your report, as shown in Figure C-32 on page 392. The trace log report parser creates an indented view of the trace log entries which represent assembler entry points, functions and macros to graphically show the flow of the program and a variety of other information regarding the individual trace log entry. Click a given trace log entry to view additional information, such as the parameters passed (RSYSC is selected in Figure C-32 on page 392). Click the Source tab to see the trace log report content.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 391 Figure C-32 Trace Log Report Parser

8. You can also perform an analysis of the trace log report by clicking the Analyze Trace Log icon, as shown in Figure C-33.

Figure C-33 Analyze Trace Log button

The results of the analysis are shown in the Trace Log Analysis view. The Trace Log Analysis view shows a wide range of summarized detail regarding the trace log report including memory usage interface calls (Figure C-34 on page 393), File Address and File ids used by the application (Figure C-35 on page 393), and macro usage (Figure C-36 on page 393).

392 z/TPF Application Modernization using Standard and Open Middleware Figure C-34 Trace Log memory analysis results

Figure C-35 Trace Log file analysis results

Figure C-36 Trace Log macro analysis results

Based on the content of the trace log report (program flow, macro usage, function parameters, and so on), you can register the debugger to stop the application at a location where further investigation needs to occur.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 393 Using the z/TPF Debugger dump viewer to debug application dumps

The z/TPF debugger provides a variety of means to debug application dumps. One method is using the Register by System error feature to allow you to examine the state of the application at the time the dump is occurring in a live debugger session.

A similar approach is to use some kind of registration to start debugging the ECB that will dump and choose Resume in the Debug view. When the application dump occurs, the debugger will stop the application at the point of the dump allowing the user to investigate the state of the application.

A third approach is to use the z/TPF Debugger dump viewer. The z/TPF Debugger dump viewer is similar to using the z/TPF Debugger except that there is no live application. The z/TPF Debugger dump viewer has two phases: dump capturing and dump viewing.

The dump capturing phase occurs on z/TPF by issuing the zaser dumpon dbug command in the z/TPF console (see Figure C-37). Next, you cause the dump on your z/TPF system. The dump is the same as the Registration by System Error example in Figure C-13 on page 373. As such, we drive our /getTime web service to cause the dump. In addition to the dump appearing on the console, a message indicates that the dump control records have been added to the processor meaning that the dump has been captured (See Figure C-37). The ZDDMP command can be used on TPF to view and manage the captured dumps.

Figure C-37 Dump capture

Dump viewing is initiated from the TPF Toolkit Remote System Explorer perspective through the TPF Dump Viewer subsystem: 1. Switch to the Remote System Explorer perspective, and expand the TPF Dump Viewer subsystem in the Remote Systems View.

394 z/TPF Application Modernization using Standard and Open Middleware 2. Click a dump, to view details about that dump in the Properties view, as shown in Figure C-38.

Figure C-38 TPF Dump Viewer subsystem

3. The TPF Toolkit provides a more convenient table view of the dump information. Right-click the All Dumps filter, and choose Show in Table, as shown in Figure C-39 on page 396. The Remote System Details view opens with a table view of all of the dumps on the system, as shown in Figure C-40 on page 396.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 395 Figure C-39 TRF Dump Viewer opening table view

Figure C-40 TPF Dump Viewer table view

4. Additional details about a dump can be seen by right-clicking a dump and choosing details, as shown in Figure C-41 on page 397. A view opens that displays the additional details including the registers at the time of the dump, as shown in Figure C-42 on page 397.

396 z/TPF Application Modernization using Standard and Open Middleware Figure C-41 TRF Dump Viewer opening dump details

Figure C-42 TRF Dump Viewer dump details

5. To open the z/TPF debugger view of the dump, right-click the dump, and choose debug, as shown in Figure C-43 on page 398.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 397 Figure C-43 TRF Dump Viewer opening dump for debug

The debugger perspective opens with a view of the application at the time the dump occurred, as shown in Figure C-44 on page 399. As you can see, the dump viewer looks and feels just like a live debugger session with the exception that you cannot modify anything, create breakpoints, or execute the application. You can examine the contents of memory, variables (notice xptr is NULL, which is what caused the dump) registers.

398 z/TPF Application Modernization using Standard and Open Middleware Figure C-44 TRF Dump Viewer viewing dump

The debug console can be used to see the ECBTrace that is typically found in z/TPF dump and is similar to the trace log trace shown in Figure C-45.

Figure C-45 TRF Dump Viewer ECBTRace

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 399 The ECB Monitor subsystem

The ECB Monitor allows you to view a list of the ECBs that are running on the system and take a snapshot of a selected ECB. Viewing a snapshot of the selected ECB is identical to using the z/TPF Dump Viewer. This is useful for examining the state of a long running ECB: 1. To view the list of ECBs currently running on the system, open the Remote System Explorer perspective, expand the ECB Monitor Subsystem in the Remote Systems view, and expand the ECBs filter, as shown in Figure C-46.

Figure C-46 ECB Monitor subsystem

2. As shown in the Dump Viewer Subsystem in Figure C-39 on page 396, you can view the list of ECBs in a table by right-clicking the ECBs filter and choosing Show in Table. The result of this action is shown in Figure C-47 on page 401. This Remote System Details view of the list of ECBs allows you to see a variety of details about the ECBs that are currently executing which can also be seen in the Properties view when you select an individual ECB.

400 z/TPF Application Modernization using Standard and Open Middleware Figure C-47 ECB Monitor subsystem table view

3. A useful companion feature of z/TPF to the ECB monitor is the ZDECB TR command, which allows you to view the ECB Trace for a selected ECB to learn about what functions and macros have been called by an ECB recently, as shown in Figure C-48.

Figure C-48 ZECB TR

4. To take a snapshot of an ECB, right-click an ECB from the ECBs filter list, and choose Snapshot, as shown in Figure C-49 on page 402 (this can also be done from the table view). The snapshot is taken on z/TPF, and the debugger view of the snapshot automatically opens, as shown in Figure C-50 on page 403. Viewing a snapshot is just like

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 401 using the dump viewer in that most views work as normal except that you cannot edit any values, create breakpoints, or perform execute actions.

Figure C-49 ECB Monitor opening a snapshot

402 z/TPF Application Modernization using Standard and Open Middleware Figure C-50 ECB Monitor viewing a snapshot

5. If you want to save an ECB monitor session for viewing at a later time, open the Debug Console, and issue ECBSNapshot import, as shown in Figure C-51. You can now locate the ECB snapshot from the Dump Viewer subsystem, as shown in Figure C-52 on page 404 (notice that the dump number is listed as ISNPSHT). You might need to right-click the All Dumps filter, and choose Refresh.

Figure C-51 Importing an ECB Monitor snapshot

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 403 Figure C-52 Locating an ECB Monitor snapshot in the Dump Viewer subsystem

The ECB Launcher subsystem

The ECB Launcher subsystem provides a means to start applications on z/TPF. As such, this method of starting an application can function as a test method for your modules and as an alternative way of debugging your application: 1. To use the ECB Launcher, you first need to create an ECB Launcher filter: a. Open the Remote System Explorer perspective, and expand the ECB Launcher Subsystem in the Remote Systems view. b. Right-click the ECB Launcher Subsystem, choose New  New ECB Launcher, as shown in Figure C-53 on page 405.

404 z/TPF Application Modernization using Standard and Open Middleware Figure C-53 Creating a new ECB Launcher Filter

c. The new filter pop-up box opens, shown in Figure C-54. Specify the name of the program you want to start, the parameter that is to be passed to the new ECB in the ECB work area, the data level specification details, and content file path to be filled into the core block placed on the specified data level of the new ECB.

Figure C-54 New ECB Launcher Filter

d. Click Next. Enter a filter name, and click Finish. 2. Create the content file to populate the data level. This case is for illustration only because the CHA0 program does not receive input on a data level. Guidelines for transferring content files are at: http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztp fdf.doc_put.cur/gtpd3/d3tecblauncher.html. The TPF Toolkit Files subsystem handles the FTP details, providing you follow the naming convention outlined at that link: a. Switch to the TPF Toolkit perspective. b. Navigate to File  New  File.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 405 c. Enter the file name test.ebcdic. d. Select the book parent folder. e. Click Next. f. Select the Book Files filter, and click Finish. g. In the editor view of the file test.ebcdic, enter some test text, as shown in Figure C-55. Save the file.

Figure C-55 test.ebcdic file

3. Transfer the test.ebcdic file to the TPF file system in the directory specified as /tmp: a. From the TPF Toolkit perspective TPF Project navigator view, right-click the test.ebcdic file, and select Copy, as shown in Figure C-56.

Figure C-56 Copying the test.ebcdic file

b. Switch to the Remote System Explorer perspective in the Remote Systems view, and expand the Files subsystem. Right-click the /tmp directory, and select Paste, as shown in Figure C-57 on page 407. The TPF Toolkit FTPs the file to the TPF file system using the correct FTP transfer mode based upon the file suffix.

406 z/TPF Application Modernization using Standard and Open Middleware Figure C-57 Pasting the test.ebcdic file

4. Launch the ECB by right-clicking the cha0 filter and selecting Launch ECB, as shown in Figure C-58 on page 408.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 407 Figure C-58 Launch ECB

In this example, the z/TPF debugger was registered for the program CHA0. Figure C-59 on page 409 shows the test text in the ECB and in the data level.

408 z/TPF Application Modernization using Standard and Open Middleware Figure C-59 Debugging launched ECB

In this way, you can vary the input to your program and test a variety of scenarios without building a large amount of scaffolding or TPF Console access.

The IBM TPF Toolkit and the z/TPF Performance Analyzer

The z/TPF Performance Analyzer allows you to quickly see the execution intensive portions of your application. This allows you to focus your efforts on making those paths as efficient as possible to help your application perform more optimally.

Using the z/TPF Performance Analyzer is similar to using the z/TPF Debugger. The first step is to register to determine which ECB will have data collected. Next, run your application, and the ECB is traced to collect the execution information until the ECB exits, and the captured data is written to a trace file. Use the TPF Toolkit to download and analyze the trace data. After performing these steps, examine the results to understand where your application is spending the time: 1. Switch to the Remote System Explorer perspective, and expand the Performance Analyzer subsystem in the Remote System View. 2. Right-click the Performance Analyzer subsystem, and select New  New Session, as shown in Figure C-60 on page 410.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 409 Figure C-60 Creating a Performance Analyzer

3. In the Performance Analyzer filter: a. Set the TPF Terminal to an asterisk (*) for the Terminal Type LNIATA (the same as the debugger). b. Set the program mask to CHA0. c. Set the trace file name to /tmp/cha0.c, as shown in Figure C-61. d. Click Next.

Figure C-61 Performance Analyzer filter

410 z/TPF Application Modernization using Standard and Open Middleware e. Set the Session Label as cha0, and click Finish. f. Register the Performance Analyzer by right-clicking the cha0 session filter and selecting Register, as shown in Figure C-62.

Figure C-62 Registering the Performance Analyzer

4. Start the application by driving our /getTime web service. After the application runs to completion, the Performance Analyzer indicates on the z/TPF console that the trace file is created, as shown in Figure C-63 on page 412.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 411 Figure C-63 Performance Analyzer trace file created

5. Request the TPF Toolkit download, and analyze the trace file. Right-click the cha0 session filter, and select Download and Analyze Trace File, as shown in Figure C-64 on page 413.

412 z/TPF Application Modernization using Standard and Open Middleware Figure C-64 Download and Analyze Performance Analyzer trace file

6. The Performance Analyzer automatically opens to display the results of the trace collection. A variety of views of the data are displayed including a UML diagram of the trace execution, execution flow diagram, and a variety of tables of execution statistics including time spent in a call, the number of calls to a function and other information, as shown in Figure C-65 on page 414.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 413 Figure C-65 Performance Analyzer results

The IBM TPF Toolkit and the z/TPF Code Coverage Tool

The z/TPF Code Coverage Tool allows you to see how much of an application is being executed during testing. This is shown at the Module, Object, Function, Source File and Source Line level. The Code Coverage Tool can also be used during problem determination. For example, suppose an application is being debugged where the user is not familiar with the code in that application, the code coverage tool can show you what parts of the application are and are not executed by your test case.

The z/TPF code coverage tool is functionally different from the z/TPF debugger and performance analyzer in that you register a set of programs and data is collected regarding the execution of those programs regardless of how many ECBs execute those programs (even simultaneously): 1. To use the code coverage tool, you must first register your program.

414 z/TPF Application Modernization using Standard and Open Middleware Switch to the Remote System Explorer perspective, and expand the Code Coverage subsystem in the Remote System View. Right-click the Code Coverage subsystem, and select New  New Session, as shown in Figure C-66.

Figure C-66 Creating a new Code Coverage filter

2. In the Code coverage registration filter, the TPF Terminal functions as a filter of which ECBs will have their execution of the registered programs recorded. Perform the following actions: a. As with the z/TPF Debugger, set the TPF Terminal to an asterisk (*) for the Terminal Type LNIATA, since you are registering for a web service. b. For the Program Mask, enter cha0, and click Add. Three levels of analysis are available: Module level, Size Analysis, and Source Analysis: • The Module level analysis is available without performing any further analysis requests and tells you which modules have and have not been executed. • The Size Analysis tells you which objects and function have and have not been executed. • The Source Analysis tells you how much of your source file and which lines have been executed. The level of analysis you use is determined by which level of information is required for you to perform your task. For this example, the check box Automatically Perform Source Analysis is selected, as shown in Figure C-67 on page 416. Click Next.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 415 Figure C-67 New Code Coverage filter

3. Create a Session Label named cha0. Click Next twice. 4. This is a convenient location to set up the Source Lookup Path. Add the TPF Project Book to the list, as shown in Figure C-68 on page 417. Click Finish.

416 z/TPF Application Modernization using Standard and Open Middleware Figure C-68 Code Coverage setting the source lookup path

5. Register and start the code coverage collection phase. Right-click the cha0 filter, and select Start collection, as shown in Figure C-69 on page 418.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 417 Figure C-69 Code Coverage Start Collection

The TPF Toolkit will implicitly register the collection and then perform the start action. The Remote Console view shows the success, failure, and status of code coverage requests, as shown in Figure C-70.

Figure C-70 Code Coverage responses in the Remote Console

6. At this point, you need to drive the application. Start the /getTime web service. 7. The code coverage tool collects the execution statistics. To see the status of the collection, right-click the cha0 filter, and select Show Collection Status. The remote console will show the count of the modules that have been executed, as shown in Figure C-71.

Figure C-71 Code Coverage Collection Status

8. To see the results of the collection right-click the cha0 filter, and choose Save and Stop Collection. The remote console will show the result of the automatic source analysis, as shown in Figure C-72 on page 419.

418 z/TPF Application Modernization using Standard and Open Middleware Figure C-72 Code Coverage Save and Stop Auto analysis

9. Expand the cha0 filter to show the time stamp entries, as shown in Figure C-73.

Figure C-73 Code Coverage time stamp entry

A new time stamp entry is created for every Start Collection that occurs. A variety of options are available by right-clicking the time stamp entry. 10.Double-click the time stamp entry to view the results of the collection. The Code Coverage perspective is opened and the Code Coverage view shows the results of the collection in terms of the size and line percentages, as shown in Figure C-74 on page 420. A variety of

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 419 actions are available in the Code coverage view, including sorting (by name, size, percentage, and line percentage), filtering, report export and so on.

Figure C-74 Code Coverage results

11.To see which lines of the source file have been and have not been executed double-click a source file or function in the Code Coverage view. Since the getTime function did not have 100% line code, double-click the getTime function to open the gettime.cpp file, as shown in Figure C-75 on page 421. The bar to the right of the scroll bar shows a map of the lines that have and have not been executed. The lines shown in green have been executed, while the lines shown in red have not been executed. The preferences allow you to change the colors and how the source lines are highlighted. Buttons are also provided to allow you to skip from executed section to executed section or non-executed section to non-executed section.

420 z/TPF Application Modernization using Standard and Open Middleware Figure C-75 Code Coverage editor results

In this way, you can investigate how your testing does not cover all paths. In this example of the gettime.cpp file, the error paths are left untested by the execution of our web service. Drivers, for example, can be developed to drive these paths to achieve 100% source line coverage. It might not be possible to drive all paths with drivers. For example, the PCRS error paths might not be easy to drive with a driver. However, the z/TPF debugger can be simultaneously used to force the application down paths that are not taken during test cases. This can be done by registering the debugger as previously described by program name CHA0. In Figure C-76 on page 422, the debugger was used to drive the error cases (using Jump to Location, variable manipulation or by other means) in a separate code coverage run. Notice that the there are now two time stamp entries under the cha0 code coverage filter, the PCRS error path is now tested, and the line percentage on the getTime function is 83% as opposed to the 77% previously seen in Figure C-74 on page 420.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 421 Figure C-76 Debugger manipulated Code Coverage results

12.The TPF Toolkit provides a code coverage comparison feature to aid in seeing the differences between code coverage runs. To view a comparison, click (while holding the control key depressed) all of the sessions you want to compare, and then right-click an entry, and choose Compare Results as shown in Figure C-77.

Figure C-77 Starting a Code Coverage comparison

422 z/TPF Application Modernization using Standard and Open Middleware 13.The comparison editor is opened showing the difference between the selected runs, as shown in Figure C-78. Like the code coverage view, you can sort, filter, and perform a variety of other actions. The delta button allows you to see deltas between the runs or the actual percentages. The list of sessions at the bottom of the view allows you to change which session is the base line.

Figure C-78 Code Coverage comparison

14.The Code Coverage comparison feature also allows you to compare the collected results for a source file. Right-click the gettime.cpp file, and select the Compare Source Analysis Results option, as shown in Figure C-79 on page 424. In the pop-up window, select the sessions and location of the source files, and click OK.

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 423 Figure C-79 Opening Code Coverage editor comparison

A comparison editor view is opened showing a side by side comparison of the file and the code coverage results for each run as shown in Figure C-80 on page 425. The comparison editor is allows you to point to two different files in case code changes have occurred between runs.

424 z/TPF Application Modernization using Standard and Open Middleware Figure C-80 150 Code Coverage editor comparison

Appendix C. The IBM TPF Toolkit and z/TPF Debugger Tools 425 426 z/TPF Application Modernization using Standard and Open Middleware D

Appendix D. TPF Toolkit wizards for WebSphere Operational Decision Management and Business Events

This appendix contains information about using the wizards referenced in Chapter 10, “Using WebSphere Operational Decision Management to apply business rules” on page 173 and Chapter 11, “Business event processing” on page 191.

© Copyright IBM Corp. 2013. All rights reserved. 427 The IBM TPF Toolkit Common Deployment Wizard

The z/TPF system uses a mechanism called common deployment to make deployment descriptors available for use. The TPF Toolkit provides a wizard to help you create the deployment descriptors for use by WebSphere Operational Decision Management and Business Events. The following examples are based on the example used in Chapter 10, “Using WebSphere Operational Decision Management to apply business rules” on page 173.

To create the deployment descriptors for use by WebSphere Operational Decision Management and Business Events: 1. To use the common deployment wizard, switch to the TPF Toolkit perspective, right-click a project, and choose New  TPF Data Model Definition, as shown in Figure D-1.

Figure D-1 New TRF Data Model Definition

2. Specify the file name and the parent folder where the XML file will be saved, as shown in Figure D-2 on page 429. Click Next.

428 z/TPF Application Modernization using Standard and Open Middleware Figure D-2 TRF Data Model Definition Name

3. Select the filter to use, and click Next. 4. Specify the name of the data model, such as miniloan, as shown in Figure D-3 on page 430.

Appendix D. TPF Toolkit wizards for WebSphere Operational Decision Management and Business Events 429 Figure D-3 TRF Data Model Definition Name

5. Add the object definitions to the data model: a. Click New. b. Specify the C name, the Java name, and optionally a comment, as shown in Figure D-4 on page 431.

430 z/TPF Application Modernization using Standard and Open Middleware Figure D-4 New object definition

c. Click Add to add members for the object. d. Specify the name, type, repeat, and length fields for the object member, as shown in Figure D-5. Click OK.

Figure D-5 New object member

6. Repeat step 5 to create all object members, as shown in Figure D-6 on page 432.

Appendix D. TPF Toolkit wizards for WebSphere Operational Decision Management and Business Events 431 Figure D-6 Complete object definition

7. Click OK. 8. Create any additional objects and object members, as shown in Figure D-7 on page 433.

432 z/TPF Application Modernization using Standard and Open Middleware Figure D-7 Complete Object Model

9. Click Finish. The XML file is created and automatically opens in the TPF Toolkit XML editor, as shown in Figure D-8.

Figure D-8 Data Definition in the XML Editor

Appendix D. TPF Toolkit wizards for WebSphere Operational Decision Management and Business Events 433 IBM TPF Toolkit WebSphere Operational Decision Management Wizards

The TPF Toolkit provides a set of wizards to help you create the endpoint group descriptor file and the RuleApp descriptor. The following examples are based on the example used in Chapter 10, “Using WebSphere Operational Decision Management to apply business rules” on page 173.

Endpoint group descriptor file wizards

To create a new endpoint group descriptor: 1. To use the endpoint group descriptor file wizard, switch to the TPF Toolkit perspective, right-click a project, and choose New  Business Rules...  WODM Endpoint Definition, as shown in Figure D-9.

Figure D-9 New Endpoint Definition

2. In the New Endpoint Definition window, perform the following actions, specify the file name and the parent folder where the xml file will be saved, as shown in Figure D-10 on page 435. Click Next.

434 z/TPF Application Modernization using Standard and Open Middleware Figure D-10 Name the endpoint definition

3. Select the filter to use, and click Next. 4. Specify the Group Name, Queue Threshold, and Queue Max Depth, as shown in Figure D-11 on page 436.

Appendix D. TPF Toolkit wizards for WebSphere Operational Decision Management and Business Events 435 Figure D-11 Endpoint details

5. Click Add to add endpoints: a. Specify the Destination, Start socket, Max socket and TPF Processor IDs, as shown in Figure D-12. b. Click OK.

Figure D-12 Endpoint definition

436 z/TPF Application Modernization using Standard and Open Middleware 6. Click Finish. The XML file is created and automatically opens in the TPF Toolkit XML editor, as shown in Figure D-13.

Figure D-13 Endpoint definition in the XML Editor

RuleApp descriptor file wizard

To use the RuleApp descriptor file wizard: 1. Switch to the TPF Toolkit perspective, right-click a project, and choose New  Business Rules  WODM Rules Application Definition, as shown in Figure D-14.

Figure D-14 New RuleApp definition

2. Specify the File Name and the Parent Folder where the xml file will be saved, as shown in Figure D-15 on page 438. Click Next.

Appendix D. TPF Toolkit wizards for WebSphere Operational Decision Management and Business Events 437 Figure D-15 Name the RuleApp definition

3. Select the filter to use, and click Next. 4. Specify the Endpoints and Application Name, as shown in Figure D-16 on page 439.

438 z/TPF Application Modernization using Standard and Open Middleware Figure D-16 Rule Application Details panel

5. Click Add to add rule sets. 6. Specify the rule set name, as shown in Figure D-17 on page 440.

Appendix D. TPF Toolkit wizards for WebSphere Operational Decision Management and Business Events 439 Figure D-17 Rule set definition

7. Click Add to add input parameters, and then specify the parameter name and parameter type, as shown in Figure D-18. Click OK.

Figure D-18 Rule set parameter definition

8. Repeat the previous step to add all input and output parameters. 9. Click OK, and then click Finish. The XML file is created and automatically opens in the TPF Toolkit XML editor, as shown in Figure D-19 on page 441.

440 z/TPF Application Modernization using Standard and Open Middleware Figure D-19 RuleApp definition in the XML Editor

IBM TPF Toolkit business events wizards

The TPF Toolkit provides a set of wizards to help you create the dispatch adapter descriptor file and the event descriptor. The following examples are based upon the business event example used in Chapter 11, “Business event processing” on page 191. 1. To use the dispatch adapter descriptor file wizard, switch to the TPF Toolkit perspective, right-click a project, and choose New  Business Events  Business Events Dispatch Adapter, as shown in Figure D-20.

Figure D-20 New Business Event Dispatch Adapter

2. Specify the File Name and the Parent Folder where the xml file will be saved, as shown in Figure D-21 on page 442. Click Next.

Appendix D. TPF Toolkit wizards for WebSphere Operational Decision Management and Business Events 441 Figure D-21 Name Business Event Dispatch Adapter

3. Select the filter to use, and click Next. 4. Specify the Name, Transport Type, and Format, as shown in Figure D-22 on page 443, and click Finish.

442 z/TPF Application Modernization using Standard and Open Middleware Figure D-22 Business Event Dispatch Adapter Details

The XML file is created and automatically opens in the TPF Toolkit XML editor, as shown in Figure D-23 on page 444.

Appendix D. TPF Toolkit wizards for WebSphere Operational Decision Management and Business Events 443 Figure D-23 Business Event Dispatch Adapter in the XML Editor

5. To use the event descriptor file wizard, switch to the TPF Toolkit perspective, right-click a project, and choose New  Business Rules  Business Event Specification, as shown in Figure D-24.

Figure D-24 New Business Event Definition

6. Specify the File Name and the Parent Folder where the xml file will be saved, as shown in Figure D-25 on page 445, and click Next.

444 z/TPF Application Modernization using Standard and Open Middleware Figure D-25 Name Business Event Definition

7. Select the filter to use, and click Next. 8. Specify the Name, Dispatch Queue Name, Dispatch Adapters and the Object Definition, as shown in Figure D-26 on page 446, and click Finish.

Appendix D. TPF Toolkit wizards for WebSphere Operational Decision Management and Business Events 445 Figure D-26 Business Event Details

The XML file is created and automatically opens in the TPF Toolkit XML editor, as shown in Figure D-27 on page 447.

446 z/TPF Application Modernization using Standard and Open Middleware Figure D-27 Business Event Definition in the XML Editor

Appendix D. TPF Toolkit wizards for WebSphere Operational Decision Management and Business Events 447 448 z/TPF Application Modernization using Standard and Open Middleware E

Appendix E. XML file for SDO examples

Example E-1 contains the CREDIT.xml file used for the SDO examples in Chapter 7, “Accessing z/TPFDF databases through SDO” on page 127.

Example E-1 CREDIT.xml file 1 1 0 0 0 23 16 Up 7 No Yes 1 39 1

© Copyright IBM Corp. 2013. All rights reserved. 449 NoOrg 8 No Yes 1 40 4 NoOrg 9 No Yes 1 3 8 13 8 0 0 0 3 20 NoOrg 2 No Yes 1

450 z/TPF Application Modernization using Standard and Open Middleware 23 9 NoOrg 3 No Yes 1 32 10 NoOrg 4 No Yes 4 72 1 NoOrg 5 No Yes 1 73 1 NoOrg 6 Yes Yes 1 76 4 NoOrg 7 No Yes 1 0 0

Appendix E. XML file for SDO examples 451 3 20 Up 2 No Yes 1 23 5 Down 4 No Yes 1 28 9 NoOrg 7 No Yes 1 37 5 NoOrg 5 No Yes 1 44 4 NoOrg 6 No Yes 1 48 4

452 z/TPF Application Modernization using Standard and Open Middleware Up 3 No Yes 1 0 0 0 4 4 NoOrg 2 No Yes 1 8 4 NoOrg 3 No Yes 1 0 0 4 4 NoOrg

Appendix E. XML file for SDO examples 453 2 No Yes 1 8 1 NoOrg 3 No Yes 1 0 0 4 4 NoOrg 2 No Yes 1 8 1 NoOrg 3 No Yes 1 0 0 4 4

454 z/TPF Application Modernization using Standard and Open Middleware NoOrg 2 No Yes 1 8 1 NoOrg 3 No Yes 1 0 0 4 4 NoOrg 2 No Yes 1 8 8 NoOrg 3 No Yes 1

Appendix E. XML file for SDO examples 455 456 z/TPF Application Modernization using Standard and Open Middleware F

Appendix F. Workarounds

This appendix provides some programming workarounds for problems encountered during the course of the project.

© Copyright IBM Corp. 2013. All rights reserved. 457 Invalid heap address

This section describes an issue with an invalid heap address and the resolution for the problem.

Problem The z/TPF system generates an OPR-I0006F1 system error out of the SOAP handler program CSOA. Example F-1 shows a console example.

Example F-1 Example of an OPR-I0006F1 from CSOA CSMP0097I 15.22.00 CPU-B SS-BSS SSU-HPN IS-01 CPSE0152E 15.22.00 IS-0001 SS-BSS SSU-HPN SE-NODUMP OPR-I0006F1 C00071B TRC-CSOA CTIS OBJ-cfree 00000312 LOADSET-BASE ECB HEAP ADDRESS IN R1 IS NOT VALID+

This occurs because the SOAP handler tries to release the SOAP input message that it thinks is in a heap block. However, the SOAP input message was passed to the SOAP handler by the communications binding, and as such is not the SOAP handler’s to release. The assumption that the SOAP message is in a heap storage block by itself is wrong.

Fix A proper solution to this problem is to update the SOAP handler to no longer try to release the SOAP input message that it thinks is in a heap storage block. However, because this is outside the scope of this book, we created a workaround in the communications binding, as shown in the right half of Figure F-1.

soapStart soapOnHeap

HTTP Header

SOAP SOAP Header Header

SOAP SOAP Body Body

Original input Heap copy of message SOAP input message

Figure F-1 SOAP input message before and after the workaround

The source code in Figure F-1 shows the fix in the communications binding source code. The original code was in the first line that is now commented out. The workaround consists of the next two lines, in which a new heap storage block is allocated, the SOAP input message is copied, and the address of the newly acquired heap storage block is then used as the SOAP input message. See Example F-2 on page 459.

458 z/TPF Application Modernization using Standard and Open Middleware Example F-2 Copying the SOAP input message to its own heap storage block // input.XMLptr = soapStart; char* soapOnHeap = (char*)malloc(input.msgLength+1); strcpy(soapOnHeap, soapStart); input.XMLptr = soapOnHeap;

Compile errors from c_node.h

This section addresses compile errors from the c_node.h file.

Problem The errors in Example F-3 are received during compile from c_node.h.

Example F-3 Compile errors from c_node.h /ztpf/cur/base/include/tpf/c_node.h:71: error: declaration of 'nodesArray* xmlNodesArray::nodesArray' /ztpf/cur/base/include/tpf/c_node.h:68: error: changes meaning of 'nodesArray' from 'typedef struct nodesArray nodesArray'

The problem is caused by the code shown in Example F-4.

Example F-4 Node array definitions in c_node.h typedef struct nodesArray { char *nodeName; int numChildren; CONTENT_TYPE content_type; int numContents; int flags; #define ATTRIBUTE_CONTENT 0x00000001 char *namespacePrefix; char *namespaceUri; char *nodeValueStr; void *expansion; /* reserved for IBM */ NODE_VALUE_DATA_TYPE nodeValueDataType; } nodesArray; typedef struct xml NodesArray { nodesArray *nodesArray; int nodesArraySize; int returnCode; } xmlNodesArray;

Fix Example F-5 shows the fix for this problem.

Example F-5 Temporary fix in node array definitions in c_node.h typedef struct xmlNodesArray { nodesArray *nodesArrayX; int nodesArraySize; int returnCode; } xmlNodesArray;

Appendix F. Workarounds 459 MakeTPF error MTPF0006E during build

This section addresses an error in the MakeTPF utility during build.

Problem Unresolved references during program build can occur accompanied by the makeTPF messages shown in Example F-6.

Example F-6 MakeTPF error MTPF0006E MTPF2101I: Errors or Warnings issued during build.

MTPF1111W: Error File: /home/grift/book/base/rt/cso4.err

maketpf.rules_errchk:67: *** MTPF0006E: The list of libraries in the makefile "cxap" specifies at least one library in mixed or lower case. The libraries must be specified in all upper case to ensure consistency with the APP targets. Stop.

TPF Toolkit return code = 0

When a shared object is built that contains external references, MakeTPF must be informed about the libraries required to resolve these external references. This is done using the LIBS variable in a shared object’s makefile. The TPF documentation tells which library is required for which function. Figure F-2 shows an example of this.

The LIBS variable value that is suggested by the documentation is wrong however, because MakeTPF requires that all library names (cxap in this example) are in all uppercase characters.

z/TPF PUT 02 tpf_xml_appendElement-Append a new element after the parent element

This function creates an element node with any associated content nodes, namespace node, appends the new element after its parent element.

Last updated

Added for PUT02.

Format

LIBS := cxap #include

int tpf_xml_appendElement (XMLHandle api_handle, char *parentName, char *etagName, char *etagValue, char *etagNamespacePrefix, char *etagNamespaceURI,

Figure F-2 Sample C API documentation

Fix Update the makefile of the shared object that you are building using all uppercase characters for anything that is assigned to the LIBS variable. Figure F-3 on page 461 shows an example.

460 z/TPF Application Modernization using Standard and Open Middleware cso4.mak Line 10 Column 1 Insert 1 change ----+----1----+----2----+----3----+----4----+----5----+----6- APP := CSO4 APP_EXPORT := ENTRY APP_ENTRY := CSO4 maketpf_env := system maketpf_env += base_rt C_SRC := cso4.c CXX_SRC := gettime.cpp

LIBS := CXAP # Uppercase characters include maketpf.rules

Figure F-3 Updated makefile example

Appendix F. Workarounds 461 462 z/TPF Application Modernization using Standard and Open Middleware Related publications

The publications listed in this section are considered particularly suitable for a more detailed discussion of the topics covered in this book.

IBM Redbooks

The following IBM Redbooks publications provide additional information about the topic in this document. Note that some publications referenced in this list might be available in softcopy only:  IBM z/Transaction Processing Facility: Overview and Enterprise Integration using SOA, REDP-4611  Transaction Processing: Past, Present, and Future, REDP-4854  WebSphere Transaction Cluster Facility Case Study and Analysis: Pushing the Database Performance Capabilities of a Distributed System, REDP-4910  WebSphere Transaction Cluster Facility, REDP-4817  Modernization with IBM WebSphere eXtended Transaction Runtime, TIPS0921  Modernizing Applications with WebSphere eXtended Transaction Runtime, REDP-4818

You can search for, view, download or order these documents and other Redbooks, Redpapers, Web Docs, draft and additional materials, at the following website: ibm.com/redbooks

Online resources

These websites are also relevant as further information sources:  IBM TPF Product Information Center http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.tpf.doc/ ic-homepage.html  IBM z/Transaction Processing Facility Libraries http://www.ibm.com/tpf/pubs/tpfpubs.htm  Service Data Objects (SDO) Access to z/TPFDF User’s Guide http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom .ibm.ztpf-ztpfdf.doc_put.cur%2Fbdfs7mst.toc.html  The Postfix Home Page http://www.postfix.org/  The Cyrus project http://cyrusimap.web.cmu.edu/  IBM WebSphere Operational Decision Management Version 8.0 Information Center http://pic.dhe.ibm.com/infocenter/dmanager/v8r0/topic/com.ibm.help.doc/infocent er_homepage.html

© Copyright IBM Corp. 2013. All rights reserved. 463  z/TPF C/C++ Language Support User's Guide: http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom .ibm.ztpf-ztpfdf.doc_put.cur%2Fgtpc2mst.toc.html  z/TPF Operations http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom .ibm.ztpf-ztpfdf.doc_put.cur%2Fgtpo1mst.toc.html  z/TPF System Generation http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztp fdf.doc_put.cur/gtps4mst.toc.html  z/TPFDF System Generation http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztp fdf.doc_put.cur/gtps4mst.toc.html  z/TPF Transmission Control Protocol/Internet Protocol (TCP/IP) http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztp fdf.doc_put.cur/gtpc1mst.toc.html  z/TPF Application Programming http://publib.boulder.ibm.com/infocenter/tpfhelp/current/topic/com.ibm.ztpf-ztp fdf.doc_put.cur/gtpa2mst.toc.html

Help from IBM

IBM Support and downloads ibm.com/support

IBM Global Services ibm.com/services

464 z/TPF Application Modernization using Standard and Open Middleware z/TPF Application Modernization using Standard and Open Middleware z/TPF Application Modernization using Standard and Open Middleware

z/TPF Application Modernization using Standard and Open Middleware

(0.5” spine) 0.475”<->0.873” 250 <-> 459 pages z/TPF Application Modernization using Standard and Open Middleware z/TPF Application Modernization using Standard and Open Middleware

z/TPF Application Modernization using Standard and Open Middleware

Back cover ® z/TPF Application Modernization using Standard and Open Middleware ®

Understanding In a world where product lifespans are often measured in months, the IBM Transaction Processing Facility has remained relevant for more INTERNATIONAL extreme transaction TECHNICAL rates and availability than four decades by continuing to process high volumes of transactions quickly and reliably. As the title of this book suggests, the SUPPORT in SOA z/TPF system uses open, standard interfaces to create services. ORGANIZATION Integration of new applications with existing z/TPF functions is a key Refacing z/TPF factor in extending application capabilities. The ability for service data applications objects (SDO) to access the z/TPF Database Facility (z/TPFDF) provides a framework for data application program development that includes Leveraging z/TPF in an architecture and application programming interfaces (APIs). SDO BUILDING TECHNICAL access to z/TPFDF provides remote client applications with access to an open systems INFORMATION BASED ON z/TPF traditional data. PRACTICAL EXPERIENCE environment This book provides an introduction to z/TPF and the technologies critical to SOA. z/TPF is positioned as a provider or consumer in an SOA IBM Redbooks are developed by supporting SOAP processing, communication bindings, and by the IBM International Extensible Markup Language (XML). An example is used to show how Technical Support Organization. Experts from z/TPF can be used both as a Web service provider and as a consumer. IBM, Customers and Partners A second example shows how to use WebSphere Operational Decision from around the world create Management to apply business rules. A third example shows how timely technical information business event processing can be incorporated in z/TPF applications. based on realistic scenarios. An example is also used to discuss security aspects, including z/TPF Specific recommendations XML encryption and the z/TPF WS-Security wrapper. The main part of are provided to help you the book concludes with a discussion of z/TPF in an open systems implement IT solutions more environment, including examples of lightweight implementations to fit effectively in your z/TPF, such as the HTTP server for the z/TPF system. The appendixes environment. include information and examples using TPF Toolkit, sample code, and workarounds (with yes, more examples). For more information: ibm.com/redbooks

SG24-8124-00 ISBN 0738438200