6 out of 13 rated this helpful - Rate this topic

Using .NET to Implement Sun Microsystems' Java Pet Store J2EE BluePrint Application

 

Microsoft

Version 2.0

October 2002


Download Petshop.msi.

Contents

Abstract
Comparison of Lines of Code Required
Introduction
Overview of Java Pet Store
Functional Walkthrough
The Microsoft .NET Pet Shop
Comparing the Code Size
XML Web Services
Conclusion
Appendix 1: Counting the Lines of Code

Abstract

The original purpose of this study was to take Sun's®'primary J2EE BluePrint application, the Sun Java Pet Store, and implement the same functionality using Microsoft .NET. Based on the .NET version of Sun's J2EE best-practice sample application, customers could directly compare Microsoft .NET to J2EE-based application servers across a variety of implementations. In addition, the study compared the architecture and programming models of each platform to evaluate relative developer productivity.

In addition to the original purpose, .NET Pet Shop has now been extended to demonstrate how to implement distributed transactions in .NET. In addition to distributed transactions, there is also a demonstration of the .NET Data Cache API, some examples of Server Controls, and an example of extending the ASP.NET repeater control as an alternative to DataGrids.

Source code to the Java Pet Store application is publicly available at the Java 2 Platform Enterprise Edition BluePrints Web site.

Comparison of Lines of Code Required

ms954626.psimp1(en-us,MSDN.10).gif

Figure 1: Lines of Code Comparison

Introduction

The .NET Pet Shop was first published in November 2001 to demonstrate a best practices architecture when developing .NET applications. A secondary goal was to compare and contrast the .NET best practices with those put forward by Sun for developing J2EE applications. Two metrics were chosen for this comparison and these were performance, how fast does the application respond to user requests under load, and lines of code to develop the application.

The lines of code metric was chosen to try and measure the productivity of developers creating the application and how easy it is to maintain the application. This may seem a little arbitrary given automatic code generation in some IDEs but should a developer want to make modifications to an application then they will need to look at and understand all the code in the application. Another reason this metric has relevance is that in general application contain less bug and perform better the fewer the lines of code they have.

After four weeks of development a team of two software engineers had taken the functional features of Sun's Java Pet Store and created a functionally equivalent application using the Microsoft .NET framework. They had accomplished this in a quarter of the lines of code of the original Sun version and when tested in a lab, was over 10 times faster than a tuned version published earlier in the year by Oracle.

Having shown the advantages of developing an application in the .NET framework we wanted to extend the .NET Pet Shop to demonstrate some more aspects of .NET. The main feature we wanted to demonstrate was how to implement a distributed transaction in .NET by using Enterprise Services. We have also added some examples of data caching.

Learn more about implementing database transactions in Implementing Database Transactions with Microsoft .NET.

Overview of Java Pet Store

The Java Pet Store is a reference implementation of a distributed application according to the J2EE BluePrints maintained by Sun Microsystems. The Java Pet Store was created by Sun to help developers and architects understand how to use and leverage J2EE technologies, and how J2EE platform components fit together. The Java Pet Store BluePrint includes documentation, full source code for the Enterprise Java Beans™ (EJB) architecture, Java Server Pages (JSP) technology, tag libraries, and servlets that build the application. In addition, the Java Pet Store BluePrint demonstrates certain models and design patterns through specific examples. The Java Pet Store is a best-practices reference application for J2EE, and is redistributed within the following J2EE-based application server products:

  • IBM® Websphere® 4.0
  • BEA® WebLogic® 6.1 & 7
  • Oracle® 9i Application Server
  • Sun Microsystems iPlanet®

The full Java Pet Store contains three sample applications:

  • Java Pet Store, the main J2EE BluePrints application.
  • Java Pet Store Administrator, the administrator module for the Java Pet Store.
  • BluePrints Mailer, a mini-application that presents some of the J2EE BluePrints design guidelines in a smaller package.

The Java Pet Store application is designed as a J2EE "best-practices" application. The application provides an emphasis on the features and techniques used to show real world coding examples.

Functional Walkthrough

Java Pet Store is an e-commerce application where customers can buy pets online. When the application is started, users can browse and search for various types of pets.

