Sample Application

A standalone sample application called Bugzooky is included in Stripes. Browsing the source code and JSPs for the application is one of the best ways to get to grips with some of the more advanced features of Stripes.

The Bugzooky sample application has examples of how to use the following features (among others):

  • Indexed properties (aka multi-row forms)
  • File upload
  • Streaming data back to the client for download
  • Built in and custom validation
  • Multiple events from a single form
  • Re-using the same pages and ActionBeans for add flows and edit flows

A few screen shots and an example class and JSP follow to whet your appetite.

"BulkAddEditBugs.jsp"
<%@ include file="/bugzooky/taglibs.jsp" %> 

<stripes:layout-render name="/bugzooky/layout/standard.jsp" title="Bulk Add/Edit Bugs"> 
<stripes:layout-component name="contents"> 

<jsp:useBean id="componentManager" scope="page" 
    class="net.sourceforge.stripes.examples.bugzooky.biz.ComponentManager"/>
<jsp:useBean id="personManager" scope="page" 
    class="net.sourceforge.stripes.examples.bugzooky.biz.PersonManager"/>

<stripes:form action="/examples/bugzooky/MultiBug.action" focus=""> 
    <stripes:errors/> 

    <table class="display"> 
        <tr> 
            <th>ID</th> 
            <th><stripes:label name="bugs.component.id"/></th> 
            <th><stripes:label name="bugs.owner.id"/></th> 
            <th><stripes:label name="bugs.priority"/></th> 
            <th><stripes:label name="bugs.shortDescription"/></th> 
            <th><stripes:label name="bugs.longDescription"/></th> 
        </tr> 

        <c:choose> 
            <c:when test="${actionBean != null}"> 
                <c:set var="list" value="${actionBean.bugs}" scope="page"/> 
            </c:when> 
            <c:otherwise> 
                <c:set var="list" value="<%= new Object[5] %>" scope="page"/> 
            </c:otherwise> 
        </c:choose> 

        <c:forEach items="${list}" var="bug" varStatus="loop"> 
            <tr> 
                <td> 
                    ${bug.id} 
                    <stripes:hidden name="bugs[${loop.index}].id"/> 
                </td> 
                <td> 
                    <stripes:select name="bugs[${loop.index}].component.id"> 
                        <stripes:option value="">Select One</stripes:option> 
                        <stripes:options-collection collection="${componentManager.allComponents}" 
                            label="name" value="id"/> 
                    </stripes:select> 
                </td> 
                <td> 
                    <stripes:select name="bugs[${loop.index}].owner.id"> 
                        <stripes:option value="">Select One</stripes:option> 
                        <stripes:options-collection collection="${personManager.allPeople}" 
                            label="username" value="id"/> 
                    </stripes:select> 
                </td> 
                <td> 
                    <stripes:select name="bugs[${loop.index}].priority"> 
                        <stripes:option value="">Select One</stripes:option> 
                        <stripes:options-enumeration enum="net.sourceforge.stripes.examples.bugzooky.biz.Priority"/>
                    </stripes:select> 
                </td> 
                <td>
                    <stripes:textarea name="bugs[${loop.index}].shortDescription"/>
                </td> 
                <td>
                    <stripes:textarea name="bugs[${loop.index}].longDescription"/>
                </td> 
            </tr> 
        </c:forEach> 
    </table> 

    <div class="buttons"> 
        <stripes:submit name="save" value="Save"/> 
    </div> 
</stripes:form> 
</stripes:layout-component> 
</stripes:layout-render> 
MultiBugActionBean.java
public class MultiBugActionBean extends BugzookyActionBean { 
    /** Populated during bulk add/edit operations. */ 
    @ValidateNestedProperties({ 
        @Validate(field="shortDescription", required=true, maxlength=75), 
        @Validate(field="longDescription", required=true, minlength=25), 
        @Validate(field="component.id", required=true), 
        @Validate(field="owner.id", required=true), 
        @Validate(field="priority", required=true) 
    }) 
    private List<Bug> bugs = new ArrayList<Bug>(); 

    /** Populated by the form submit on the way into bulk edit. */
    private int[] bugIds; 

    /** Gets the array of bug IDs the user selected for edit. */ 
    public int[] getBugIds() { return bugIds; } 

    /** Sets the array of bug IDs the user selected for edit. */ 
    public void setBugIds(int[] bugIds) { this.bugIds = bugIds; } 

    /** 
     * Simple getter that returns the List of Bugs. Not the use of generics syntax - this is 
     * necessary to let Stripes know what type of object to create and insert into the list. 
    */ 
    public List<Bug> getBugs() { 
        return bugs; 
    } 

    /** Setter for the list of bugs. */ 
    public void setBugs(List<Bug> bugs) { 
        this.bugs = bugs; 
    } 

    @DefaultHandler 
    public Resolution save() { 
        BugManager bm = new BugManager(); 

        for (Bug bug : bugs) { 
            Bug newBug = populateBug(bug); 
            bm.saveOrUpdate(newBug); 
        } 

        return new RedirectResolution("/bugzooky/BugList.jsp"); 
    } 

    @DontValidate 
    public Resolution preEdit() { 
        if (this.bugIds == null) { 
            getContext().getValidationErrors().addGlobalError( 
            new SimpleError("You must select at least one bug to edit.") ); 
            return getContext().getSourcePageResolution(); 
        } 

        BugManager bm = new BugManager(); 
        for (int id : this.bugIds) { 
            this.bugs.add( bm.getBug(id) ); 
        } 

        return new RedirectResolution("/bugzooky/BulkAddEditBugs.jsp").flash(this);
    } 
}