Implementing the Applications


One of the major strengths of Application Designer and the other Distributed System Designers is that they encourage the design of systems that can actually be implemented and deployed. In this section, we'll show you just how easy it is to move rapidly from a design to an implemented and locally deployed system.

Note

UML tools in particular encourage the design of applications in an abstract sense, and from a user perspective, with little regard up-front for whether those applications can actually be built. We have witnessed too many projects where that has turned out to be the case. The use-case-driven analysis-first approach is fine up to a point, which is where we currently see a retained role for Visio alongside Team System, but once the handover has occurred from the business analysts to the designers/developers, it's time to take advantage of Team Edition for Architects' real strengths.

It's precisely because of the Distributed System Designers' strengths in this area that we'll be devoting plenty of attention to coding, in what you might have expected to be purely a "design" chapter. Don't worry as it won't be too taxing and we won't be asking you to work with complex database schemas, XML files, and the like. You'll do just enough to get the design up and running to the point that you could credibly take it forward.

Before you implement the design, we'll invite you to set the implementation languages for the various applications by clicking each one in turn and selecting the relevant language in the Properties window:

  • StockQuoteApp should be set to Visual C#.

  • DealingApp should be set to Visual Basic.

  • StockBroker should be set to Visual Basic.

  • MarketMaker should be set to Visual C#.

Of course, you're free to choose whatever languages you wish, but the subsequent discussion of the generated code will make more sense if you stick to our choices.

Important

Provided files: The accompanying file StockBrokerApplicationDesign.zip includes a Visual Studio 2005 solution containing the application diagram for our example, so you have the option of performing the following implementation steps using our diagram if you have not successfully created your own. A separate file, StockBroker ApplicationDesignImplemented.zip, contains the full solution as we implemented it, so wherever we ask you to enter code in the following sections, you could simply copy the code from the files in that solution.

To implement an entire design, you can simply right-click an empty portion of the diagram and choose Implement All Applicationsfrom the context menu. The phrase "empty portion of the diagram" is important because if you click a specific application, you will implement just that one.

Important

You cannot reverse the process that generates project files for applications, which means you cannot subsequently modify some implementation properties such as the language. It's always a good idea to save the application diagram (i.e., Stock BrokerApplicationDesign.ad) as soon as you've drawn it and before you implement it, so that you can roll back and start again.

A Confirm Application Implementation dialog box will appear showing the applications to be implemented. Clicking OK will cause Visual Studio to begin generating code and creating deployment websites. At the end of this process, you will see several new projects in the Solution Explorer, one for each implementable application.

Important

By default, Web service applications will be deployed as file-based Web services that run in the ASP .NET Development Server, rather than being deployed in full to IIS. This can be very convenient during development, but if you want to deploy properly to IIS, then you can do this by selecting the application on the application diagram and changing its Project property (in the Implementation section) to localhost/WebServiceName.

The StockMarket application will not have an implementation in the Solution Explorer because it's a generic application; and as mentioned earlier, generic applications cannot be implemented.

If you had represented the MarketMaker third-party application as an ExternalWebService (we told you how in the "Representing an existing service" section earlier in this chapter), it too would not have been implemented; but as there was no such service in existence already, we modeled it as a conventional ASP .NETWebService to demonstrate the service layering. This means it will have an implementation project. Obviously, the database will not have been generated as an implementation project, but it will be represented as a connection in its client application.

You can represent applications that are referenced by other applications but that are not implemented in your solution nor planned for deployment as part of any application systems that you design and compose from applications in the solution. Though these applications are called external because they are technically external to a system in the context of implementation and deployment, you can still include these applications as part of a system design. Including external applications in a system makes it possible for you to validate communication pathways to and from these applications when you define and validate deployment for the system. When the system is eventually deployed, references to external applications must be resolved with the actual deployment location of these applications. Don't underestimate what has happened here. While your UML tool may well be able to generate code skeletons from a design, would you really expect it to deploy new websites directly into IIS in a form that you can run with no additional configuration and virtually no extra coding?