A typical session using the Java Pet Store is as follows:

  • Homepage - the main page that loads when the user first starts the application.
  • Category View – There are five top-level categories: Each category has several products associated to it.
  • Products – When a product is selected within the application, all variants of the product are displayed. Typically the product variant is either male or female.
  • Product Details – Each product variant (represented as items) will have a detailed view that displays the product description, a product image, price, and the quantity in stock.
  • Shopping Cart – Allows the user to manipulate the shopping cart (add, remove, and update line items).
  • Checkout – displays the shopping cart in a read-only view.
  • Login Redirect – When the user selects Continue on the checkout page, they are redirected to the login page if they have not signed in yet.
  • Verify Sign in – After being authenticated for the site, the user is redirected to the credit card and billing address form.
  • Confirm Order – billing and shipping addresses are displayed.
  • Commit Order – the final step in the order-processing pipeline. The order is now committed to the database at this point.

The Microsoft .NET Pet Shop

The goal of the .NET Pet Shop was to focus on the Java Pet Store application itself (the administration and mailer component were not ported to .NET in this implementation). In addition to reproducing the functionality of the Java Pet Store application, two additional objectives were added:

  • Compare and contrast the architecture, programming logic and overall code size of this best-practice application between the .NET and J2EE implementations. This information is contained within this document.
  • Provide performance benchmark data on how well each application performs at varying user loads. This information is summarized in this document.

ms954626.psimp2(en-us,MSDN.10).gif

Figure 2: The Microsoft .NET Pet Shop

The logical architecture of the .NET Pet Shop is detailed in Figure 3.

