{khapre.org}
Nothing More : Nothing Less : Just Perfect : Online Since 1997
Friday, April 17, 2009

CICS Web Services Assistant for Windows

As we know, web services are reached to mainframes also. The best way to enable any CICS program (except assembler) via web services is to use Rational Application Developer for System Z. I would say that is the best and also the most expensive way to create WS on mainframe. You can use CICS Web Services Assistant to do that. Usually the license of RAD4Z is very expensive, so if you only need to create webservices artifacts, use CICS WS assistant.

You need to first download the CICS WS A from here, importantly check the documentation that it comes with. Apart from that you need to download Java Record I/O for OS/390. You can both these from your CICS/USS installation on mainframe. Later I found out that, DFHLWS2WS batch program invokes the java classes one after the other to create Web services. Using JRIO, you can read the VSAM datasets (KSDS), system catalogs, I am still not sure why do we need this for running the Windows assistant. I would suggest reading this overview for more details.

Using the assistant you can create both approaches

  1. Top down approach - WSDL to CICS program - WS2LS
  2. Bottom up approach - CICS program to WSDL - LS2WS

First things first

  1. I created a utility class which will read from a properties file with the string/constant values that are needed.
  2. I downloaded the copybook for the CICS program that needs to be enabled via Web services.
  3. You may want to separate the input and output as two different copybooks.
  4. Read thru the sample code for more documentation.
Initialize
  1:     // Decide your defaults.
  2:     // Here is the target program name
  3:     public final String PARAM_PROGRAM_NAME = Utility.getProperty("PARAM_PROGRAM_NAME", "FIRSTCICS");
  4:     // Is the target program looking for perticular container name in
  5:     // default channel? Default container name is "DFHWS-DATA"
  6:     public final String PARAM_CONTAINER_NAME = Utility.getProperty("PARAM_CONTAINER_NAME", "DFHWS-DATA");
  7:     /*
  8:          * You need to provide Cobol mapping level that is used in copybooks.
  9:          * This is important because some mappings are not supported by certain
 10:          * version of CICS WS.
 11:          */
 12:     public final String PARAM_MAPPING_LEVEL = Utility.getProperty("PARAM_MAPPING_LEVEL", "2.0");
 13:     /*
 14:          * If you have preference for namespaces for the WSDL, you can specify
 15:          * that here. Usually, the auto generated Java/C# classes has reveresed
 16:          * package/namespace hierarchy. Like when you say com.test.myCo the
 17:          * namespace in Java will look like myCo.test.com. This is the reason I
 18:          * wrote it reversed. This helps if you plan to import the generated
 19:          * WSDL into JAX-WS or Axis based tool. Specify namespaces for request
 20:          * and response.
 21:          * 
 22:          */
 23:     public String PARAM_REQUEST_NAMESPACE_MF = Utility.getProperty("PARAM_REQUEST_NAMESPACE_MF", "myCo.test.com");
 24:     public String PARAM_RESPONSE_NAMESPACE_MF = Utility.getProperty("PARAM_RESPONSE_NAMESPACE_MF", "myCo.test.com");
 25:     // You must specify the programmming language for target program.
 26:     // 0 = COBOL.
 27:     public final int PARAM_LANGUAGE = Integer.parseInt(Utility.getProperty("PARAM_LANGUAGE", "0"));
 28:     // What is the target program need COMMAREA or CHANNELS/Containers.
 29:     public final int PARAM_PROGRAM_INTERFACE = Integer.parseInt(Utility.getProperty("PARAM_PROGRAM_INTERFACE", "1"));
 30:     // Name of default channel?
 31:     public final String PARAM_CHANNEL_NAME = Utility.getProperty("PARAM_CHANNEL_NAME", "CHANNEL");
 32:     // Define codepage for the PDS that will be used as input or output.
 33:     // I used default as IBM-037
 34:     public final String PARAM_PDS_CODEPAGE = Utility.getProperty("PARAM_PDS_CODEPAGE", "IBM-037");
 35:   
 36:     public String PARAM_SERVICE_INTERFACE = "";
 37:     //Location of generated WSDL (LS2WS) or WSDL to be used to generate (WS2LS)
 38:     public String WSDL_LOCATION = "";
 39:     
 40:     //Name of the PDS file names on local machine.
 41:     public String PARAM_REQUEST_CBMEMBER_MF = "";
 42:     public String PARAM_RESPONSE_CBMEMBER_MF = "";
 43:     /*
 44:      * This is the name of interface that wsbind file will use to create a web service.
 45:      * This will also be used at http://server:port/PARAM_SERVICE_INTERFACE
 46:      */ 
 47:     public String PARAM_INTERFACE_ID = "";
 48:     public String PARAM_DIRECTORY_PDS_LIB = "";
 49:     public String PARAM_DIRECTORY_ARTIFACTS_WSDL = "";
 50:     public String PARAM_DIRECTORY_ARTIFACTS_WSBIND = "";
 51:     public String PARAM_DIRECTORY_ARTIFACTS_LOG = "";
 52:     public final String PARAM_EXTENTION_WSBIND = Utility.getProperty("PARAM_EXTENTION_WSBIND", ".wsbind");
 53:     public final String PARAM_EXTENTION_WSDL = Utility.getProperty("PARAM_EXTENTION_WSDL", ".wsdl");
 54:     public final String PARAM_EXTENTION_LOG = Utility.getProperty("PARAM_EXTENTION_LOG", ".log");

