Rapid Application Development (RAD) Best Practices with CodeGear

Delphi Journal

Subscribe to Delphi Journal: eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get Delphi Journal: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


Delphi Authors: Jordan Sanders, satya brahma, Bob Swart, Salvatore Genovese, Core Ideas

Related Topics: Apache Web Server Journal, Java Developer Magazine, Delphi Journal

Apache Web Server: Article

Delphi 6 and Kylix 2Web ServicesEasy-to-build Web servicesand SOAP Applications

Delphi 6 and Kylix 2Web ServicesEasy-to-build Web servicesand SOAP Applications

When Borland shipped Delphi 6 in May of last year, one of its new features was support for SOAP - most notably in the form of Web services. Borland Kylix 2 (for Linux) is now also available with the same capabilities, and as I write this article, Borland has just announced the Borland Web Services Kit for Java, which will enable Borland JBuilder to create and consume Web services using WSDL and SOAP. Finally, by the time you read this article I expect Borland C++ Builder 6 to be announced (or available) with the same SOAP and Web services capabilities that Delphi 6 and Kylix 2 currently have. Perhaps even a bit more, since SOAP is ever evolving.

In this article, I want to demonstrate the ease of use of Delphi 6 and Kylix 2 (two RAD tools) by developing a Web service in a Delphi 6 server (running on Win32) and consuming it in a Kylix 2 client running on Linux.

What is a Service?
For the Web Service "engine," I'm using Delphi 6 Enterprise. You can download a free 60-day trial edition of Delphi 6 Enterprise from their Web site at www.borland.com/downloads (although you may not deploy applications written with this trial edition, you can follow the instructions and steps in this article to see how easy it is to write your own Web services).

To create a Web service, start Delphi 6 Enterprise and from the main menu do File | New and then select Other to get the so-called Object Repository dialog. Go to the Web Services tab, which contains three icons: one for a Soap Server Application, one for a Soap Server Data Module, and one for the Web Services Importer. If you've registered your copy of Delphi 6 Enterprise (the real version), you can download a few additional tools and wizards, which among others result in a fourth icon here, namely the Invocable Wizard (see Figure 1).

To start a new Web service, double-click on the Soap Server Application icon, which gives a dialog (see Figure 2) in which we will specify the Web server application that will contain our Web service. Note that although the latest SOAP protocol specifies more than just the HTTP protocol for communication (including FTP and SMTP), Delphi mainly supports HTTP using the wizards from Figure 1, and hence uses a simple Web server application as wrapper.

Figure 2 shows that we have a number of choices here. For a real-world Web service that will be used (consumed) a lot, you should look at ISAPI/NSAPI or Apache DLL possibilities. For debugging purposes, you can start with a Web App Debugger executable (you can always transform your Web server project to another target). For our example, I want to select a simple CGI standalone executable because I want to deploy the resulting Web service on the Internet, and since it's only an example with this article, I don't reckon it will be consumed that much (so I don't need to turn it into a DLL for improved efficiency).

Web Module
Once we've made our choice, we can click on the OK button and a new Soap Server application will be generated, including a Web module (the core of our Web server application). Save the Web module in file SWebMod.pas and the project in D6WebService.dpr before you continue. As you may have noted by now, the Web module already contains three configured components, which form the basis of our Web service.

From left to right, the HTTPSoapDispatcher is used to receive incoming SOAP requests and dispatch them to another component (defined by the Dispatcher property) that can interpret the request and execute it. The latter will be done by the HTTP SoapPascalInvoker component, which receives the incoming SOAP request, executes (invokes) a Pascal method, and produces the response back to the HTTPSoapDispatcher. But before the HTTPSoapPascalInvoker can actually invoke the requested Pascal method, it checks to see if the method's interface and implementation class have been registered (in the invocation registry; we'll get back to this in a moment). While the first two components are used when the Web service is actually consumed, the third component - WSDLHTML Publish - is used to produce the WSDL (Web Service Description Language) that defines the Web service itself.