There are three logical tiers: the presentation tier, the middle tier, and the data tier. The tiers allow for clean separation of the different aspects of a distributed application. The business logic is encapsulated into a .NET Assembly (implemented as a C# Class Library).

The database access is funneled through a class that handles all interaction with the SQL Server Managed provider. In the original version of the .NET Pet Shop, access to the data stored in the database was accomplished through stored procedures. Although this architecture is the best way to access data in SQL Server, it was decided to convert the application to use dynamic SQL from the middle tier. The application represents a complete logical three-tier implementation using .NET and illustrates coding best-practices for the Microsoft .NET platform.

ms954626.psimp3(en-us,MSDN.10).gif

Figure 3. .NET Pet Shop Logical Architecture

ms954626.psimp4(en-us,MSDN.10).gif

Figure 4. Sample .NET Pet Shop Physical Deployment Diagram

What is new in Version 2.0

Many changes have been made to .NET Pet Shop since its original creation in October 2001. The main piece of new functionality is the inclusion of distributed transactions using .NET Enterprise Services and the Microsoft Distributed Transaction Controller (MS DTC). Here is a list of all the key changes that have been made to the application.

  • Enterprise Services
  • Inline SQL in the middle tier
  • Data caching
  • Use of custom server controls

One of the most obvious changes is the move from stored procedures in the database to inline SQL in the middle tier. This change was made to demonstrate that the .NET Pet Shop and the .NET framework can perform equally well using middle tier SQL as opposed to stored procedures. One of the main reasons for the small performance difference between the two different database access approaches is that in the .NET Pet Shop the stored procedures wrapped simple database calls only. To ensure that the only performance benefit from the stored procedure was in the precompiled execution plan, no business logic was placed in the stored procedures. SQL Server caches all execution plans for queries, and since the .NET Pet Shop uses parameterized queries, the SQL Server engine will be able to use the execution plan cache.

Another important change is that, internally, the .NET SQL Server Data Provider uses the sp_executesql stored procedure when executing SQL statements which again takes advantage of cached execution plans. Best practices would still highly recommend the use of stored procedures for database access. In many cases there are real performance benefits from using stored procedures and it also provides an excellent way to encapsulate your database access. It allows database administrators to ensure that database access is properly tuned, because the database administrators have access to the exact SQL code that will run in the database.

Data caching has been added to demonstrate caching at multiple levels in the application. You can output cache the ASP.NET page itself, in this case the page rendering is cached on the web server based on properties such as the query string and post parameters.

It is also possible to cache data from the middle tier. Using the Data Cache API you can store the results of a middle tier method in the web tier. This allows you to store non-volatile data from the middle tier and provide un-cached fully dynamic pages in the web tier. It is also possible to use a combination of both caching techniques however we decided to just use data caching in this case.

Architecture of the Application

The previous section addressed the high-level architecture of the application. This section will walkthrough a section of the code to gain a better understanding of how the application works. This will demonstrate the interaction between the presentation tier, the middle-tier, and the data tier. To further illustrate the design, we will take a detailed look at the interaction and implementation details at each tier for the shopping cart as shown in Figure 5.

In designing n-tier applications, there are a variety of approaches. In implementing the .NET Pet Shop, a data-driven approach was used.

ms954626.psimp5(en-us,MSDN.10).gif

Figure 5. Architecture Walkthrough

Database

The database for the Java Pet Store is available in several database vendor formats. The first step taken was to port the Java Pet Store database schema to SQL Server 2000. This required no changes from the Sybase version of the schema. The database has the following overall structure of tables:

Table NamePurpose
AccountRepresents basic customer information
BannerDataStores the ad banner information
CategoryThe catalog categories (i.e. Fish, Dogs, Cats, etc)
InventoryProduct inventory status
ItemIndividual product details
LineItemOrder details
OrdersThe orders placed by the customer. An order contains 1 or more line items
OrderStatusOrder status
Productatalog products. Each product may have one or more variants (Items). A typical variant is usually male or female.
ProfileCustomer user profile
SignonLogin table for customers
SupplierInformation concerning fulfillment suppliers

Table 1. Database Table Names

The complete physical database schema for the .NET Pet Shop is illustrated in Figure 6.

To demonstrate distributed transactions in .NET we decided to split the schema across two physical databases. The account, products and inventory data was left in the first database while the order related tables were moved to a second database. This can be seen in Figure 7. This means that the Place Order scenario the system now needs to modify data in two databases. The Order, OrderStatus, and LineItems data needs to be inserted into the second database and then the inventory tables need to be updated based on the products quantities purchased. As this is an atomic operation we needed to use the Microsoft Distributed Transaction Controller to ensure that either both databases commit their changes or neither database commits their changes.

ms954626.psimp6(en-us,MSDN.10).gif

Figure 6. .NET Pet Shop Physical Database Schema

ms954626.psimp7(en-us,MSDN.10).gif

Figure 7. Pet Shop schemas in the Distributed Transaction Scenario

The Sun Java Pet Store makes heavy use of Bean Managed Persistence (BMP) in its middle-tier Enterprise Java Beans (EJB). Essentially, this provides objects a mechanism to persist their state to the database. The .NET Pet Shop takes a different approach. The middle-tier components make specific database calls for each business method invoked. Version two varies from version one in that for .NET Pet Shop Version 2, we have moved the SQL code to the middle tier rather than residing in the database as stored procedures. Using stored procedures at the database level is well established as a best practice for distributed applications. It provides a cleaner separation of code from the middle-tier and also helps clarify the transaction context and scope. In the original Pet Shop the stored procedures had only contained basic queries; with all the business logic kept in the middle tier .NET classes. With the new version of Pet Shop, we wanted to show that the performance of the application did not originate from the use of stored procedures, and that the underlying .NET framework used in the web and middle tiers was the source of the .NET Pet Shop's superior performance.

Version 1 of the .NET Pet Shop used the OpenXML feature of SQL Server 2000 and was used to return XML documents instead of traditional rowsets. This was relied upon heavily in the order checkout process, because it simplified the number of parameters to be managed between the middle-tier component and the database stored procedures. With the move to the distributed database model and away from stored procedures, the architecture of the application was changed to use simple SQL queries. With the stored procedure model, we would recommend the use of OpenXML in your applications.

Middle-Tier

Sun uses Enterprise Java Beans (EJBs) to implement the business logic of the application. Sun implemented the application using a mix of Entity and Session Beans to handle all of the logic.

EJB NameEJB Type
AccountEntity Bean
InventoryEntity Bean
OrderEntity Bean
ProfileMgrEntity Bean
ShoppingCartStateful Session Bean
ShoppingClientControllerStateful Session Bean
AdminClientControllerStateless Session Bean
CatalogStateless Session Bean
CustomerStateless Session Bean
MailerStateless Session Bean

Table 2. Java Pet Store Business Logic

The .NET Pet Shop middle-tier business logic is encapsulated into a single .NET Assembly containing multiple C# clases. The namespace is called Pet Shop.Components as illustrated in Figure 8.

ms954626.psimp8(en-us,MSDN.10).gif

Figure 8. Middle-Tier Component Class View and Solution Explorer File View

There are eight core classes, each one is implemented in its own .cs file.

Class NamePurpose
AccountAccount management and login verification.
CartShopping cart functions.
CartItemA line item in the Shopping cart.
DatabaseADO.NET data access using the SQL Server Managed Provider.
ItemRepresents a product variant.
OrderCOMOnline orders transactions using Enterprise Services
OrderWebServiceA class to access the Order information for the Web Service. (This does not required Enterprise Services and hence is in a separate class)
ProductA product in the catalog.

Table 3. Key Middle-Tier components

All middle-tier code is compiled into a single assembly. The code-behind logic for the web tier is compiled into a separate assembly.

For the code walkthrough, we will examine the shopping cart functionality for Java and .NET, starting with the Java Pet Store.

The ShoppingCart EJB is a Stateful Session Bean, meaning the object maintains its contents for a specific amount of time on the server while the client is making a request. One common task of any shopping cart page is to add items to the user's basket. Before adding an item, the application must first determine which product is being added. In order to get the product information we will take a look at CatalogDAOImpl.java:

public Product getProduct(String productId, Locale locale) throws
       CatalogDAOSysException 
{
        String qstr =
            "select productid, name, descn " +
            "from " +
            DatabaseNames.getTableName(DatabaseNames.PRODUCT_TABLE, locale) +
            " where " +
            "productid='" + productId + "'";
        Debug.println("Query String is:" + qstr);

        Product product = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            getDBConnection();
            stmt = dbConnection.createStatement();
            rs = stmt.executeQuery(qstr);
            while (rs.next()) {
                int i = 1;
                String productid = rs.getString(i++).trim();
                String name = rs.getString(i++);
                String descn = rs.getString(i++);
                product = new Product(productid, name, descn);
            }
        } catch(SQLException se) {
            throw new CatalogDAOSysException("SQLException 
            while getting " +
                        "product " + productId + " : " + se.getMessage());
        } finally {
            closeResultSet(rs);
            closeStatement(stmt);
            closeConnection();
        }
        return product;
}