Setup the parameters:

  1: private IAssistantParameters setParams(String type) {
  2: 	IAssistantParameters params = Factory.createAssistantParameters();
  3: 	/*
  4:          * You can create both LS2WS and WS2LS from CICS WS Assistant. Both use
  5:          * different parameters. this program is written to handle both
  6:          * scenarios.
  7:          */
  8: 	if (type.equals("LS2WS")) {
  9: 	    //Copybook to web services approach
 10: 	    params.setParamLANG(PARAM_LANGUAGE);
 11: 	    params.setParamPDSCP(PARAM_PDS_CODEPAGE);
 12: 	    params.setParamMAPPING_LEVEL(PARAM_MAPPING_LEVEL);
 13: 	    params.setParamPGMNAME(PARAM_PROGRAM_NAME);
 14: 	    params.setParamREQMEM(PARAM_REQUEST_CBMEMBER_MF);
 15: 	    params.setParamRESPMEM(PARAM_RESPONSE_CBMEMBER_MF);
 16: 	    params.setParamPGMINT(PARAM_PROGRAM_INTERFACE);
 17: 	    params.setParamPGMINT(PARAM_CHANNEL_NAME);
 18: 	    params.setParamCONTID(PARAM_CONTAINER_NAME);
 19: 	    params.setParamPDSLIB(PARAM_DIRECTORY_PDS_LIB);
 20: 	    params.setParamURI(PARAM_INTERFACE_ID);
 21: 	    params.setParamREQUEST_NAMESPACE(PARAM_REQUEST_NAMESPACE_MF);
 22: 	    params.setParamRESPONSE_NAMESPACE(PARAM_RESPONSE_NAMESPACE_MF);
 23: 	    params.setParamWSBIND(PARAM_DIRECTORY_ARTIFACTS_WSBIND + PARAM_INTERFACE_ID + PARAM_EXTENTION_WSBIND);
 24: 	    params.setParamLOGFILE(PARAM_DIRECTORY_ARTIFACTS_LOG + PARAM_INTERFACE_ID + PARAM_EXTENTION_LOG);
 25: 	    params.setParamWSDL(WSDL_LOCATION);
 26: 	} else {
 27: 	    //WSDL to Cobol copybook/program approach
 28: 	    params.setParamLANG(PARAM_LANGUAGE);
 29: 	    params.setParamPDSCP(PARAM_PDS_CODEPAGE);
 30: 	    params.setParamMAPPING_LEVEL(PARAM_MAPPING_LEVEL);
 31: 	    params.setParamPGMNAME(PARAM_PROGRAM_NAME);
 32: 	    params.setParamREQMEM(PARAM_REQUEST_CBMEMBER_MF);
 33: 	    params.setParamRESPMEM(PARAM_RESPONSE_CBMEMBER_MF);
 34: 	    params.setParamPGMINT(PARAM_PROGRAM_INTERFACE);
 35: 	    params.setParamPGMINT(PARAM_CHANNEL_NAME);
 36: 	    params.setParamCONTID(PARAM_CONTAINER_NAME);
 37: 	    params.setParamPDSLIB(PARAM_DIRECTORY_PDS_LIB);
 38: 	    params.setParamURI(PARAM_INTERFACE_ID);
 39: 	    params.setParamCHAR_VARYING("NO");
 40: 	    /*
 41: 	     * No need to specify namespaces here, because they come from specified WSDL.
 42: 	     */
 43: 	    // params.setParamREQUEST_NAMESPACE(PARAM_REQUEST_NAMESPACE_MF);
 44: 	    // params.setParamRESPONSE_NAMESPACE(PARAM_RESPONSE_NAMESPACE_MF);
 45: 	    params.setParamWSBIND(PARAM_DIRECTORY_ARTIFACTS_WSBIND + PARAM_INTERFACE_ID + PARAM_EXTENTION_WSBIND);
 46: 	    params.setParamLOGFILE(PARAM_DIRECTORY_ARTIFACTS_LOG + PARAM_INTERFACE_ID + PARAM_EXTENTION_LOG);
 47: 	    params.setParamWSDL(WSDL_LOCATION);
 48: 	}
 49: 	return params;
 50:     }