Invokable Wizard
The three components on the Web module have already been configured, so you don't have to work on them to make your Web service function. In fact, right after you've created the Web module and saved your project files, you should continue with the next step, which involves starting the Invokable Wizard from the Object Repository. Again, do File | New | Other, go to the Web Services tab and double-click on the Invokable Wizard. This will result in the Invokable Interface & Class Wizard where we can define the (file)name of our Web service engine (see Figure 3).

Because we're building an example Web service, I've designed a simple engine which does nothing more than convert some input value to an output value. For this example, I've implemented a little Roman number conversion routine - from decimal to Roman and back. As a result, I would like to use the name "Roman" (the editbox in the upper-left corner). Typing Roman here seems to result in a sensible value for everything except the Invokable class type combobox, which offers us two choices: TInterfacedObject or TInvokableClass. The latter is easier to manage, so select the TInvokableClass here.

Finally, click on Generate to create two new units: RomanIntf.pas with the IRoman interface definition and RomanImpl.pas with the TRoman class that implements the IRoman interface.

Without the Invokable Wizard to generate the two units, you can write the units Roman Intf.pas and RomanImpl.pas yourself (see the two listings that follow), so with the trial edition you need to enter more code.

IRoman interface
Both the definition of IRoman and implementation of TRoman are still empty, of course, so now is the time to actually write some code. For our Roman number conversion, I want two methods: IntToRoman and RomanToInt. The first would get an Integer as argument and produce a String as result; the second would get a String as input argument and would produce an Integer as result. In Object Pascal, the IRoman definition should look like Listing 1 (unit RomanIntf.pas).

The code inside the initialization section will register the IRoman interface in the Invokable Registry (where the HTTPSoapPascalInvoker will look for it later). Note that you needed to write only two lines (the functions IntToRoman and RomanToInt), and that the generated comments already suggest you should use the stdcall calling convention.

TRoman Implementation
Once we've saved the RomanIntf.pas file again, we can move to the RomanImpl.pas unit to finish the TRoman class. Since TRoman is implementing the two methods from IRoman, we must copy these declarations inside the class definition of TRoman. With only two methods, that's easy, but with a few dozen it can be a bit messy. Fortunately, Delphi offers us some support with Code Insight. Just move to the class definition of TRoman in the code editor and click Ctrl+Space to show the available methods of TRoman and IRoman. The Code Insight window will start with a number of methods in Red - these are the abstract methods from IRoman that need to be implemented. Just select all the Red methods and press enter to insert them all inside the class definition of TRoman.

Once the class definition is complete, you can generate empty placeholders for the actual implementation by pressing Ctrl+C. This will produce the skeletons for the IntToRoman and RomanToInt functions (see Listing 2).

Again, the code inside the initialization section will register the TRoman class in the Invokable Registry (where the HTTPSoapPas calInvoker will look for it).

The actual implementation of IntToRoman and RomanToInt is rather lengthy, and not important for the Web service topic itself, so I haven't included it here in the listing of unit RomanImpl.pas.

Deployment
This is it. After you've saved your project files, you can compile the Web service application. In order to use it, you must now deploy it as a Web server application. For your convenience, I've done that already, and the D6Web Service.exe is available to use as an exercise on my Web site at www.eBob42.com/cgi-bin/D6WebService.exe

Note that this direct URL won't do anything. You actually have to pass the additional PathInfo/wsdl to get the WSDL (automatically produced by the WSDLHTMLPublish component; see Figure 4).