A note about SDM files

In the discussions that follow, we'll invite you to examine some of the implementation files that have been generated, and to modify those files in order to complete the implementations. In addition to those files, a number of System Definition Model (.sdm) files may also have been created. We won't discuss those files in this chapter as they are not crucial to the implementation of our design, but you will learn about the structure and purpose of SDM files in Chapter 7.

All you need to know right now is that prior to implementation, the application diagram (.ad) file itself stores the definitions of the applications. During implementation, an additional SDM file will have been generated for each application to contain the definitions. These files should not be modified except through Application Designer.

The MarketMaker implementation

The MarketMaker project will appear in Solution Explorer under location C:\…\MarketMaker\ (for file-based deployment) or http://www.localhost/MarketMaker (for IIS deployment), and will contain several automatically generated files. The important files for our discussion are as follows:

      App_Code/       DealingService.cs      DealingService.asmx 

The file DealingService.cs contains the implementation code for the service of that name exposed by the MarketMaker application. You will modify this file.

The file DealingService.asmx defines the DealingService Web service that you added as a provider endpoint. You won't modify this file, but you will use it to test the service, and it's worth noting its content, which hooks up to the DealingService.cs code-behind file:

      <%@ webservice  language="c#"      codebehind="~/App_Code/DealingService.cs" %> 

Modifications to DealingService.cs

