Guru: move a web service to another web server
Feb. 19, 2018
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 can use IWS to manually create it on each server, but this would be time consuming and error prone. Simply missing a parameter when creating the service can lead to unexpected results.
Or you can automate the process. This would ensure that the attributes of the service are transferred from one server to another. Although I will not go into the process of creating web services, as there are already many articles that deal with this topic, I will show a series of programs that I have created to automatically copy a service from a server. to another.
IBM provides shell scripts that can be used to perform various functions in IWS. These functions include starting and stopping a server, producing a list of all servers, and getting and setting properties for services. I use a lot 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 about the scenario being discussed. I created an RPG program called TEST_WS and compiled it into development and test libraries on IBM i. The program accepts an input parameter called a message and returns the message with its own message. Not a very useful program and not the best program name, but it will suffice for what I am demonstrating.
I also created development and test web servers through IWS. For starters, I am using IWS to deploy the RPG program from the development library to the development web server. Once this is done, I use the automated process to deploy the RPG program from the test library to the test web server. Using the automated process, I make sure that the test service deploys with the same attributes as the development service.
Looking at the development server in Figure 1. You can see that 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 to use the automated tool to deploy these services on the test server (Figure 2).
I have created a user interface (Figure 3) that will collect 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 facilitate the demonstration, I chose to create a user interface.
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 deploy. The right side of the user interface defines tables in which the process stores various information about web servers and services. These tables are crucial to the process and allow it to retrieve the attributes of the service deployed on the development server and apply them to the service being deployed on the test server.
Press F6 to validate what has been entered on the user interface. Part of the validation is making sure the source and destination servers exist, whether the service exists on the source server, and whether the RPG program object exists, among other things. If any errors are found, an error message appears, indicating what is wrong. To show part of the error handling, I intentionally entered a source server that does not exist (Figure 4).
I correct the error and press F6 again. This time, all values are correct and the service is ready to be deployed (Figure 5).
Note that there is now a pre-populated field that displays the list of libraries to use in the deployment. Where does this come from? Using the IBM-supplied shell scripts I mentioned earlier, I extract information from the service deployed on the development server (in this case, the list of libraries). The UI allows the library to be changed for deployment to the test server and this is perfect as I have promoted the RPG program in my test library on the IBM i. I edit the list of libraries (Figure 6) to point to the test RPG program and hit enter. Of course, I should have pressed F6 again to validate the UI, but I’m just going to ignore it this time. It is important to note that libraries must be separated by a colon.
I press Enter and after a few seconds a message pops up on the UI saying the process has been submitted (Figure 7).
I look at my test server and see that the service has been deployed! (See Figure 8.)
I am following the same steps to deploy the REST service on the test server (Figure 9).
After pressing Enter, I check the test server again and see that the REST service has been deployed (Figure 10).
Now that you’ve seen the process in action, you’re probably curious to see how it happened. There are a number of shell scripts in IFS (Figure 11) that allow interaction with web servers and services. I use a lot of scripts in 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 the relevant pieces of this code. While I am not showing all of the code used in the process, please rest assured that all of the code is included with this article.
Remember when I pressed the F6 key to validate the values on the UI? Well, a lot of things happened when I did that. A series of routines performed various checks to ensure that the information entered into the user interface 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;
While each of these is important, I’ll focus on the BuildPropertiesTable routine to show how to run a shell script from RPG and what properties of the service are returned. This subroutine runs the getWebServiceProperties.sh shell script. This script provides details of the web service to move 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 run the script passing the development server and service names. Since I want the properties to be available for my program, I write the properties to a file using the Rfile command. The -wQ switch indicates that I am writing to a file and using qualified syntax for filenames. After the Rfile command, I tell Qshell which library and filename to direct the output to. Figure 12 shows the contents of the web service properties file after running the script.
The properties of the service deployed on the development server that I am using include:
- List of libraries
- Type of service
- PCML file path
- Runtime user ID
- Transport metadata
- Transport headers
- Service name
- Server name (this will be the destination UI server)
Once I have the properties I need, I can easily change them, if needed, in order to move the service to another server. There are other properties that I don’t use, but which might be useful for other web services related projects.
When I pressed the Enter key on the UI, a series of RPG programs were launched, each running shell scripts to perform various tasks. The table below provides a list of RPG programs and shell scripts that deploy the service.
|RPG program||Shell script||Goal|
|WS_PROMOTE||installWebService.sh||Install the service on a web server|
|WS_SETPROP||setWebServiceProperties.sh||Define the properties of a service|
|WS_STOP||stopWebService.sh||Stop a service|
|WS_START||startWebService.sh||Start a service|
The next set of code will complete the task. The first step in 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 collected earlier, set the properties on the service that was just deployed, as shown 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;
Then 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, isn’t it? 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 gain more and more importance in the industry. By providing tools to build and deploy web services, project completion time is reduced and risk is mitigated by eliminating human error. If you would like to see more articles showing other ways to use shell scripts, let me know.