Mining Web Services from a Legacy Application

 

Michael Oara

CEO, System Renewal, Inc.

 

 

The complexity of existing legacy applications makes quite difficult the task of identifying potential services for exposure in a SOA architecture. The difficulty varies based on the “layering” degree of the application. It is simpler for a well-layered application and more difficult for a non-layered application. It is simpler when programs use simple communication areas and more difficult when these areas are complex and consist of a large number of unused fields.

To expose a service, we must solve a number of problems:

·         Which programs are suitable for exposure?

·         Which programs contain the desired functionality?

·         What is the best level of granularity for the service exposure?

·         How to proceed when the desired functionality is intermixed with other functionality?

·         How to select the essential fields in the communication areas?

·         How to perform minimum intrusive changes to the application code, if such changes are needed for service exposure?

 

To solve these problems, we will use a number of specialized tools:

·         RMW Analyst will be used to parse the application sources and perform some initial understanding of the application

·         RMW SOA Analyzer will be used to discover potential services and define them

·         RMW Architect will be used to perform certain remedies on some programs so that they can be exposed as services

·         RMW Business Rule Manager will be used to discover validation rules relevant in an SOA enablement project

 

 

We will start with a discussion of the application layers, which is relevant for all subsequent points.

 

Application layers

 

Building an application with distinct layers is not a new concept. Even for old applications, architects have realized the benefits of placing the artifacts in well-defined layers. In a perfect-layered application one may distinguish the following layers

·         Layer 0 – User interface layer

Consists of screens which would be visible to the users

·         Layer 1 – Client layer

Consists of all programs that communicate directly with the screens.

Such programs would contain all the logic for capturing user’s requests, validating the input data, invoking the appropriate “service” programs from the lower layers and formatting the output that responds to the user’s request.

In this layer the execution moves to the lower layers via CALL or LINK operations and moves to other programs of the same layer via exclusive transfer of control, which in CICS could be accomplished by XCTL or RETURN TRANID statements.

In fact this layer may contain two type of programs:

o   “Client programs” that receive and send screens

o   “Transitional programs” that make navigation decisions

Transitional programs are sometimes used as traffic dispatchers. A program CPROG1 may receive a screen SCREEN1 and pass exclusive control to a program TPROG that analyzes the user request in order to decide which is the next screen to be presented to the user. It may be that TPROG will pass exclusive control back to CPROG1, which in turn will present the same SCREE1, with additional data that satisfies the request. It may also be that TPROG decides to transfer control to a program CPROG2, which in turn will present the screen SCREEN2.

The benefit of transitional programs is that they encapsulate the navigation logic. The client programs are confined to screen logic, while the transitional programs are confined to navigation logic.

·         Layer 2 – Service layer

Consists of all programs that satisfy a request, without any screen communication or regard to screen logic. Most programs in this layer interact in one way or another with application’s persistent data, but they may also perform certain pure logic related to computations or formatting. As an example, one “service” program may retrieve an invoice information based on an invoice number or it may simply compute the number of business days between two dates.

Service layer programs may be also classified based on their position in the calling hierarchy, resulting in three categories:

·         Layer 2A: Frontier programs, which are called directly by a Layer 1 program

·         Layer 2B: Indirect data access programs, which access data through some other called service programs or perform computations or formatting

·         Layer 2C: Direct data access programs, which access the persistent data from VSAM files or from databases.

 

·         Layer 3 – Persistent data

 

A classification of assets in a perfect-layered application is illustrated in the following hierarchy, as displayed by the Relativity’s SOA Analyzer tool:

Figure 1 – Legacy artifacts classification

 

In the case of a well-layered application, programs in each layer will have well designated business functions:

·         Client programs contain screen logic

·         Transitional programs contain navigation logic

·         Frontier programs contain business level data manipulation logic

·         Sub-frontier programs contain both business logic and technical data manipulation logic

The layering of the application is of immediate importance in an SOA enablement project. As we try to expose services that execute discrete requests, we can look at the client and transitional programs only for the purpose of identifying the location of potential services. In themselves, they do not offer services, as they do not execute any server type logic. Their functionality will be replaced in an SOA architecture with new technical artifacts that are “client facing”, implemented practically on an application or web server.

The service programs are the ones offering “service” capability and we can create web services based on their functionality.

 

Understanding an artifact’s place in the architecture