The following listing shows the code that was generated for the MarketMaker.cs file. Notice how the Summary texts that we entered into the Web service Details window have found their way into comments in code. All of this code was generated automatically, except for the highlighted lines. You should add those manually to provide basic implementations of the web methods:

      namespace MarketMaker      {       [System.Web.Services.WebServiceBinding(Name = "DealingService", ConformsTo =      System.Web.Services.WsiProfiles.BasicProfile1_1, EmitConformanceClaims = true),      System.Web.Services.Protocols.SoapDocumentService()]       public class DealingService : System.Web.Services.WebService       {         ///<summary>         ///This operation allows a stock to be bought.         ///</summary>         ///<param name="stockSymbol">The unique identifier for the stock.</param>         ///<param name="numberOfShares">The number of shares to be bought.</param>         [System.Web.Services.WebMethod(),      System.Web.Services.Protocols.SoapDocumentMethod(Binding = "DealingService")]         public int buyStock(string stockSymbol, int numberOfShares)         {         System.Random rnd = new System.Random(numberOfShares);         if (rnd.NextDouble() > 0.5) return numberOfShares;         else return 0;          }          ///<summary>          ///This operation allows a stock to be sold.          ///</summary>          ///<param name="stockSymbol">The unique identifier for the stock.</param>          ///<param name="numberOfShares">The number of shares to be sold.</param>          [System.Web.Services.WebMethod(),      System.Web.Services.Protocols.SoapDocumentMethod(Binding = "DealingService")]         public int sellStock(string stockSymbol, int numberOfShares)         {          System.Random rnd = new System.Random(numberOfShares);          if (rnd.NextDouble() > 0.5) return numberOfShares;          else return 0;         }        }      } 

If you really did want to place stock deals into a database, that is where your database access code would go. To keep it simple, you're just returning the number of shares sold (if the deal went ahead) or 0 (if it didn't) on a random basis. Client applications need not know that you've used such a stubbed-out implementation.

Test-running the MarketMaker application

Once you have made the code modifications highlighted in the preceding section, you are in a position to take the MarketMaker application—specifically, its DealingService Web service—for a test drive. Just right-click the DealingService.asmx file, choose View in Browser, and Internet Explorer will open at the URL for the service.

You'll see options for the two operations. If you choose buyStock, you will then be able to fill in the form shown in Figure 2-8.

image from book
Figure 2-8

Remember that the buyStock operation returns the number of shares actually bought, or 0 if the deal could not be processed. Given the input data of stockSymbol=MSFT, and numberOfShares=12, the response in XML is as follows:

      <?xml version="1.0" encoding="utf-8" ?>      <short xmlns="http://tempuri.org/">12</short> 

If you enter 5 as the numberOfShares, then you get the following response, demonstrating how we've simulated failed deals using the random number generator:

      <?xml version="1.0" encoding="utf-8" ?>      <short xmlns="http://tempuri.org/">0</short> 
Note

We think that one of the great features of Web services, compared with other distributed technologies, is that you can test them in this way independently and irrespective of whether you have yet coded their clients.

The StockBroker implementation

The MarketMaker project will appear in the Solution Explorer under location C:\…\StockBroker\ (for file-based deployment) or URL http://www.localhost/StockBroker (for IIS deployment) and will contain several automatically generated files. The important ones for our discussion are as follows:

      App_Code/       DealingService.vb       StockQuoteService.vb      DealingService.asmx      StockQuoteService.asmx 

Between them, the files DealingService.asmx and StockQuoteService.asmx contain the following Web service definitions with links to the code-behind file:

      <%@ webservice  language="vb"      codebehind="~/App_Code/DealingService.vb" %>      <%@ webservice  language="vb"      codebehind="~/App_Code/StockQuoteService.vb" %> 

StockQuoteService.vb

This code simulates the action of the getQuote operation by simply returning a random number between 0 and 100 as the latest stock price, regardless of the stockSymbol passed in. Remember that you're implementing this method purely to test the interconnectedness of the overall design, not to create a fully functional stockbroking system.

      Namespace StockBroker        <System.Web.Services.WebServiceBinding(Name:="StockQuoteService",      ConformsTo:=System.Web.Services.WsiProfiles.BasicProfile1_1,      EmitConformanceClaims:=True)> _        <System.Web.Services.Protocols.SoapDocumentService()> _        Public Class StockQuoteService          Inherits System.Web.Services.WebService          ''' <summary>          ''' This operation returns the current share price for a given stock.          ''' </summary>          ''' <param name="stockSymbol">The unique identifier for the stock.</param>          <System.Web.Services.WebMethod()> _      <System.Web.Services.Protocols.SoapDocumentMethod(Binding:="StockQuoteService")> _          Public Function getQuote(ByVal stockSymbol As String) As Double           Dim randomPrice As Integer           randomPrice = Rnd() * 10000           Return randomPrice /100          End Function        End Class      End Namespace 

DealingService.vb

In the code that follows, the buyStock and sellStock operations are implemented by delegating to the same-named services of the (third-party) MarketMaker application. The remote services are accessed via local Web service proxies that for our purposes are identical but which hide the technical details of sending SOAP messages to those services.

Note

A proxy is a client-side representation of a remote object, component, or service. A method invoked on a local proxy triggers the same method to be invoked on the remote service, with the details of how that happens—for example, by sending a SOAP message—being hidden within the proxy itself.

      Namespace StockBroker        <System.Web.Services.WebServiceBinding(Name:="DealingService",      ConformsTo:=System.Web.Services.WsiProfiles.BasicProfile1_1,      EmitConformanceClaims:=True)> _        <System.Web.Services.Protocols.SoapDocumentService()> _        Public Class DealingService          Inherits System.Web.Services.WebService          ''' <summary>          ''' This operation allows a stock to be bought.          ''' </summary>          ''' <param name="stockSymbol">The unique identifier for the stock.</param>          ''' <param name="numberOfShares">The number of shares to be bought.</param>          <System.Web.Services.WebMethod()> _              < System.Web.Services.Protocols.SoapDocumentMethod       (Binding:="DealingService")> _          Public Function buyStock(ByVal stockSymbol As String, ByVal numberOfShares As       Integer) As Integer            Dim MarketMakerDealingService As New       StockBroker.WebServiceProxies.DealingService()            MarketMakerDealingService.UseDefaultCredentials = True            Return MarketMakerDealingService.buyStock(stockSymbol, numberOfShares)         End Function         ''' <summary>         ''' This operation allows a stock to be sold.         ''' </summary>         ''' <param name="stockSymbol">The unique identifier for the stock.</param>         ''' <param name="numberOfShares">The number of shares to be sold.</param>         <System.Web.Services.WebMethod()> _             <System.Web.Services.Protocols.SoapDocumentMethod       (Binding:="DealingService")> _          Public Function sellStock(ByVal stockSymbol As String, ByVal numberOfShares As       Integer) As Integer            Dim MarketMakerDealingService As New       StockBroker.WebServiceProxies.DealingService()            MarketMakerDealingService.UseDefaultCredentials = True            Return MarketMakerDealingService.sellStock(stockSymbol, numberOfShares)         End Function       End Class      End Namespace 

Important

The code line MarketMakerDealingService.UseDefaultCredentials = True is included to overcome a problem with accessing remote Web services in a file-based deployment. If you deploy properly to IIS (we told you how), then that code will not be required.

With that code in place, you're now ready to test the StockBroker application.

Test-running the StockBroker application

Test-running the DealingService on this application will produce the same results as when you tested the same service on the MarketMaker application; but as you test this service yourself, bear in mind that something quite different is happening under the covers: a Web service delegating to another Web service.

Note

One of the guiding principles of a Service Oriented Architecture (SOA) is that services may be designed in layers, with application-specific services calling on generic business services and/or technology-bound services.

The StockQuoteService is new in this application, and Figure 2-9 shows it in action.

image from book
Figure 2-9

For stockSymbol MSFT (Microsoft), the resulting XML response is as follows:

      <?xml version="1.0" encoding="utf-8" ?>      <double xmlns="http://tempuri.org/">70.55</double> 

Each time you run it, the result will be different because you implemented this method with Rnd() to simulate the volatility of share prices. (Of course, it's only a fictional share price, so don't go investing on the back of this information!)

That's the last of the Web services that we designed. You have tested them independently, and if you're happy that they're all running correctly, you can now proceed to look at the end-client applications shown on the application design diagram.

The StockQuoteApp implementation

The StockQuoteApp project will appear in the Solution Explorer under location C:\…\StockQuoteApp\ (for file-based deployment) or URL http://www.localhost/StockQuoteApp (for IIS deployment), and will contain several automatically generated files, of which two are important for our discussion: Default.aspx (the main web page for the application) and Default.aspx.cs (the code-behind file).

Default.aspx

The following listing shows the code that will have been generated for the Default.aspx file, with the additions you should make highlighted:

      <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"      Inherits="_Default" %>      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"      "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">      <html xmlns="http://www.w3.org/1999/xhtml"      > <head runat="server">          <title>Untitled Page</title>      </head>      <body>        <form  runat="server">        <div>        <asp:Label  Runat="server" Text="Enter Stock Symbol"></asp:Label>        <asp:TextBox  Runat="server"></asp:TextBox>        <asp:Button  Runat="server" Text="Get Quote"      OnClick="QuoteButton_Click" />        <br />        <asp:Label  Runat="server" Text="Latest Stock Price"></asp:Label>        <asp:TextBox  Runat="server"></asp:TextBox>        </div>        </form>      </body>      </html> 

That code defines a user interface comprising two labels, two text boxes, and a button. Actually, we didn't write the code by hand but generated that too from a UI design drawn using the web forms designer. You can design the form (which you'll see soon) or enter the preceding code as you see fit.

