Sample App : Understanding the Storefront Developer Sample
Contents |
Introduction
An online storefront is a web application that lets users browse through a retail catalog and buy products. It generally provides:
- A way to explore a hierarchy of categories and subcategories
- A search function
- A way to view detailed product information
- A shopping cart
Through these common features, the storefront is also an important generic web application design pattern. It is widely used, and has been implemented on many major web platforms. Finally, the storefront is a data-driven application, requiring thorough development of all layers of a three-tier web application—client, middleware, and database. The Bungee Storefront developer sample shows you how Bungee Connect integrates these layers and provides a rich and compelling experience for both users and developers.
This wiki entry is a guide to the Storefront application. You can try the latest deployed version at http://testdeploy.bungeeconnect.com/storefront.
![]() |
You can also import the project as a developer sample to take a closer look at the source code, modify the code, or extend the application with new functionality. To do so, you need a Bungee Developer account, which you can create at https://builder.bungeeconnect.com.
In this article, you learn how to do the following in Bungee Connect:
- Create a rich user interface
- Use DynamicForms to swap visual elements at runtime
- Take advantage of Bungee's advanced AJAX capabilities
- Create a data-driven web application
- Structure the user-interface code, the application logic, the data interface, and the database
- Create and connect to a sandboxed MySQL database hosted by Bungee Connect
The Requirements for an Online Storefront
- Client tier
- A well-designed storefront, like a physical store, makes shopping pleasant and easy. Users should be able to:
- Find specific products quickly.
- Browse and evaluate many products easily.
- Save selected items in a shopping cart.
- A well-designed storefront, like a physical store, makes shopping pleasant and easy. Users should be able to:
- Middleware tier
- The middleware, or server tier is the heart of a web application. It runs the application's business logic and serves data to the client. Good design practice dictates that the middleware must:
- Provide a fast and responsive experience for storefront customers, ensure safety against hackers, and have low downtime. In an e-commerce application, safety and reliability are particularly important, and in most web technologies, particularly difficult to ensure.
- Be extensible for the storefront to be scalable. It should be able to grow to meet any level of user demand while keeping all of the previous requirements.
- Be maintainable. The middleware code, which holds the application together, should keep configuration and "plumbing" code to a minimum, and each component must have well-defined, modular interface.
- The middleware, or server tier is the heart of a web application. It runs the application's business logic and serves data to the client. Good design practice dictates that the middleware must:
- Data tier
- The data tier delivers an application's content. In a real-world storefront application, the data tier has to accommodate all three database access patterns: read-only, read-mostly, and read-write. Read-only data, such as product and category descriptions, are read often and have to be quickly searchable. Read-mostly, such as product inventory, have to be quickly searchable but also, sometimes, securely updated. Finally, read-write data, like user account and shopping cart information, has to be secure and robust as it's being accessed and changed.
The Bungee Storefont
Bungee Connect provides an elegant way to meet the requirements of an online storefront. Bungee Connect lets you visually design the application's user interface, integrate it with application logic, and connect to data sources—with nothing but a web browser. Some difficult problems in most web application development projects, such as deploying efficiently, ensuring a responsive user experience, and guarding against unplanned downtime, are solved automatically through the Bungee Grid server architecture. Bungee lets you focus on high-level application design.
The design of the Storefront application is outlined below, in four layers:
-
User interface: The connection between the middleware and the client
-
Application logic: The functionality that the application provides
-
Data wrapper: The connection between the middleware and data layer
-
Database: The Storefront's integrated SQL database
User Interface
Rich, Interactive AJAX Interface
AJAX varies widely from technology to technology in terms of power and ease of implementation, and the two usually oppose each other. In Bungee Connect, complete interactivity is built into every control. Controls are bound declaratively to data, and updates—across controls, panels, and even browser windows—are fully automatic.
Familiar UI Design Pattern
The Storefront displays hierarchically structured data with a tree view on the left of the page and data and detail views to the right, implementing a common UI design pattern that many users have experience with.
- The tree view lets users browse through categories.
- The data view lets them browse all products in the selected category or search for products.
- The detail view displays a description and thumbnail image for the selected product, and lets users add or remove products from the shopping cart.
The general pattern is common to many applications that let users browse large sets of data, including Windows Explorer and Bungee's WideLens reference application.
Static and Dynamic Form Interfaces
Bungee Connect uses forms to visually represent classes. Each class can have many forms, and visual elements displaying instances of a class specify which form to use with a form interface. They can do this either statically or dynamically.
With a static form, the elements that the form contains will stay the same, but their content will still update automatically if the class instance that the form is bound to changes, or if the binding changes to a different instance. For example, the Storefront uses a static form interface to display the product detail view. Each time a new product is selected, the view updates, but the view's controls and layout stay the same.
With dynamic form interfaces, the form used to display an object is chosen at runtime. For example, the Storefront uses a dynamic form interface to display the tabbed product data view, letting the user switch between browsing by category and searching for products by keyword. The DynamicForm is bound to the currentTab element of MainClass. This element will have either an instance of SearchTab or of CategoryTab, depending on which tab index is selected, and uses a custom DynamicFormInterface to find the appropriate FormInterface. Both SearchTab and CategoryTab contain a DynamicFormAdapter, which interfaces with the DynamicFormInterface and specifies which form to use. The Storefront also uses a DynamicForm to toggle between the "Add to cart" button in the detail view and the "Remove from cart" button with an input controlling the cart quantity. In this case, the DynamicForm is bound to a ProductCartItem instance, and the corresponding DynamicFormInterface returns either the AddToCartInterface or a ChangeQuantityInterface, depending on whether the quantity is greater than zero.
Modular UI Design
UI design is simplified by factoring out and re-using common controls. For example, Storefront's SearchTab and CategoryTab both use PaginatedProductList, which provides a form to navigate and view pages of products. Separating complex controls into smaller controls and re-using the parts has several advantages. First, it simplifies development by splitting difficult tasks into more manageable modules. Second, it makes applications more consistent, since the same functionality is always provided by the same controls. Lastly, control re-use makes applications easier to modify, since it usually ensures that a single modification won't have to be implemented in more than one place.
Customization
Bungee Connect offers many ways to add custom functionality to controls through its Model-View-Interface UI architecture. In this model, each control is bound to an underlying data field with a control interface. A TextBox, for example, uses a control interface to connect to a string field representing its text. Many controls have interface settings in addition to the one connecting them to their main data source.
The drag-and-drop interface, for example, works by defining a custom function interface for MultiColumnList's Drag Function propery, and implementing a method that handles the drag. The custom drag function, ShoppingCart.productDrag(), compares each new item with the existing items in the cart. If an item is already present, it increments the cart quantity instead of adding it again. Support for multiple selection and dragging is enabled by setting the corresponding MultiColumnList properties to true. Core drag-and-drop functionality, customized or not, is specified declaratively using named drag and drop zones.
In addition, the shopping cart interface takes advantage of Bungee Connect's cross-window drag-and-drop functionality. The cart is displayed as a pop-out dialog, and products can be added by dragging them from the main window's data view. The cart items can also be reordered by dragging them past one another, or by sorting the cart using MultiColumnList's default sort provider. Clicking a cart item displays that item in the main detail view where the quantity can be changed and the item removed. Items can also be removed from the shopping cart with the keyboard's Delete key, implemented with a custom function interface for the MultiColumnList's Remove property.
![]() |
Dynamic Data Loading
The Storefront implements dynamic data loading in three ways:
- Lazy evaluation
- Dynamic pagination
- Data caching
Many Bungee controls support lazy evaluation, which means properties are evaluated only when they are used. Lazy evaluation makes efficient data-binding easy. For example, the TreeView in the Storefront dynamically loads subcategories when a category is expanded. The underlying DynamicCategoryTreeItem simply defines a TreeItemAdapter with a list property. The code for list (see screenshot) is called only when the item is expanded; it queries the database to get that item's children. Bungee Connect also automates caching; the list property is only called the first time an object gets expanded, or after its children have expired from the cache. Lazy evaluation is one of the features that give the Storefront scalability. By only loading the data that's actually displayed, the application supports an arbitrary number categories.
![]() |
![]() |
The Storefront loads product data dynamically as well. The data views (for category browsing and keyword search) are loaded one page at a time. Sorting and pagination happens in the data layer, minimizing the amount of bandwidth that the middleware-database connection needs as well as the resources used by the middleware. The data view is implemented by the PagedProductList control, which loads data through a data connection (an instance of StoreDataWrapper, taken from MainClass) and displays it in a MultiColumnList control. The MultiColumnList control has rich data binding options that let you easily specify sorting, drag-and-drop, and some keyboard functionality (such as handling the Delete key). This works by simply setting the MultiColumnList control's Sort, Drag Function, and Remove interfaces, respectively. The product data view uses a custom sort function. The shopping cart, on the other hand, uses custom drag and remove functions. Function interfaces are defined at the solution level. In this case, they include PaginatedSortInterface, ProductDragInterface, and RemoveCartItemInterface, which correspond to the MultiColumnList control extensions described above. Functions, through their interface list, can "listen" to the events that the interfaces correspond to. In the future, interfaces may be able to specify a method signature. The MultiColumnList control's "sort" event, for example, passes a sort field and sort direction to the functions that connect to it—but PaginatedSortInterface can't specify this yet. At the time of this writing, function interfaces serve, from the developer's point of view, as identifiers that connect functions to events.
![]() |
Lastly, the Storefront loads product details dynamically whenever a product is selected from the data view. Details are cached programmatically, using ProductItems' productDetailCache field.
Planning the data access patterns that user interaction creates, to load as little data as possible, and never in large chunks, has lots of advantages. First, it keeps the user experience responsive. Loading data only when needed, instead of at start up, reduces load times. Second, dynamic loading saves database bandwidth and server resources, which translates into saving Bungee Units. Finally, limiting the amount of data that gets loaded at a time, combined with scalable database design, allows your applications to stay responsive no matter how large the underlying database becomes. Efficient data loading is already made easy by controls such as the TreeView, which uses lazy data binding and automatically caches the results. Other features in the data and detail views use Bungee functionality like custom sort interfaces to implement efficient data access. Even more dynamic data loading and caching automation is on the way!
Application Logic
The application (or business) logic defines the functionality that a web application provides. It is part of the middleware layer, and interfaces with both the data wrapper and the user interface. The Bungee Storefront has three main functions: searching for specific products, browsing the product catalog, and saving products in a shopping cart. A real storefront application would also be able to persist shopping carts between sessions, manage user credentials, and interface with external payment sources. This functionality, however, would add complex components outside of Bungee Connect, and is beyond the scope of the Storefront sample.
Shopping Cart Functionality
Managing the shopping cart requires some simple application logic. This logic is encapsulated by the ShoppingCart class, which contains a collection of ProductCartItems. The ProductCartItem class, in turn, is a wrapper around ProductItem that adds a cart-quantity field, as well as methods for changing the quantity or adding or removing that item from the cart. Together, these classes provide an interface that ensures:
- No item can be in the cart more than once. Instead, each one has a quantity.
- Every item in the cart has to have a quantity greater than zero, but not more than the inventory.
- Total prices for every item, as well as the cart total, are always current.
Search Functionality
The search functionality is implemented as an SQL stored procedure, at the database level. Search compares each product's name and brand to the search string, looking for exact matches as well as words that sound similar. For example, a search for "P-51" will return the "P-51 Mustang" product, and a search for "braddavehobies" will return all products from "Brad & Dave Hobbies."
Products can be both searched and browsed by category. The search function provides an option to return items only from the currently selected category, or from all categories.
Data Wrapper
The data wrapper provides a high-level Bungee interface to the data layer. It handles all communication between the Bungee layer and the underlying data source—for the Storefront it's a Bungee-hosted MySQL instance. The data wrapper is responsible for managing network connections. In this case, the wrapper is connecting to a relational database, which can only return data in rowsets. The wrapper has to turn this "flat" data into hierarchical objects. In other words, it has to bridge the "object-relational impedance mismatch." Centralizing data access in one place with a data wrapper has several advantages:
- You have oversight over all the data access code
- The code is easy to change and easy to debug
- The rest of application becomes more manageable because it doesn't have to know which kind of database or web service the underlying data is from.
The Storefront data wrapper is implemented by the StoreDataWrapper class. Switching, for example, between a SOAP service and a direct database connection requires only a few changes in this class. You can switch from one database to another by changing a single method—init(), which defines the database connection information.
Data Connection Support
Bungee has several tools that make it easy to interface with data sources. Because of this, these tools let you quickly create a data wrapper object. They include embedded MySQL hosting, SQL connection projects, and, for web services, automatic WSDL importing. Bungee's SQL projects let you:
- Configure a connection to a database—hosted externally or by Bungee Connect.
- Run queries to test SQL code or to modify the database.
- Browse and create tables
Together, these let you manage databases, define their schemas, load data, test queries, and so on.
Currently, Bungee Connect can connect to MySQL and PostgreSQL. The Storefront application uses MySQL. This tutorial explains how to create Bungee database connections.
![]() |
![]() |
Querying an SQL Database
Bungee has an SQL API that lets you connect to and query a database programmatically. The API handles all type conversions from SQL's primitive types to Bungee's automatically, which facilitates fast development. The API is concise and focused on the SQLConnection class. SQLConnections provide three main methods: login(), which takes a Config object that defines the database connection; logout(), which closes the connection; and query(), which executes an SQL query and returns a RecordSet object.
You can query a database in two main ways: with a direct SQL SELECT statement and by calling a stored procedure. SELECTs have the advantage of simplicity, but stored procedures have some important advantages as well:
- Speed: Stored procedures are precompiled, which means that the database server doesn't have to parse SQL commands on-the-fly for every query, reducing server usage.
- Economy: Saves BungeeUnits!
- Security: By only allowing stored procedures, you can control exactly how your application, or anything else that manages to connect, can access your database.
- Clean design: All your SQL code is in one place; the data wrapper is just a connector, not an SQL query generator.
With stored procedures, the database itself can provide more than just a collection of tables; it can provide an API—a collection of methods that define the logical purpose that the data layer serves.
The Storefront uses procedure-based database design. For comparison, the getCategory() and getSubcategory() methods of StoreDataWrapper have been implemented in both ways—using simple SQL statements and calling the stored procedures. Simply uncomment one connection.query() call and comment out the other to switch between the two ways of retrieving data.
Database
The Bungee Storefront uses a MySQL database with specific engines (MyISAM and InnoDB) for each table—this optimizes each table for the way in which it's most often accessed. Bungee provides hosted MySQL functionality, which makes it easy to create, browse, and modify a database at design-time. The databases are also hosted alongside the middleware, which ensures low connection latency between middleware and database servers.
The Storefront database schema is outlined as follows:
- Tables:
- products
- id
- brand
- category_id
- price
- in_stock
- product_details
- product_id
- description_html
- thumbnail_url
- categories
- id
- parent_id
- name
- products
- Functions:
- is_parent_id([category id], [parent id])
- get_path([category id])
- Stored procedures:
- get_category([category id])
- get_subcategories([category id])
- get_product_page([query],[category id],[sort field],[sort direction],[start index], [count])
- get_product_details([product id])
- get_product_count([query], [category id])
Additional Resources
- Video:Storefront Reference Application
- Support & Questions: Q & A Knowledgebase.