The simple classification of application artifacts does not give us a full understanding about how they are used. The SOA Analyzer supplies a more detailed picture when we ask for ‘vertical’ and ‘horizontal’ slices that show the context in which the artifact is used. Such “slices’ are very useful, as a complete diagram of the application may be exceedingly complex and hard to understand.

A vertical slice shows “usages”, that is how an artifact is used (for instance via a call or a file access), and how itself uses other artifacts. A ‘horizontal’ slice shows how the control passes between artifacts, usually through exclusive change of control or through screen navigation.

We can obtain the vertical and horizontal slices by a right click on an artifact in the Classification pane, followed by the selection of the ‘Show  vertical slice’ or ‘Show horizontal slice’ menus. Let us look at certain examples.

 

Figure 2 – A vertical slice for a CICS transaction

As a CICS transaction appears in the highest layer of the architecture, it does not appear as used by another artifact. In Figure 2, we can see that transaction RWCD is started by program RWCP1198, which calles RWCP1200, RWCP116 and RWCP1202. In turn, the last two programs access certain files in read mode (R), Read/Update (RU) or Read/Update/Insert mode.

 

Figure 3 – A vertical slice for a screen

Figure 3 shows a vertical slice for the screen RWCS80A, which is sent and received by the program RWCP110 and sent only by program RWCP1132.

 

Figure 4 - Vertical slice for a program

 

Figure 4 shows a vertical slice for program RWCP1136. We can immediately notice that this happens to be a ‘frontier’ program, according to the classification that we have described earlier, as it does not access screens and is called directly by programs that access screens. This special position in the architecture would make it a good candidate for exposure as a web service.

 

Figure 5 - Vertical slice for a file

From Figure 5 we can discover a fact that is relevant in the effort to extract services: all operations against the selected file (seen at the bottom, in a white box) are performed via a single program, RWCP1120. This makes the program ideal as a service, as it certainly contains all the logic needed to access the file from outside.

While vertical slices through the application’s architecture show usage scenarios, horizontal slices show the processes or workflow performed by the operator. Horizontal slices do not make sense for files or tables of other persistent data artifacts, as they do not represent processes or actions triggered by the user. For programs, horizontal slices represent the exclusive change of control from one program to another, as for example via XCTL operations in CICS. For screens, they show the possibility for the operator to move from one screen to another.

We can looks at some examples of horizontal slices.

Figure 6 - Horizontal slice for a screen

Figure 6 shows a horizontal slice for screen RWCSA8. The block on the left shows all the screens from which the operator can potentially move to this screen, while the block on the right shows all the screens to which the operator can potentially move from this screen.

I have intentionally used the word “potentially,” because not all these transitions may happen at runtime. The simple reason is that the static analysis cannot always discover the exact transitions, due to the fact that they may be controlled deep in a program or even in a file or table. In some legacy applications, the “traffic” between screens is recorded in a table which a “traffic cop” program reads in order to figure out how to process a user request. Figure 6 should be interpreted as “from screen RWCSA8 one may possible move to screens RWCSA3, RWCSA5 and RWCSA8.” In reality the program that controls RWCSA8 may contain additional restrictions, which prevent, for example, a move to screen RWCSA8.

Figure 7 - Horizontal slice for a program

Figure 7 shows a horizontal slice for programs. Every edge in the graph indicates an exclusive change of control from one program to another program.

Together, horizontal slices and vertical slices offer a good picture of the role of a particular artifact in the application architecture.

 

Understanding anomalies

 

In many real legacy applications there are various exceptions from the layering scheme described above. The SOA Analyzer tool will identify these exceptions, which sometimes need to be addressed in one way or another to allow for an SOA enablement of the all potential services offered by the application.

We are going to call such exceptions “anomalies,” and it is important to notice that they do not represent errors or mistakes. Programs with anomalies (as they are understood here) may function perfectly as they were originally intended, but present dificulties when it comes to a migration to a SOA architecture, as will further see.

In all diagrams presented by the SOA Analyzer, programs with anomalies are shown with a red background. A click on a node for such a program will display a properties pane, where the anomaly is clearly stated, as in Figure 8.

 

Figure 8 - Object properties

 

There are four types of anomalies that the SOA Analyzer identifies.

Client programs with data access

In a perfect architecture, all programs that belong to the client layer should only deal with screen logic and navigation. Data access should be accomplished through the programs belonging to the frontier and sub-frontier layers, which in turn should be called by the client programs. This is the case in a well-layered application, but in real life this restriction is not always enforced. In some cases, where no strict architectural discipline is enforced, programmers may take short cuts and combine the screen access and data access in the same programs, as it could be seen in the vertical slice for program CUSTINQ1.