Code Snippet from the Java Pet Shop

public static IList GetProductsByCategory(string category) {

   IList productsByCategory = new ArrayList();

   SqlParameter parm=new SqlParameter(PARM_CATEGORY, 
      SqlDbType.Char, 10);
   parm.Value = category;

   using (SqlDataReader rdr=Database.ExecuteReader(Database.CONN_STRING1,
                        CommandType.Text, 
               SQL_SELECT_PRODUCTS_BY_CATEGORY, parm)) {
      while (rdr.Read()){
         Product product = new Product(rdr.GetString(0),
             rdr.GetString(1), rdr.GetString(2));
         productsByCategory.Add(product);
      }
   }

   return productsByCategory;
}

Code Snippet for .NET Pet Shop

Note that .NET version is making a call to ExecuteReader(). This is a method in our reusable Database class and in this case will execute a dynamic SQL statement returning a SqlDataReader (very similar to a read-only, forward-only cursor in ADO). We also make use of the using keyword, which will automatically call dispose on the SqlDataReader object at the end of the code block.

public static SqlDataReader ExecuteReader(string connString, 
         CommandType cmdType, string cmdText, params SqlParameter[] cmdParms) {
   SqlCommand cmd = new SqlCommand();
   SqlConnection conn = new SqlConnection(connString);

   try {
      PrepareCommand(cmd, conn, null, cmdType, cmdText, cmdParms);
      SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
      cmd.Parameters.Clear();
      return rdr;
   }
   catch {
      conn.Close();
      throw;
   }
}

Code Snippet from .NET Pet Shop Data Tier