Default.aspx.cs

The code-behind file handles the button press, as shown in the following code. Again, the code you should enter is shown highlighted:

      public partial class _Default : System.Web.UI.Page      {        protected void QuoteButton_Click(object sender, EventArgs e)        {         StockQuoteApp.WebServiceProxies.StockQuoteService QuoteService = new             StockQuoteApp.WebServiceProxies.StockQuoteService();         QuoteService.UseDefaultCredentials = true;         StockPriceOutput.Text =            QuoteService.getQuote(StockSymbolInput.Text).ToString();        }      } 

A proxy to the StockBroker's StockQuoteService is created and its getQuote operation code invoked with the text supplied by the user in the StockSymbolInput text box; the result is displayed in the StockPriceOutput text box.

Test-running the StockQuoteApp web application

The functionality provided by the StockQuoteApp is pretty much identical to that provided by the autogenerated test form for the StockQuoteService, except that this time it's a proper client ASP .NET web application that you have designed and implemented.

Figure 2-10 shows what will happen if you enter a stock symbol and press the Get Quote button. Of course, the latest stock price will be different each time you run it.

image from book
Figure 2-10

Note that we have now completed the client-server pair of the StockQuoteApp ASP .NET web application and the StockBroker Web service.

The DealingApp implementation

As a Windows application, the DealingApp will be represented as a folder in the Solution Explorer, with generated files stored locally in the solution directory, so there will be no URL associated with this project. Only one file in this project requires further investigation, DealingForm.vb, which represents the application's main Windows Form.