Part I: Create Copybook to Web service (LS2WS)


  1:  public String CreateWSArtifactsLS2WS() {
  2: 	try {
  3: 	    /*
  4: 	     * Create the paths where you want your WS artifacts will be crated.
  5: 	     */
  6: 	    PARAM_REQUEST_NAMESPACE_MF = this.PARAM_SERVICE_INTERFACE + "." + PARAM_REQUEST_NAMESPACE_MF;
  7: 	    PARAM_RESPONSE_NAMESPACE_MF = this.PARAM_SERVICE_INTERFACE + "." + PARAM_RESPONSE_NAMESPACE_MF;
  8: 	    WSDL_LOCATION = PARAM_DIRECTORY_ARTIFACTS_WSDL + PARAM_INTERFACE_ID + PARAM_EXTENTION_WSDL;
  9: 	    
 10: 	    /*
 11: 	     * Setup parameters
 12: 	     */
 13: 	    IAssistantParameters params = this.setParams("LS2WS");
 14: 	    /*
 15: 	     * Create assistant
 16: 	     */
 17: 	    ICICSWebServicesAssistant cwsa = Factory.createCICSWebServicesAssistant();
 18: 	    /*
 19: 	     * Make the run
 20: 	     */
 21: 	    IAssistantResponse ar = cwsa.DFHLS2WS(params);
 22: 	    /*
 23: 	     * Check the output.
 24: 	     */
 25: 	    int retCode = ar.getReturnCode();
 26: 	    String retMessages = "";
 27: 	    /*
 28: 	     * There are list of messages.
 29: 	     */
 30: 	    String[] msgs = ar.getAllMessages();
 31: 	    for (int i = 0; i < msgs.length; i++) {
 32: 		retMessages += msgs[i] + "\n";
 33: 		Utility.PrintLine(msgs[i]);
 34: 	    }
 35: 	    Utility.PrintLine("DFHLS2WS:AssistantResponse.getReturnCode():" + retCode);
 36: 	    if (retCode == IAssistantResponse.RC_ERROR) {
 37: 		Utility.PrintLine("Error while creating the WSDL\n" + retMessages);
 38: 		throw new Exception("WSDL Creation Error : " + retMessages);
 39: 	    }
 40: 	} catch (Exception e) {
 41: 	    Utility.PrintError(e);
 42: 	}
 43: 	
 44: 	return WSDL_LOCATION;
 45:     }
 46: 

 

Part II: Create Web service to Cobol(WS2LS)

  1:     public String CreateWSArtifactsWS2LS() {
  2: 	try {
  3: 	    /*
  4: 	     * Create the paths where you want your WS artifacts will be crated.
  5: 	     */
  6: 	    PARAM_REQUEST_NAMESPACE_MF = this.PARAM_SERVICE_INTERFACE + "." + PARAM_REQUEST_NAMESPACE_MF;
  7: 	    PARAM_RESPONSE_NAMESPACE_MF = this.PARAM_SERVICE_INTERFACE + "." + PARAM_RESPONSE_NAMESPACE_MF;
  8: 	    WSDL_LOCATION = PARAM_DIRECTORY_ARTIFACTS_WSDL + PARAM_INTERFACE_ID + PARAM_EXTENTION_WSDL;
  9: 	    /*
 10: 	     * You have to provide the names of the PDS which it will generate the the Copybooks.
 11: 	     */
 12: 	    PARAM_REQUEST_CBMEMBER_MF = "WBSXI";
 13: 	    PARAM_RESPONSE_CBMEMBER_MF = "WBSXO";
 14: 	    IAssistantParameters params = this.setParams("WS2LS");
 15: 	    ICICSWebServicesAssistant cwsa = Factory.createCICSWebServicesAssistant();
 16: 	    IAssistantResponse ar = cwsa.DFHWS2LS(params);
 17: 	    int retCode = ar.getReturnCode();
 18: 	    String retMessages = "";
 19: 	    String[] msgs = ar.getAllMessages();
 20: 	    for (int i = 0; i < msgs.length; i++) {
 21: 		retMessages += msgs[i] + "\n";
 22: 		Utility.PrintLine(msgs[i]);
 23: 	    }
 24: 	    Utility.PrintLine("DFHLS2WS:AssistantResponse.getReturnCode():" + retCode);
 25: 	    if (retCode == IAssistantResponse.RC_ERROR) {
 26: 		Utility.PrintLine("Error while creating the WSDL\n" + retMessages);
 27: 		throw new Exception("WSDL Creation Error : " + retMessages);
 28: 	    }
 29: 	} catch (Exception e) {
 30: 	    Utility.PrintError(e);
 31: 	}
 32: 	return WSDL_LOCATION;
 33:     }