If you click on the link for WSDL for IRoman (or http://www.eBob42.com/cgi-bin/D6WebService.exe/wsdl/IRoman) you get the full WSDL for the IRoman interface.Now we'll move over to Linux and start Kylix 2 Enterprise to write a Web Service consumer for this application.

Kylix 2 Enterprise
If you don't have Kylix 2 Enterprise, you can download a 60-day trial version from the Borland Web site. But you can also write a Delphi 6 client for the Web service using the same steps needed for the Kylix 2 client, so it shouldn't be hard to play along either way.

A Web Service consumer can be any kind of application. But to keep things simple, let's just start a new default visual application in Kylix. Save the form in file MainForm.pas and the project in RomanC lient.dpr (or any other filename you wish to use now).

Web Service Importer
Remember the Web Services tab of the Object Repository in Delphi 6? Kylix 2 has a similar one (although I haven't seen the Invokable Wizard for Kylix yet). This time, we need to use the Web Service Importer, since we must import the WSDL that defines the Web service and generate an Object Pascal import unit that defines the interface of this particular Web service. So, do File | New and go to the Webservices tab of the Object Repository and double-click on the Web Service Importer icon, which will result in the Web Services Import wizard (see Figure 5).

We now need to specify the URL to retrieve the WSDL information for our Web Service, (www.eBob42.com/cgi-bin/D6WebService.exe/wsdl/IRoman). Look at the options in the Advanced tab or directly click on the Generate button to create the Web Service import unit. This will also work with Web services that are written in another development environment, although some interoperability issues between SOAP implementations remain to be worked on.

Save the generated import unit in file Roman.pas and add it to the uses clause of the MainForm unit. The generated unit Roman.pas can be seen in Listing 3:

Note that the arguments to the two methods, IntToRoman and RomanToInt, have been declared as "const" now. Other than that, the importation of the IRoman interface looks exactly as the original IRoman interface that we defined using Delphi 6.

Now, drop two TLabel, two TEdit, and two TButton components on the main form. One label/edit pair is for the normal decimal number, and one label/edit pair is for the Roman numeral. Finally, one button will convert the contents of EditInt from Int to Roman and another button will convert the contents of EditRoman back from Roman to Int again. We also need to drop a HTTPRIO component from the Web Services tab of the Component Palette (see Figure 6 for the final layout of the main form).

HTTPRIO
The HTTPRIO component is our gateway (using HTTP) to the Remote Invokable Object. Although we have the Roman.pas import unit that defines the capabilities of our Web Service, we must tell the HTTPRIO component some information as well (such as the Service and Port). For this, we need to specify the WSDL URL again in the WSDLLocation property of the HTTPRIO component. Once you've set this property value, you can open up the combobox for the Service property, to give it the value IRomanservice; and then for the Port property, to give it the value IRomanPort (see Figure 7).

Once the HTTPRIO component is configured, we can write two event handlers and a little code to actually use the available methods. To use the HTTPRIO component, we can simply cast it to the IRoman interface (actually, the correct phrase would be to extract the IRoman interface from the HTTPRIO component, but the effect is the same). The implementation of the two-button OnClick event handlers inside the main form is shown in Listing 4.

The Web service consumer client running on Linux can be seen in Figure 8.

A final nice thing about Delphi 6 and Kylix 2 is that although the former runs on Win32 and the latter runs on Linux, the source code of their CLX projects is actually cross-platform (usually with minor changes to make it work). In this case, it doesn't involve a single change in the source code, so you can take the RomanCli ent.dpr project from Kylix 2 and compile it with Delphi 6 to produce a working client on Windows.

Conclusion
I hope I've shown you that it's easy to build Web services and SOAP applications with Delphi 6 and Kylix 2 using available components and wizards for both the server side and the client (consumer) side. And with the addition of the Borland Web Services Kit for Java (for JBuilder) and the forthcoming release of C++Builder 6, we'll have a full range of Borland RAD tools and languages on platforms supporting SOAP and Web services.

For interoperability with other vendors and their SOAP implementations, Borland participates in the SOAP Interoperability studies, which can be found on the Borland Website at http://soap-server.borland.com/WebServices

More Stories By Bob Swart

Bob Swart (aka Dr.Bob at www.drbob42.com) is an IT consultant, developer, reseller, author, trainer and webmaster for his company Bob Swart Training &Consultancy (eBob42) based in Helmond, The Netherlands.

Bob has spoken at Delphi Developer Conferences since 1993. Bob is co-author of several books, including C++Builder 5 Developer's Guide, Kylix Developer's Guide, and Delphi 6 Developer's Guide, as well as a contributing author for numerous computer magazines.

Comments (2)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.