Note

We renamed this form from its auto-generated name to make it more meaningful.

To complete the implementation of this application you'll need to open the file in design view and use the Windows Form designer to come up with something like what is shown in Figure 2-11.

image from book
Figure 2-11

The first text box (named StockSymbolInput) enables you to enter a stock symbol for which the user can obtain the latest price by pressing the button marked Get Latest Price (and named QuoteButton). The result is to be displayed in the second text box, named StockQuoteOutput.

Once the user has obtained the latest stock price, he or she can enter a number of shares into the third text box (named QuantityInput) and initiate a deal by pressing the Buy button (named BuyButton) or the Sell button (named SellButton).

Once you've designed the form, you'll need to add some code behind each of the buttons, which you can do easily by double-clicking each button in Design view.

DealingForm.vb code

The code behind each of the buttons should be as follows (note that in each case, one of the operations on one of the Web services of the StockBroker application is invoked):

      Public Class DealingForm        Private Sub QuoteButton_Click(ByVal sender As System.Object, ByVal e As      System.EventArgs) Handles QuoteButton.Click         Dim QuoteService As New DealingApp.StockQuoteService.StockQuoteService         StockQuoteOutput.Text = QuoteService.getQuote(StockSymbolInput.Text)        End Sub        Private Sub BuyButton_Click(ByVal sender As System.Object, ByVal e As      System.EventArgs) Handles BuyButton.Click         Dim DealingService As New DealingApp.DealingService.DealingService         MsgBox(DealingService.buyStock(StockSymbolInput.Text, QuantityInput.Text), ,      "Number of Shares Bought")        End Sub        Private Sub SellButton_Click(ByVal sender As System.Object, ByVal e As      System.EventArgs) Handles SellButton.Click        Dim DealingService As New DealingApp.DealingService.DealingService        MsgBox(DealingService.sellStock(StockSymbolInput.Text, QuantityInput.Text), ,      "Number of Shares Sold")        End Sub      End Class 

For the Buy and Sell buttons, the result is not written to an output text box but displayed in a pop-up message box with the title "Number of Shares Bought" or "Number of Shares Sold."

Test-running the DealingApp Windows application

For this application, we've already shown you what happens when it is run. Figure 2-11 showed not only the layout of the form, but also the data used to test the stock price functionality. When the user enters a number of shares—in this case, 100—the outcome will be a message box with the following information:

      Number of Shares Bought: 100 

or

      Number of Shares Sold: 100 

That completes the implementation of the second client application—this time a Windows application that demonstrates the end-to-end connectivity of the design. The application invokes an application-specific Web service, which delegates to a (third-party) business service, which in turn would write to the database if we had set one up.



Professional Visual Studio 2005 Team System
Professional Visual Studio 2005 Team System (Programmer to Programmer)
ISBN: 0764584367
EAN: 2147483647
Year: N/A
Pages: 220

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net