Guru: Moving A Web Service To Another Web Server
February 19, 2018 Mike Larsen
IBM Integrated Web Services (IWS) makes it easy to create web services and deploy them to a web server. If you need to deploy the same service to multiple web servers, you could use IWS to manually create it on each server, but it would be time-consuming and error-prone. Simply missing a setting when creating the service can lead to unexpected results.
Or you could automate the process. That would ensure the attributes of the service carry forward from server to server. While I won’t get into the web service creation process, as there are already many articles that address that topic, I will show a series of programs I built to automatically copy a service from one server to another.
IBM provides shell scripts that can be used to perform various functions within IWS. These functions include starting and stopping a server, producing a listing of all servers, and getting and setting properties for services. I use many of these scripts to copy a service from server to server.
This story contains code, which you can download here.
Before I get into the process, I want to give more information on the scenario being discussed. I created an RPG program called TEST_WS and compiled it to both development and test libraries on IBM i. The program accepts an input parameter called message and returns the message along with a message of its own. Not a very useful program and not the best program name, but it will suffice for what I’m demonstrating.
I also created development and test web servers via IWS. To start, I use IWS to deploy the RPG program from the development library to the development web server. Once this is complete, I use the automated process to deploy the RPG program from the test library to the test web server. By using the automated process, I ensure the test service deploys with the same attributes as the development service.
Looking at the development server in Figure 1. You can see I have two services deployed: TEST_WS_SOAP and TEST_WS_REST. I used the same RPG program to create each service to show that the automated process can handle both REST and SOAP services.
The goal is use the automated tool to deploy these services to the test server (Figure 2).
I created a UI (Figure 3) that will gather information about the service that needs to be deployed. In a production scenario, most (if not all) of these values would be stored in a table. However, to make it easier to demonstrate, I chose to create a UI.
On the left side of the UI, I provide the name of the IBM i, the source and destination web servers, the RPG object and library, and the name of the service to be deployed. The right side of the UI defines tables where the process stores various information about the web servers and services. These tables are crucial to the process and are what allow it to retrieve attributes about the service deployed to the development server and apply them to the service being deployed to the test server.
Pressing F6 validates what was entered on the UI. Some of the validation includes ensuring the source and destination servers exist, whether the service exists on the source server, and if the RPG program object exists, amongst other things. If any errors are detected, an error message appears, showing what’s wrong. To show some of the error processing, I intentionally keyed in a source server that doesn’t exist (Figure 4).
I correct the error and press F6 again. This time, all the values are correct and the service is ready to be deployed (Figure 5).
Notice there is now a pre-populated field that shows the library list to be used in the deployment. Where did that come from? Using the IBM provided shell scripts I mentioned earlier, I extract information from the service that’s deployed to the development server (in this case, the library list). The UI allows for changes to the library for deployment to the test server and that’s perfect because I promoted the RPG program to my test library on the IBM i. I change the library list (Figure 6) to point to the test RPG program, and I press Enter. Of course, I should have pressed F6 again to validate the UI, but I’ll just skip it this time. It’s important to note that libraries need to be separated by a colon.
I press Enter and after a few seconds, a message appears on the UI indicating the process has been submitted (Figure 7).
I look at my test server and see the service has been deployed! (See Figure 8.)
I follow the same steps to deploy the REST service to the Test server (Figure 9).
After I press Enter, I check the Test server again and see the REST service has been deployed (Figure 10).
Now that you’ve seen the process in action, you’re probably curious to see how this happened. There are a number of shell scripts in the IFS (Figure 11) that enable interaction with web servers and services. I use many of the scripts in the RPG programs and run them using Qshell.
The program behind the UI orchestrates the entire process, including running the shell scripts, so I’ll show relevant pieces of that code. Although I don’t show all the code used in the process, rest assured all code is provided with this article.
Remember when I pressed the F6 key to validate the values on the UI? Well, a lot happened when I did that. A series of subroutines performed various checks to make sure the information keyed into the UI was valid, as shown in the following piece of code:
//-------------------------------------------------------- // PerformValidation subroutine //-------------------------------------------------------- Begsr PerformValidation; Exsr BuildPropertiesTable; Exsr ValidateServer; Exsr ValidateService; Exsr ValidatePropFileLib; Exsr ValidatePgmObjLib; Exsr ValidateSvrFileLib; Exsr ValidateSvcFileLib; Exsr ValidateIbmi; Endsr;
Although each of these are important, I’ll focus on the BuildPropertiesTable routine to show how to execute a shell script from RPG and what properties about the service are returned. This subroutine executes the shell script getWebServiceProperties.sh. This script provides details about the web service to be moved from one server to another.
//-------------------------------------------------------- // GetProperties subroutine //-------------------------------------------------------- Begsr GetProperties; CmdStr = *Blanks; // Run a shell script to get a Web Services properties. CmdStr = 'Qsh Cmd(''/QIBM/ProdData/OS/WebServices/bin/+ getWebServiceProperties.sh -server ' + %Trim(ServerName) + ' -service ' + %Trim(Service) + ' | Rfile -wQ ' + %Trim(FileLibrary) + '/' + %Trim(File) + ''')'; Callp Run(Cmdstr:%Size(CmdStr)); Endsr;
I execute the script passing the development server and service names. Since I want the properties available to my program, I write the properties to a file using the Rfile command. The -wQ switch indicates I’m writing to a file and using qualified syntax for file names. Following the Rfile command, I tell Qshell the library and file name into which to direct the output. Figure 12 shows the content of the web service properties file after executing the script.
The properties from the service deployed to the development server I use include:
- Library list
- Service type
- PCML file path
- Runtime user ID
- Transport metadata
- Transport headers
- Service name
- Server name (this will be the destination server from the UI)
Once I have the properties I need, I can easily modify them, if necessary, in order to move the service to another server. There are other properties that I’m not using, but could be useful for other projects related to web services.
When I pressed the Enter key on the UI, a series of RPG programs was initiated, each of which ran shell scripts to perform various tasks. The chart below shows a listing of the RPG programs and shell scripts that deploy the service.
|RPG program||Shell script||Purpose|
|WS_PROMOTE||installWebService.sh||Install the service to a web server|
|WS_SETPROP||setWebServiceProperties.sh||Set properties of a service|
|WS_STOP||stopWebService.sh||Stop a service|
|WS_START||startWebService.sh||Start a service|
The next series of code will complete the task. The first step of the process installs the service on the server.
Begsr PromoteService; CmdStr = *Blanks; // Run a shell script to install a Web Service CmdStr = 'Qsh Cmd(''/QIBM/ProdData/OS/WebServices/bin/+ installWebService.sh' + ' -server ' + %Trim(ServerName) + ' -service ' + %Trim(Service) + ' -programObject ' + %Trim(NewObjectPath) + ' -pcml ' + %Trim(PcmlFilePath) + ' -userid ' + %Trim(RuntimeUid) + ' -serviceType ' + %Trim(ServiceType) + ' -libraryList ' + %Trim(LibListToUse) + ''')'; Callp Run(Cmdstr:%Size(CmdStr)); Endsr;
Then, using the properties that were gathered earlier, set the properties on the service that was just deployed, as demonstrated here:
Begsr SetProperties; CmdStr = *Blanks; // Run a shell script to set properties on a Web Service CmdStr = 'Qsh Cmd(''/QIBM/ProdData/OS/WebServices/bin/+ setWebServiceProperties.sh' + ' -server ' + %Trim(ServerName) + ' -service ' + %Trim(Service) + ' -transportMetadata ' + %Trim(TransMetaData) + ' -transportHeaders ' + %Trim(TransHeaders) + ' -libraryList ' + %Trim(LibListToUse) + ''')'; Callp Run(Cmdstr:%Size(CmdStr)); Endsr;
Next, we stop the service:
Begsr StopService; CmdStr = *Blanks; // Run a shell script to stop a Web Service CmdStr = 'Qsh Cmd(''/QIBM/ProdData/OS/WebServices/bin/+ stopWebService.sh -server ' + %Trim(ServerName) + ' -service ' + %Trim(Service) + ''')'; Callp Run(Cmdstr:%Size(CmdStr)); Endsr;
Finally, we start the service:
Begsr StartService; CmdStr = *Blanks; // Run a shell script to start a Web Service CmdStr = 'Qsh Cmd(''/QIBM/ProdData/OS/WebServices/bin/+ startWebService.sh -server ' + %Trim(ServerName) + ' -service ' + %Trim(Service) + ''')'; Callp Run(Cmdstr:%Size(CmdStr)); Endsr;
Pretty cool, right? With just a few RPG programs and a handful of Shell scripts, I created a very functional web service management system.
Web services continue to become more and more important in the industry. By providing tools to create and deploy web services, the time to complete projects is reduced and risk is mitigated by the elimination of human error. If you’d like to see more articles showing other ways to use the Shell scripts, let me know.