Glue it togather:

  1: String WSDL_LOCATION ="";
  2: CICSCreateWSDL createWSDL = new CICSCreateWSDL();
  3: 
  4: createWSDL.PARAM_INTERFACE_ID="GetCustomerAddress";
  5: createWSDL.PARAM_REQUEST_CBMEMBER_MF = "CUSTADDR.cpy";
  6: createWSDL.PARAM_RESPONSE_CBMEMBER_MF = "CUSTADDR.cpy";
  7: createWSDL.PARAM_DIRECTORY_PDS_LIB = Utility.BASE_ARTIFACT_FOLDER + "1.Interfaces\\";
  8: createWSDL.PARAM_DIRECTORY_ARTIFACTS_WSDL = Utility.BASE_ARTIFACT_FOLDER + "2.WSDLs\\";
  9: createWSDL.PARAM_DIRECTORY_ARTIFACTS_WSBIND = Utility.BASE_ARTIFACT_FOLDER +  "3.WSBINDs\\";
 10: createWSDL.PARAM_DIRECTORY_ARTIFACTS_LOG = Utility.BASE_ARTIFACT_FOLDER + "4.LOGs\\";
 11: createWSDL.PARAM_SERVICE_INTERFACE=PARAM_NAMESPACE;
 12: WSDL_LOCATION=	createWSDL.CreateWSArtifactsLS2WS();

Vishal KHAPRE | Mi Marathi Manus@3:02 PM < (0) @ Add

. . ° º o O o º ° . .
Monday, April 06, 2009

Read my book review from Amazon : Visual Basic.NET and XML

Few years back, somebody approached me to review a new emerging book on Visual Basic .Net and XML. The book is focused only on XML related processing in VB.Net.

Recently I had been searching for pages related to my website and I can see my review is sold on Amazon along with the book for $5.95.

Feels good to see...

Citation Details
Title: Visual Basic.NET and XML: Harness the Power of XML in VB.NET Applications.(Book Reviews)
Author: Vishal Khapre
Publication: Technical Communication (Refereed)
Date: February 1, 2004
Publisher: Society for Technical Communication
Volume: 51 Issue: 1 Page: 123(2)


Vishal KHAPRE | Mi Marathi Manus@8:26 AM < (0) @ Add

. . ° º o O o º ° . .
Wednesday, January 21, 2009

Add Command prompt to explorer context menu

Its been always a long process to reach to desired folder using "cd" command on Command Prompt. It was easier to have a context menu for any folder in Windows Explorer as "Start command here". I had been using it for such a long time, so don't know who told me how to do this, but recently a friend asked me so thought it is easier to post a blog and point him to the post.

  1. Open Windows explorer

    image 

  2. Go to Tools menu -> Folder Options -> File Types. You can probably reach this place via control panel also.

    image
  3. Select "Folder" remember not to select "File Folder" and click on "Advanced". I already have created "command" as my context menu so you will see that here too.

    image
  4. Click New and put Action as "Start command here" and Application used as absolute path to cmd.exe usually it is in your system32 directory.

    image
  5. Click "Ok" and then "Close" to get back to Windows Explorer.
  6. Right click on any folder in Windows Explorer to see the context menu added.

Good luck!!

Labels:


Vishal KHAPRE | Mi Marathi Manus@10:45 PM < (2) @ Add
Saturday, February 07, 2009 7:06:00 AM
Blogger Chirs says....