Figure 9 - Anomaly: Client program with data access

As I have already stated, a program like CUSTINQ1 may function very well, however it may present some limitations when it comes to the mining of services. Let is suppose that this program contains some very special logic that interprets the data read from the Customer Master file. It is possible, for example, that the program reads the date of birth of a customer and calculates the age, which is then displayed on the screen. Many such other derivations are possible. We would like to have a service that not simply reads a record from the Customer Master file, but also interprets and derives new data items. Unfortunately, while CUSTINQ1 does the interpretation and the derivation, it cannot be simply made into a service, as it is also conversing a screen (by definition, a service cannot do that). We will discuss later what can be done in such a case.

Client programs called

It is tempting to look at all programs that are called as potential services. In principle, a call is a request to the called program to perform a task, and that is the nature of a service. In real life applications we will encounter however situations where a called program cannot be made into a service for the simple reason that it also converses a screen, as it can be seen in Figure 10, with program SYSTEM.PCITN100.

Figure 10 - Anomaly: Client called

 

There can be many reasons why the original application included this anomaly. Perhaps the most common one is that when a program written as a service encounters some kind of exceptions, the programmer found it convenient to have the program immediately report it to the operator, by sending a screen with a message.  By writing the program in this style, the programmer simplified the code, but rendered it unfit for a service (which by definition cannot converse with a user interface.

If the program in question is desired as a service, it should be modified such that in stead of sending a screen in case of an exception, it should return to its caller with a special return code signaling the same exception.

 

Transitional programs called

This anomaly is mostly theoretical, as transitional programs are not usually candidates for services. It signals, however, a strange situation, in the sense that usually transitional programs (as defined above) are dedicated mostly to directing the screen navigation, not to the fulfillment of a task, typical for the called programs.

 

Called programs on a path to a screen conversation

This is a generalization of the “Client programs called” anomaly. It happens when a client program calls a “service” program, which in turn calls another client program. Although the one in the middle seems to be a perfect service (because it is called and does not converse a screen), it is in fact impossible to turn into a service, as during the execution one of its called programs converses a screen.

In Figure 10 this is the case with the program CRMODL.GRQUN900, which is “almost” as service, being called by CRMODL.GRQUN600, but in turn calls SYSTEM.CRTXN06, which calls SYSTEM.PCITN100, which is a client program, conversing the screen SYSTEM.PCITM100.

 

Other difficulties

There are some other difficulties we need to overcome in order to expose services from a legacy application. Programs that appear as perfect candidates for services may display certain characteristics that need remedial action.

The problem of screen validations

A ‘perfect’ CICS service program may not become a perfect web service due to the fact that it fails to perform data validations. That may not be a problem in its original environment, as it relies on its callee to perform such validations. Let’s look at Figure 11

Figure 11 - Validations

Next to the ORDERR1 program you can see a label with the text “7 validations”. This label appeared automatically after:

·         I used Relativity’s Business Rule Manager, where I made a request to automatically detect all screen validations in program ORDERR1.

·         I pressed the Tools/Intersect validations menu in the SOA Analyzer.

The “7 validations” label indicates that as ORDERR1 converses the screen ORDMAP1, it performs 7 validations against the data entered by the operator on this screen. Such validations may be checking if the data is numeric, properly formatted or entered in the mandatory fields. When program GETINV is invoked to perform an operation against the INV.CONTROL file, it assumes that all data is already valid (otherwise ORDERR1 would have issued a warning message to the operator). GETINV can now fulfill the requested tasks without the danger of running into some data that does not make sense.

Although GETINV is otherwise a good candidate for a service, here is the caveat! If this service is invoked from another environment then its original one, there may be no guarantee that the data it receives is valid. What worked perfectly in CICS may not work properly in a SOA architecture.

There are various remedies we can provide to resolve this issue. One may be that the application server or even the client facing programs in the new architecture performs the validations and ensures that GETINV will not receive anything else then correct data. Another remedy is to repeat the same validations in GETINV as they exists in its caller, ORDERR1, and have GETINV return with a special return code should these validations fail.

The problem of transient or temporary data queues

One would usually expect that the caller and callee programs in a CICS environment communicate through the CICS COMMAREA. This is the most common way in which CICS programs pass data, but not the only one. It is also possible that the callee writes the data into a temporary storage queue and the caller reads it from there. As most CICS adapters are equipped to only deal with data passing through COMMAREA, this creates a major difficulty.

We need to discover if such situations exists. It is in fact quite simple. After I display a vertical slice through the architecture (see the description of vertical slices above), I press on the Tools/Intersect queues menu. This will add labels next to the programs that operate with queues, as in Figure 12.

Figure 12 - Operations with queues

This diagram tells us that GETINV writes to a queue and ORDENT1 reads from a queue. It is just a red flag at this point, enough to send us to investigate. If we really find that the data passes from GETINV to its caller via the queue, then we know that normal service adaptors would not be able to create a good service out of GETINV. When the program will be called as a web service in a SOA architecture, the service consumer will expect to collect all data from the service interface that describes the COMMAREA, while the data will actually reside in a queue.

The remedy is to either modify GETINV to pass the data exclusively through the COMMAREA, or to create a special ‘service’ program that reads the queue and passes it through the COMMAREA. Finally, it is possible that some vendors may offer service adapters that are capable to get the data from CICS queues.

 

 

Finding the service functionality

 

As service programs capable for exposure are themselves placed in sub-layers, the question is which one to choose. Given that we may look for a particular service function (like, for example, “retrieve claim”), we need to narrow the search to those that in one way or another are related to this function. The development team maintaining the application may simply know which are the programs implementing the function. In the absence of such direct knowledge, we can use other methods to find the functionality we want to expose.

Starting from screens

One such method is to start with the screens that suggest the functionality we are after. By inspecting the screens, for instance, we may discover that one of them helps the operator perform an “order entry” function. Screens may be viewed in the SOA Analyzer by selecting the “View source” menu visible when we right-click on a screen mode. Our ‘order entry function will display as in Figure 13 bellow.

Figure 13 - Order entry screen


Once we discover the screen that deals with the service function, we can look at its “vertical slice” through the application. The vertical slice, as displayed by the SOA Analyzer, shows a cut through the layers, which includes the screen as well as all the programs that service it, as in the diagram bellow.

Figure 14 - Vertical slice for Order Entry screen

 

In this diagram, we can see that the screen ORDMAP1 (which appears on the top) is accessed by the program ORDENT1, which in turn calls other programs to fulfill a request. Any of these called programs are candidates for services. Together, they could become operations in a web service that would be consumed when in the new SOA architecture one makes a request to create a customer order.

As we look for potential service programs, we should give a special attention to the frontier programs. Indeed, they encapsulate the most complete functionality. They “know” not only what data to access, but also how to assemble it in a business-consistent manner that is suitable for further use. If lower layer programs are selected, then some of the data assembly must be performed on the application server, opening the possibility of erroneous implementations that differ in functionality from the original application. Choosing frontier programs for exposure makes the task simpler and eliminates the possibility of further errors.

Looking for special program constructs

Another method to find the services with a particular functionality is to look for special patterns in the code. This can be accomplished from the RMW Analyst with the aid of the so-called clipper queries.

To run a clipper query, we’ll go through the following steps:

·         Select a program in the SOA Analyzer, right-click on it and press the Show source menu. The source of the program appears in a pane of the tool, as in Figure 15. If I press on the top right button, a menu appears on which I select Clipper.

Figure 15 - Source pane

 

·         A new pane is open in the source pane. I press the corresponding toolbar button to create a new list (this is where the results of the query will be deposited).

 

·         A new pane is opened in the source pane, on which I locate the search button and after I press it I select Cobol sources as the space that I’m going to search, as in Figure 16 bellow.

 

Figure 16 - Start clipper query

·         I am prompted with a new window on which I can build my query. Clipper queries allow me to interrogate any type of program construct as well as combinations of such constructs. In this case, I build a very simple query that looks for variables containing the string INV, hoping to find the places where an invoice is updated. The intention is to isolate the program that maintains invoice data. The query looks like the Figure 17 bellow.

 

Figure 17 - Clipper query

·         After I press the Find All Constructs button a search is performed and results are stored in the new list that I have created, called Invoice. I can at any point in time inspect this list and visit all occurrences if the INV string in a variable name. I can, of course, write down the name of the programs that contain such occurrences, but I can also ask the SOA Analyzer to “intersect” any diagram with this list. This will show which programs included in a diagram contain occurrences from the list.

·         In order to intersect a diagram with a list of program constucts obtained from a Clipper query, I display first the diagram, then I select the Tools/Intersect list menu. I am prompted with a list of all existing lists, as in Figure 18, of which I select one (in this case the one called Invoice, which I have just created.

Figure 18 - Selecting a list

·         As a result of a selection, SOA Analyzer creates labels for all programs in the current diagram, that contain items from the list. The text of the label indicates the number of occurrences, as in Figure 19.

 

Figure 19 - Vertical slice intersected with a list

All this search points to the GETINV as a good candidate for the desired service. It performs some operations with the Invoice and it is a service type program that does not converse any screen.

 

The case of mixed programs

 

Sometimes the functionality we want to expose is found in a client program. Unfortunately the client program cannot be called as a service, as it contains screen communication as well as screen logic that does not make sense in a service call.

There are at least two solutions to this problem.

Solution 1: Modify the program by removing all screen interaction and screen logic.

Solution 2: Split the program into two separate programs, one containing the screen interaction and logic, the other containing the service function.

The first solution has a number of disadvantages:

·         It requires a massive modification of the code, which may result in errors.

·         It results in duplication of code (supposing the original program is kept inn production), hence requiring synchronized maintenance to the original and modified versions.

The second solution, the one we recommend, avoids the pitfalls of the first. It consists in using a slicing technique, which could be achieved either manually or by the use of a specialized tool, like Relativity’s RMW Architect product.

Slicing could be described as follows. Given a program PROG with a paragraph PARA, two programs are created, PROG1 (main) and PROG2 (service), such that (1) PROG1 calls PROG2, (2) paragraph PARA no longer exists in PROG1, but appears in PROG2 and (3) PROG1 (which includes the call to PROG2) functions in an identical way to the original PROG.

Program slicing may be employed in order to separate the client functionality from the service functionality. In a simple case, suppose that a program communicates with a screen on which the user requests the content of an invoice with a particular invoice number. The program receives the screen, validates that the invoice number is correctly formatted, determines which program key was pressed by the user, invokes a paragraph GET-INVOICE to obtain the data, formats it and displays it on the same screen. In this case, paragraph GET-INVOICE may be sliced out of the program. The resulting main program will now contain the screen logic, while the resulting service program will access the persistent storage and return the content of the invoice. Since this second program has the characteristics of a service, it could be exposed to the outside world as a web service. Furthermore, the application will function just as before the slicing.

If slicing is used to separate screen logic from service logic, the question is what paragraph could be used as the basis for slicing?

We face here a similar situation with the one described before, in which we must decide the level of the granularity offered by the service. If we aim too low in the paragraph “call map,” we risk obtaining services that are too granular and at the same time lose some of the business logic that prepares the data. If we aim too high, we risk to include undesired screen logic. The best choice is to again select a “frontier” paragraph, which sits at the border of the screen and service logic. Such a paragraph would be the highest in the hierarchy of service type paragraphs.

In order to find the best slicing point and extract a slice that could be later used as a service, we proceed as follows.

·         Once we located the program that requires slicing, we right click on a node that represents it and select the “Show internal” menu. As a result, we see a new diagram that displays the relationships between paragraphs, as in Figure 20 bellow.

Figure 20 - Internal paragraph calls

·         We must find the paragraphs which can be “sliced out” in the form of separate callable programs. We must select only paragraphs that (1) do not access screens and (2) do not call other paragraphs that access screens.

In the example from Figure 20, we can see that 000-ENTER-ORDERS cannot be sliced-out, as it calls 1400-SEND-ORDER-MAP, which contains screen opertations. The same is true for other paragraphs, like for instance 2000-PROCESS-POST-ORDER or 1000-PROCESS-ORDER-MAP.

There are other paragraphs that are good candidates for slicing. It is to our advantage to select one that is as high as possible in this call hierarchy, as that would provide maximum functionality. One such candidate is 1200-EDIT-ORDER-DATA, which accesses both the customer and the product files. Another one is 2100-WRITE-INVOICE-RECORD. If we create slices of these two paragraphs, we obtain two programs, which together offer the functionality needed in order to create an invoice.

·         To mark the selected paragraphs for slicing, we right-click on them and select the “Create slice item” menu. As a result, two things happen: (1) the paragraphs are marked on the diagram indicated that we have marked them for slicing (as you can see in Figure 21) and (2) a list is created that contains information about these slicing points.

Figure 21 - Slicing points defined

·         We switch now to the RMW Architect, in order to perform the actual slicing operation. We will find the two slicing points in a list under the category Architect. As we click on any item in this list, the source pane will automatically select the corresponding paragraph for slicing, as in Figure 22 bellow.

 

Figure 22 - Finding the paragraphs to be sliced

·         We right-click Structure Based in the Components pane and then select the “Define new” menu, which opens another pane, where the parameters of the slice are defined. We only have to point it to the paragraphs in the list created from SOA Analyzer, to create a correct slicing definition, as in in Figure 23.

 

·         We press the Extract button (represented by an icon showing scissors). We have to specify a number of parameters, as for instance if we want the resulting program to be a CICS callable program. As a result, a new program is created, which contains the intended functionality and which could be exposed as a web service.

 

Determining the data interface

After we have found the right programs that can be exposed as web services, we need to define their data interfaces. This is not a trivial task, for a number of reasons.

Let’s take the case in which we want to expose the service that retrieves an invoice based on an invoice number. It would be great if (1) the definition of the commarea of the service program would be stored in a copybook and (2) the commarea would have a very simple definition, like for instance

01    COMMAREA.
05 INVOICE-NUMBER    PIC 9(7).
05 INVOICE-CONTENT.
     10 INVOICE-DATE…..

In reality, we are faced with three problems:

(1)   the definition of the commarea may not reside in a copybook

(2)   the commarea defined in the LINKAGE SECTION of the program may be very simple, like for instance 01 COMMAREA PIC X(30000), thus obscuring the actual fields, that appear in another structure to which COMMAREA is moved in the program

The SOA Analyzer will help us to determine the correct interfaces and even create a complete WSDL definition for the service.

We will proceed as follows.

 

·         In SOA Analyzer we select the Service/New menu and give a name to the service. (We will call it “Invoice”.) This service will appear on a new pane of the tool.

·         Having this service selected, we select a proper program (which was found in the previous steps), right-click on the node representing it and select the “Add to Service” menu. SOA Analyzer will analyze the program and detect its COMMAREA which will form the basis for the service interface. In the Service pane, the SOA Analyzer will display something like in Figure 23 bellow.

Figure 23 - Adding a program to a service

·         In the service pane, under the service called Invoice, we have a tree with a node called Seeds. Under this node we find the specification for the program that we added to the service, including the COMMAREA that is used as in interface. We find however a common problem, the fact that the COMMAREA appears as a single block of 90 bytes, which would not allow us to derive sensible and useful fields for the service interface.

To solve this problem by designating a synonym for DFHCOMMAREA. A synonym is another data structure, which either redefines or is moved to DEFCOMMAREA or DFHCOMMAREA is move to it. Such synonyms are easy to find with the following procedure:

o   We select the DFHCOMMAREA in the source screen and right click on it.

o   We select the Instances menu, which will show a list of all usages of this data structure (where it is moved or redefined)

o   As we inspect the list, we select a convenient synonym

·         In this example, we notice that DFHCOMMAREA is moved to INVCTL-RECORD, which may supply a better definition for the interface. We select this data area in the source pane, then select DFHCOMMAREA in the service pane and press the “Import synonym” menu. As a result, the definition of the interface inn the source pane changes to what we can see in Figure 24.

Figure 24 - Using COMMAREA synonyms

·         We notice that now we have a detailed specification for the COMMAREA. One last task that we can perform, before creating the WSDL is to indicate the inputs and outputs of the interface. By default, all fields are both inputs and output, however it would be nice to separate them, if it is possible. In this case it is quite easy, since one substructure contains INPUT in the name, the other contains OUTPUT. We can right-click on INVCTL-INPUT and select the “Make input” menu. In the same way, we select the INVCTL-OUTPUT and select the “Make Output” menu. As a result, the specification now looks like in Figure 25, in which the arrows for the adjacent icons indicate the usage as input or output.

Figure 25 - Inputs and outputs

·         We have come to the last step: creating a service definition. We right-click on the service and press the “Generate WSDL” menu. As a result, a WSDL definition for the service is generated and display as in Figure 26 bellow.

 

Figure 26 - Generating WSDL

 

·         We can add more then one program to the service. In this case, each program will generate on service operation, while its COMMAREA will define an interface. The resulting WSDL can be exported in an outside fiile, by ising the File/Export WSDL menu of the SOA Analyzer tool.