Chrysalis Quick StartChrysalis is a lightweight, MVC (Model-View-Controller) web development framework with some twists. This guide is designed to quickly familiarize you with its major features. To understand this document, you need to know the Java language, basic web programming (HTML and form processing) and be familiar with servlet and JSP development. Web developers (HTML page authors) may wish to begin with the Web Developers Guide instead. Model-View-ControllerLike most modern web frameworks, Chrysalis is based on the Model-View-Controller (MVC) pattern. MVC is a pattern for user interface development that divides components into three groups:
The basic work horses in Chrysalis are the controllers, so this document will cover them first. ControllersChrysalis controllers resemble ordinary Java classes and may have as many methods as they need to perform their functions. Controllers:
Controller methods can have any logic necessary to process web applications operations. For example, you could have a "Cart" controller that store shopping cart items in a Map between method invocations. The CartController could controller adding, removing and retrieving items from the cart, and eventually using those items to place an order. public class CartController extends Controller { private Map items = new HashMap(); public void addItem(Long itemId) throws Exception { items.put(itemId, Item.load(itemId)); } public void removeItems(Long[] itemId) { for (int i=0; i<itemId.length; i++) { items.remove(itemId[i]); } } public Collection getItems() { return this.items.values(); } public void placeOrder() throws Exception { // Use the items collection to create an order } } Controller methods are targeted by Command URLs inside the web application. Command URLs consist of:
Cart.addItem.cmd?itemId=296 The Command URL can appear in hyperlinks or form actions: <h1>Catalog<h1> Hat [<a href="Cart.addItem.cmd?itemId=296">Add to Cart</a>]<br> Shirt [<a href="Cart.addItem.cmd?itemId=689">Add to Cart</a>]<br> Shoes [<a href="Cart.addItem.cmd?itemId=806">Add to Cart</a>] In the example above, each time an [Add to Cart] link is
clicked, the specified item id would be passed to the
Other controller methods can be targeted by different Command URLs in the site. If the URL is a form action, the form's input elements (form fields) determine the parameter values submitted to the controller method: <h1>Shopping Cart</h1> <form action="Cart.removeItems.cmd"> Items<br> <input type="checkbox" name="itemId" value="296" /> Hat <br> <input type="checkbox" name="itemId" value="689" /> Shirt <br> <input type="submit" value="Remove Items" /> </form> <form action="Cart.placeOrder.cmd"> <input type="submit" value="Place Order" /> </form> In the example above, the selected checkboxes in the first form
determine the parameter values passed to the
There is at most one instance of a given type of controller for a particular user, so all of these operations will interact with the same controller and manipulate the same data. Controller Configuration and RedirectionThe configuration information for individual controllers is in an XML file called chrysalis.xml. This configuration file is loaded from the Java classpath, and therefore should be in the same directory as the controller's class file. This is the com/domain/catalog/controllers/ directory for the sample catalog application: <!-- chrysalis.xml for controller package --> <config> <class name="CartController"> <default view="/showCart.jsp" errorpage="/error.jsp" /> <method name="addItem" parameters="itemId" /> <method name="removeItems" parameters="itemId" /> <method name="placeOrder" view="/showOrder.jsp" errorpage="REFERER_PAGE" /> </class> <!-- Configuration for other controller classes ... --> </config> This configuration file includes:
When a controller finishes its processing, it redirects to the
specified view, or the error page if an exception is thrown. A
controller can also use its public class CatalogController extends Controller { // Other operations ... public void editItem(Item item) throws Exception { item.save(); setView("/showItem.jsp", "itemId", item.getItemId()); } } The controller above will redirect to the view URL
The Model: JavaBeansThe Chrysalis model consists of ordinary JavaBean business objects. The JavaBean specification states that JavaBeans must:
Chrysalis supports the use of any JavaBean, but the framework
functions more smoothly if the JavaBeans encode business object
metadata in the public class Item { private Long itemId; private String name; private int stock; private double price; private Date startDate; public Long getItemId() { return this.itemId; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public int getStock() { return this.stock; } public void setStock(int stock) { this.stock = stock; } public String getPrice() { return this.price; } public void setPrice(double price) { this.price = price; } public Date getStartDate() { return this.startDate; } public void setStartDate(Date date) { this.startDate = date; } // Other methods: load(), save(), etc. } <!-- chrysalis.xml for JavaBean package --> <config> <class name="Item"> <property name="name" maxlength="20" /> <property name="stock" min="0" max="1000" /> <property name="price" min="0.01" datatype="Currency" /> </class> <!-- Other JavaBean configuration ... --> </config> If a property is omitted from the configuration file, Chrysalis derives the attributes of that property via reflection, as it does with the "itemId" and "startDate" properties in the example above. The Chrysalis framework defines a number of "well-known" attributes used elsewhere in the framework:
Some of these values ( The View: JSPsChrysalis generates views using JSP, with a library of custom tags to support form generation. A typical Chrysalis form might be rendered as follows: <jutil:use var="item" controller="Catalog" /> <h1>Edit Catalog Item</h1> <jhtml:form action="Catalog.editItem.cmd"> <table> <jhtml:field property="itemId" /> <jhtml:field property="name" /> <jhtml:field property="stock" /> <jhtml:field property="price" /> <jhtml:field property="startDate" /> <tr><td colspan="2"><input type="submit" value="Submit"></td></tr> </table> </jhtml:form> The For the generated JavaScript validations to work, the page must
import and initialize the <!-- In template.jsp for the sample application --> <script src="/catalog/javascript/FormValidation.js"></script> <body onload="initFormValidation()"> <!-- The rest of the template ... --> The public class CatalogController extends Controller { public Item getItem(Long itemId) throws Exception { return Item.load(itemId); } // Other logic ... } Controller methods that load bean data are called initializers or controller properties to distinguish them from more general controller methods. Initializers are the only controller methods a JSP can invoke directly. Controller initializers resemble the getter methods of JavaBean
properties, but they may have method parameters which can be used
to initialize data. The example editItem.jsp?itemId=689 Controllers that Update BeansThe public class CatalogController extends Controller { public Item getItem(Long itemId) throws Exception { return Item.load(itemId); } public void editItem(Long itemId, String name, int stock, double price, Date startDate) throws Exception { Item item = Item.load(itemId); item.setName(name); item.setStock(stock); item.setPrice(price); item.setStartDate(startDate); item.save(); setView("/showItem.jsp", "itemId", item.getItemId()); } } Because this public class CatalogController extends Controller { public Item getItem(Long itemId) throws Exception { return Item.load(itemId); } // Form data will be copied into the Item object. public void editItem(Item item) throws Exception { item.save(); setView("/showItem.jsp", "itemId", item.getItemId()); } } When the
This technique is most useful when beans and forms match each other. If this is not the case, you can always use explicit controller method parameters. Putting It All TogetherSuppose one of your application use cases is "Edit an existing catalog item". You decide that you need:
Item ModelYou design your model class first: public class Item { private Long itemId; private String name; private int stock; private double price; private Date startDate; public Long getItemId() { return this.itemId; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public int getStock() { return this.stock; } public void setStock(int stock) { this.stock = stock; } public String getPrice() { return this.price; } public void setPrice(double price) { this.price = price; } public Date getStartDate() { return this.startDate; } public void setStartDate(Date date) { this.startDate = date; } public static Item load(Long itemId) { /* Load item data */ } public void save() { /* Save item data */ } } You configure your <!-- chrysalis.xml for JavaBean package --> <config> <class name="Item"> <property name="name" maxlength="20" /> <property name="stock" min="0" max="1000" /> <property name="price" min="0.01" datatype="Currency" /> </class> <!-- Other JavaBean configuration ... --> </config> Catalog ControllerYour view will not function without a controller to load data, so you may want to create the controller first. public class CatalogController extends Controller { public Item getItem(Long itemId) throws Exception { return Item.load(itemId); } // Form data will be copied into the Item object. public void editItem(Item item) throws Exception { item.save(); setView("/showItem.jsp", "itemId", item.getItemId()); } } You configure your <!-- chrysalis.xml for controller package --> <config> <class name="CatalogController"> <method name="getItem" parameters="itemId" /> <method name="editItem" parameters="item" view="/showItem.jsp" /> </class> <!-- Other controller configuration ... --> </config> The
Item ViewYou can have a <jutil:use var="item" controller="Catalog" /> <h1>Edit Catalog Item</h1> <jhtml:form action="Catalog.editItem.cmd"> <table> <jhtml:field property="itemId" /> <jhtml:field property="name" /> <jhtml:field property="stock" /> <jhtml:field property="price" /> <jhtml:field property="startDate" /> <tr><td colspan="2"><input type="submit" value="Submit"></td></tr> </table> </jhtml:form> Your <jutil:use var="item" controller="Catalog" /> <h2>Catalog Item</h2> <table border="1" cellspacing="0" cellpadding="3"> <tr> <td><jhtml:label property="itemId" />: </td> <td><jutil:print property="itemId" /></td> </tr> <tr> <td><jhtml:label property="name" />: </td> <td><jutil:print property="name" /></td> </tr> <tr> <td><jhtml:label property="stock" />: </td> <td><jutil:print property="stock" /></td> </tr> <tr> <td><jhtml:label property="price" />: </td> <td><jutil:print property="price" /></td> </tr> <tr> <td><jhtml:label property="startDate" />: </td> <td><jutil:print property="startDate" /></td> </tr> </table> Flow of ExecutionThe flow of execution is as follows: 1. The user opens the " 2. The user submits the form to the
" 3. Chrysalis redirects to the
" More Use CasesOnce one of your item-related use cases is done, the others
become much easier. Other item-related operations (Create Item,
Delete Items, Show List of Items) can re-use the same
Other use cases will likely require expanding your model with additional beans. New controller methods can be added to a single controller if the model objects are closely related; the "CatalogController" could handle all catalog-related use cases. Unrelated function can be put into separate controllers for better modularity, such as a "SecurityController" to handle security issues. Chrysalis ConfigurationThe controllers in a Chrysalis application should be in a
specific set of packages (the controller packages). In the sample
applications, there is only one controller package:
<!-- ChrysalisConfig.xml --> <config> <servlet.engine> <controller> <package>com.domain.catalog.controllers</package> <!-- Other controller packages, as needed --> </controller> </servlet.engine> </config> Configuration for each seperate controller package is located in the chrysalis.xml configuration file in that controller package. Similarly, the configuration for each JavaBean package (bean metadata) goes in the chrysalis.xml configuration file in that JavaBean package. Servlet 2.2 View URLsMost of Chrysalis is based on the older Servlet 2.2/JSP 1.1 standard. Chrysalis does use one feature of the Servlet 2.3+ API: filters. Chrysalis needs to perform some preprocessing before displaying JSP pages, and filters are the best way to do this. To support the older standard, Chrysalis provides a special
FilterServlet that invokes Servlet 2.3 filters in Servlet 2.2
containers. The FilterServlet requires a URL pattern, and this
pattern cannot be Unfortunately, this means that for Servlet 2.2 containers, the URLs used to invoke the view and the file name of the page will not be the same.
Though awkward, this mechanism does allow Chrysalis to support
older servlet engines that only comply with the Servlet 2.2
standard. The Servlet 2.3 version of Chrysalis can also recognizes
the " ConclusionThat's it for the major features of Chrysalis. Take a look at the sample applications for more examples. Look at the Java Developers Guide and the Web Developers Guide for additional details. Flow Diagram for Catalog Application
Note: Since the template.jsp is incorporated in every page, its links are available globally. |