I am learning good things from this site.

send flowers

Tuesday, March 17, 2009 10:24:00 AM
Blogger vismit says....

more tricks at
http://www.xtreamefun.com/upload


. . ° º o O o º ° . .
Wednesday, August 20, 2008

JAX-WS and Custom SOAP Header

Recently, during my transition to JAX-WS, a work in hand made me use Custom Soap headers in design in a JAX-WS implementation. Pertaining same, my recent conversations with friend, we need a quick sample how to use custom headers with JAX-WS.

JAX-WS by Sun’s specifications support custom soap headers. It is as easier as .Net or webMethods. It supports the WSDL with SOAP header information also.

https://jax-ws.dev.java.net/jax-ws-ea3/docs/annotations.html

As per W3C, “The Representation header block is designed to allow applications to carry a representation of a Web resource in a SOAP message”. 

Ref:http://www.w3.org/TR/soap12-rep/

It is not limited or only used by system processing, applications can use it for several reasons which include the access restriction, avoiding payload browse, and also overhead (accessing headers is faster than body). So it is perfectly allowed to use SOAP custom headers, philosophy being soap:body should contain only the payload, all routing headers should be used as soap:headers.

Here is how you do it.

Change your soapbinding annotation to DOCUMENT, by default it is DOCUMENT but I made it explicit because it was giving some error.

@WebService(name = "GoodbyeWorldWS", 
targetNamespace="http://webservice_producer/goodbyeworld") @SOAPBinding(style = SOAPBinding.Style.DOCUMENT)

Add new @WebParam with header=true. You can also set the Mode to INOUT so that header value is returned to consumer too. You can access the headers via the WebParam name specified in the name attribute.

@WebMethod
public String sayGoodbye(
   @WebParam(name="message") String message,
   /*Add header element */
   @WebParam(name="header",mode=Mode.IN, header=true) String headerElement) 
{
System.out.println("SOAP HEADER VALUE" + headerElement); return ".Goodbye."; }

Here is how the WSDL looks like, it has the soap:header added.

<input> 
    <soap:body parts="sayGoodbye" use="literal" /> 
  <soap:header message="tns:GoodbyeWorldWS_sayGoodbye" part="header" use="literal" />
</input>

Here is the C# code to invoke it.

GoodbyeWorldWSService.GoodbyeWorldWSService ws = 
      new ConsoleApplication2.GoodbyeWorldWSService.GoodbyeWorldWSService();
            
GoodbyeWorldWSService.sayGoodbye input = 
     new ConsoleApplication2.GoodbyeWorldWSService.sayGoodbye();
            
input.message = "JAX WS support Body";
ws.header = new ConsoleApplication2.GoodbyeWorldWSService.@string();
ws.header.Text = new String[] { "JAX WS Supports Headers" };
            
GoodbyeWorldWSService.sayGoodbyeResponse output = ws.sayGoodbye(input);
Console.WriteLine(output.@return);

Here is how the SOAP message  looks like in server log

22:07:21,187 INFO [STDOUT]
[
<soap:Envelope xmlns:soap=http://schemas.xmlsoap.org/soap/envelope/
   xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
   xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
  <header xmlns="http://webservice_producer/goodbyeworld">
      JAX WS Supports Headers
  </header>
</soap:Header>
<soap:Body>
  <sayGoodbye xmlns="http://webservice_producer/goodbyeworld">
     <message xmlns="">JAX WS support Body</message>
   </sayGoodbye>
</soap:Body>
</soap:Envelope>
].


Vishal KHAPRE | Mi Marathi Manus@10:00 PM < (0) @ Add

. . ° º o O o º ° . .
Friday, July 04, 2008

Windows Live Writer

My laptop changed, so wanted to get back to the setup I had before, been through enough trouble to get Windows Live Writer to be installed on my machine. You wish it is a MS baby, single installable, double click and boom!! Everything is installed completely.

 

Otherwise Windows Live Installer uses Windows Installer, Automatic Updates and all underlying component. Not sure why?

It uses so many components and piece in background to make it work. Basically, the installable can install any or a lot more components on your machine than required. Found garmahis.com (Thanks to Michael Garmahis) where I could get a standalone installable. There is another one if you like ... here.


Vishal KHAPRE | Mi Marathi Manus@11:46 PM < (0) @ Add

. . ° º o O o º ° . .