The snippets of code for the .NET Pet Shop are essentially the skeleton for all data access in the application. The Java application data access mechanisms vary from EJB to EJB. There are some sessions objects, but for the most part the components are bean-managed, meaning that the object itself is responsible for persisting itself to the database, hence the inline SQL code.

The .NET Pet Shop is using ASP.NET Session state to store the contents of the shopping cart (matching the functionality of the Java Pet Store). The session state is stored in-process, but ASP.NET also includes the ability to run a dedicated State Server and supports SQL Server database session state as well. This becomes important when you want to create a clustered web tier for redundancy and scalability. By storing the Session state in a dedicated state server or in a SQL Server database the session data can be shared amongst the various servers running the application.

Presentation-Tier

The presentation-tier for the Pet Shop was written using ASP.NET Web Forms combined with User Controls. The site was created with Visual Studio .NET and therefore uses code-behind where the code for each ASPX page is encapsulated into a separate file. The Java Pet Store makes heavy use of Servlets (or mini java-server programs that emit HTML). The Servlets are using a design pattern called the Model View Controller, allowing the data to be displayed and manipulated in several different ways. The .NET Pet Shop accomplishes this same functionality using the ASP.NET Server Controls in addition to the User Controls.

Since the .NET Pet Shop application makes uses of Server Controls and Session State, careful consideration was given to their parameters to achieve high performance. The configuration is detailed in Table 4. To ensure high performance, ViewState and SessionState were turned off for the entire web application using the web.config file, and then enabled in the pages that required these features.

ASP.NET WebFormsEnableSessionStateEnableViewState
ShopppingCart.aspxTrue True
Category.aspxFalseFalse
CheckOut.aspxFalseFalse
CreateAccount.aspxTrueFalse
Default.aspxFalseFalse
EditAccount.aspxTrueTrue
Error.aspxFalseFalse
Help.aspxFalseFalse
OrderAddressConfirm.aspxFalseFalse
OrderBilling.aspxTrueFalse
OrderProcess.aspxFalseFalse
OrderShipping.aspxTrueFalse
Item.aspxFalseFalse
ItemDetails.aspxFalseFalse
Search.aspxFalseFalse
SignIn.aspxTrueFalse
SignOut.aspxFalseFalse

Table 4. WebForm Session State and View State settings. These settings are included as 1-line directives at the top of the individual aspx files.

Caching

One of most effective ways to improve the performance of a database driven application is to eliminate accessing the database for every query. ASP.NET offers a variety of caching mechanisms that add considerable performance benefits to the application. The two foremost ways to use caching in ASP.NET are output caching and data caching.

Output caching takes the response from an ASP.NET web page and stores the page in a cache while the data cache is designed to work between the web tier and the middle tier and caches the data from middle tier methods, or the results of database calls in the case of two tier apps. The first .NET Pet Shop distribution was offered in an output-cached version and a non-cached version. With this version, we have removed all output caching and added data caching. This means that each web request results in a new page rendering.

ASP.NET Output Caching

Output caching is used to capture the contents of a page and store the results in memory. Subsequent requests for that page are served from the cache and do not require accessing the database. The Java Pet Store does not have a way to do this easily. While various J2EE application servers have output cache capabilities (for example, IBM Websphere 4.0 and BEA Weblogic Server), these features vary from product to product. Using these features may require modifying the Java Pet Store source code to work with a given J2EE application server.

The original .NET Pet Shop application (version 1.5, available at http://www.gotdotnet.com/team/compare/petshop.aspx) also used Partial Page (Fragment) Caching to cache various regions of page. For instance, the header information that appears on the top of every page is cached. However, the header information is dependent on the user signing in (so two different versions of the page have to be cached). ASP.NET easily allows this by using the VaryByCustom attribute on the OutputCache directive. Using VaryByCustom requires overriding the GetVaryByCustomString method to get a custom cache for the header.

ASP.NET Data Caching

The data cache (Cache API) allows you to store the results of a method call or database query in the internal caching engine with the .NET Framework. Since you have gone further through the application pipeline, the data cache may not offer the same performance boost that Output Caching yields. However, it does offer a good compromise between fully dynamic pages and reducing the load on the database by storing nonvolatile data in the middle tier. For example you may want to display the same piece of data differently in two web pages.

// Check the cache to see if the product data is in the cache
// If it is in the cache then use the cached copy otherwise fetch
 it from the // middle tier components 
if(Cache[Request[catKey]] != null){
products.DataSource = (IList)Cache[Request[catKey]];
}else{
IList productsByCategory = null;
productsByCategory = Product.GetProductsByCategory(Request[catKey]);
Cache[Request[category]] = productsByCategory;
products.DataSource = productsByCategory;
}

ASP.NET Data Cache Code Snippet

The sample code above shows how you would access the ASP.NET cache API and retrieve information from the cache. The example is based on the category query in the Pet Shop application where a user can select one of the five predefined categories of Pet and view of list of animals in the category. The first thing the code does is check to see if the data has already been cached by using the category id as a key to look up an element in the data cache, if this element does not exist (the data has not yet been cached), it will return null. If the element exists, the data from the cache is pulled and cast to the appropriate type. If the data is not in the cache, the standard mechanisms are used to pull the data from the middle tier objects.

Caching Options in ASP.NET

Type of CachingBenefitsLimitations
Output CachingOffers best performance

Entire page output is cached

Simple to implement

Entire page output is cached

Limited to time invalidation

Fragment Caching

(Cache user controls)

Different user controls on a page can have different cache timeouts

Cached controls can be shared across pages

Need to cache each user control individually

Limited to time invalidation

Cache APICache raw data rather than data and presentation

More control over what is cached

Cached data can be shared throughout web application

Finer control over the cached data. The Cache API provide ability to specify cache priorities, dependencies and callback functions to invalidate the cache from external applications

Need to go further into application pipeline before you can take advantage of cached data.

ASP.NET Cache Monitoring

There are several ways to monitor what is happening in the ASP.NET Caching System. The foremost method is to use Perfmon but you can also use a SQL Server trace to check when database access is occurring or not occurring as the case may be. To monitor the cache in Perfmon, select the Output Cache Entries and Cache API Entries counters under the ASP.NET Application performance object and add them to the Perform graph. A sample graph is shown below, see Figure 9. It is also possible to monitor the turnover rate and the hit rate within Perfmon to detect whether the item is being used in the cache.

ms954626.psimp9(en-us,MSDN.10).gif

Figure 9. Using Perfmon to Monitor ASP.NET Caching

Error Handling

The error handling in the .NET Pet Shop has been simplified by using custom errors for ASP.NET. All thrown exceptions are now being caught in the Application_Error() method in the Globabl.asax.cs file.

/// <summary>
/// Global application level error handling. This method is invoked 
/// anytime an exception is thrown. 
/// </summary>
/// <param name="sender">Sender</param>
/// <param name="e">Event arguments</param>
private void Application_Error(object sender, System.EventArgs e) {
string err = "Microsoft .NET PetShop Application Error\n\n";
   err += "Request: " + Request.Url.ToString() + "\n\n";
   err += "Strack Trace: \n" + Server.GetLastError().ToString();

   // write the error message to the NT Event Log
   Components.Error.Log(err);
} 

This allows the Pet Shop to have a global application-level error handling. If an error occurs, the user is directed to a default error page (Error.aspx). The full stack trace and requested URL that generated the error is then written to the Application Event Log for the system administration, preventing the end user from seeing an unhanded exception error in the browser.

Security

Both the Java Pet Store and the .NET Pet Shop leverage a variety of security mechanism to prevent break-ins and attacks. The .NET Pet Shop uses ASP.NET Forms-based Authentication. These settings are centralized in the web.config file:

<!--   AUTHENTICATION 
       This section sets the authentication policies of the application.   
       Possible modes are "Windows", "Forms", "Passport" and "None" 
-->
<authentication mode="Forms">
    <forms name="Pet ShopAuth" 
           loginUrl="SignIn.aspx" 
           protection="All" 
           path="/" />
</authentication>

The Java Pet Store exhibits similar functionality, but security meta data is expressed in Web component deployment descriptors:

<web-app>
  <login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
      <form-login-page>login.jsp</form-login-page>
      <form-error-page>login.jsp</form-error-page>
    </form-login-config>
  <login-config>
<web-app>

The security behavior of the Java Pet Store and the .NET Pet Shop are the same: ASP.NET allows the entire security configuration to be centralized into one configuration file while the Java version has several configuration files.

Debugging

During the development of the .NET Pet Shop, we discovered bugs easily with the Visual Studio .NET integrated debugging. Before we could debug, we needed to ensure that our web.config had the debug attribute in the compilation element set to true.

<compilation defaultLanguage="c#" debug="true" />
   

Here is a typical debugging session for the Search.aspx WebForm. We have set a breakpoint right before we are going to do our data binding. You can also note that the input search text in this session was dog (see the lower left hand side of the screenshot).

ms954626.psimp10(en-us,MSDN.10).gif

Figure 10. Debugging in Visual Studio .NET

Comparing the Code Size

It is interesting to compare the overall lines of implementation code in the two versions of the application to get an understanding of the relative developer productivity in Microsoft .NET versus Sun's J2EE development platform. A comprehensive code-count reveals that the lines of code required to implement the Java Pet Store is over 5 times the amount of code required to implement the same functionality in the .NET Pet Shop. The following tables give a more complete break down by tier.

ms954626.psimptbl1(en-us,MSDN.10).gif

Table 5. Lines of code broken down by tier.

ms954626.psimp11(en-us,MSDN.10).gif

Figure 11. Lines of code broken down by tier.

The mechanism used to perform the code count is detailed in Appendix 1.

Why the .NET Code Base is much Smaller and More Efficient

The Java Pet Store contains several complex design patterns that result in making the J2EE BluePrint application very challenging for developers to reuse. The Java Pet Store takes a complete object-oriented approach which results in very heavy middle-tier objects. The use of the J2EE-recommended bean managed persistence and other EJB functionality adds to the complexity of the design. The .NET Pet Shop takes a streamlined component approach with very small, light-weight objects that take advantage of several .NET features that significantly reduce the overall code size and increase developer productivity. For example, the use of ASP.NET Server Controls and ASP.NET Web Forms help reduce the server-side and client-side programming burden on developers significantly. In addition, the Java code has to manually update pages using its Model View Controller design pattern as opposed to the .NET code that uses DataBinding with ASP.NET Server Controls like the DataGrid.

On the data tier, the core database schema (the tables and all of the relationships and constraints) are virtually identical for both versions of the application. In both, the schema is roughly 400 lines of SQL code.

XML Web Services

Using Visual Studio.NET, we quickly added an XML Web Service (based on the SOAP and UDDI standards) that returns the order details given an order ID. The sample XML output of the GetOrderDetails() SOAP method in OrderWebService.asmx Web Service is shown in Figure 12.

ms954626.psimp12(en-us,MSDN.10).gif

Figure 12. Results from .NET Web Service Call

Conclusion

The Java Pet Store is Sun's reference BluePrint application for building enterprise Web applications with the J2EE technology. The .NET Pet Shop is a BluePrint application that serves to highlight the key Microsoft .NET technologies and architecture that can also be used to build enterprise Web applications. Now architects and developers can compare .NET and J2EE side by side using functionally identical reference applications that illustrate best coding practices for each platform.

Appendix 1: Counting the Lines of Code

We were very careful to count Java Pet Store code only for the precise functionality implemented in the .NET Pet Shop application. Lines of code for the Administration functionality and the BluePrint Mailer application were not counted, since this functionality was not included in the .NET Pet Shop. In addition, we factored out code in the Java Pet Store used for supporting databases other than Oracle. To come up with line counts for both the Java and .NET versions of the code, we created a program that looks only at those lines considered important in each file. For instance, to count the lines of code in a file containing C# or Java code, we wanted to ignore blank lines and lines containing comments.

Table 6 describes in more detail what lines where counted in which types of files.

File typeWhich lines were counted
.csAny line containing C# code
.javaAny line containing Java code
.jsAny line containing JavaScript code
.asax, .aspxAny line containing server-side code (C#)
.jspAny line containing server-side code (Java)
.sqlAny line containing SQL code

Table 6. Lines of code counted

In addition, for .asax, aspx, and .jsp files, if more than one server-side block (delimited by "<%" and "%>") appeared on the same line, each was counted as a separate line. For all other file types (e.g. .xml), all lines were counted. The line counting program was written as a lexical specification for lex, a readily-available lexical analyzer and code generator. In our case, we used flex, the GNU equivalent whose source code is freely available from the Free Software Foundation. Either can be used to produce a C source file from the specification file. The C file can, in turn, be compiled into an executable. A makefile for VC6 and VC7 is included in the distribution.

The usage of the program is quite simple. It accepts zero, one, or two command line arguments, depending on what kind of file is to be counted and whether the file to be counted is specified on the command line or piped in from another source. Table 7 describes the accepted command line arguments and how they are intended to be used.

ArgumentEffectIntended file types
(none)Assumes file contains a mixture of HTML and server-side code.asax, .aspx, .jsp
-allCounts all linesAll others (e.g. .html, .xml, and .txt)
-codeCounts only lines of code.cs, .java, .js
-sqlCounts only lines of SQL code.sql

Table 7. cloc command line arguments

Since the line counting program accepts no more than one file at a time, we also created a collection of batch files to help count all of the lines in all of the directories for both the Java and .NET versions. These files are also included in the distribution.

In our makefile, we decided to have flex produce a C source file with a .cpp extension. Since VC compiles files such as C++, this allowed us to use the bool type and gave us better type safety. However, it also expects an include file called unistd.h. This is a standard include file on many systems but is not part of Visual C++. This file does not contain any declarations relevant to our line counting tool, so using an empty file is fine.

If you would like to reproduce our line count results, you may run the batch files yourself. The first one, Extensions Used.bat, produces a listing of the file extensions used in a directory hierarchy. The path of the top-level directory of the directory hierarchy is specified as the only command line argument. Files without extensions do not show up in the listing, but there are no files without extensions we needed to count. This batch file was run on the Java and .NET versions to determine which file extensions each used. Table 8 shows the file extensions found in each version the extensions used to compute the total line counts for each.

PlatformExtensions countedExtensions not counted
Javajava, js, jsp, sql, tld, txt, xmlbat, html, mf, sh
.NETasax, ascx, aspx, config, cs, sql, txtbat, cmd, css, html, gif, jpg, resx, vbs, vsdisco

Table 8. Extensions

The other two batch files, Count Java Lines.bat and Count .NET Lines.bat, count the number of lines in the files in the Java and .NET versions, respectively. These are separate batch files since the extensions those batch files looks for are different, as shown in Table 8. Both batch files take a single command line argument (the path of the top-level directory of the directory hierarchy) to search for files to count.

To get the line counts for the different tiers, we ran the batch files on specific subdirectories and only included specific extensions, as shown in Table 9.

ms954626.psimptbl2(en-us,MSDN.10).gif

Table 9. Final code breakdown

Determining a satisfactory line count across different file types is difficult enough without also attempting to count across different platforms. For instance, we did not count HTML files, because the tools used to generate them may format the code differently on different platforms, thus producing different line counts. Although this also applies to how the logic tier files are formatted, it is certainly illuminating that the difference in the line counts between the java files and the cs files is as large as it is. These numbers reveal the amount of infrastructure in the .NET platform in place to help developers concentrate on their problem domain, instead of concentrating on accounting for a lack of infrastructure.

We are required by the Sun Java Pet Store License to include the following legal information regarding the Java Pet Store application:

Copyright 1999-2001 Sun Microsystems, Inc. ALL RIGHTS RESERVED

Redistribution and use in source and binary forms, with or without modification,

are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

-Redistribution in binary form must reproduct the above copyright

notice, this list of conditions and the following disclaimer in the

documentation and/or other materials provided with the distribution.

Neither the name of Sun Microsystems, Inc. or the names of contributors

may be used to endorse or promote products derived from this software

without specific prior written permission.

> >

This software is provided "AS IS," without a warranty of any kind. ALL

EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,

INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A

PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN

AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY

LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE

SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR

ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR

FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR

PUNITIVE DAMAGES,HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF

LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE,

EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

> >

You acknowledge that Software is not designed, licensed or intended

for use in the design, construction, operation or maintenance of

any nuclear facility.

Did you find this helpful?
(1500 characters remaining)
© 2013 Microsoft. All rights reserved.