Hello!

2009/3/2 AK <[email protected]>:
> ..."We keep our Actions simple and lightweight, deferring all non-display
> logic to transactional, spring-managed services. I.ve seen examples where
> Actions are directly interacting with the database, a pattern I
> discourage."
>...
> Any thoughts and guidance would be appreciated.

I totally agree with the statement. Doing testdriven develeopment this
helps writing simple tests without mocking a complex environment. I am
using stripes as web framework for  3 tier applications and Guice as
dependency injection framework. Here is my code for displaying a list
of events and the functionality to mark them "as read". The @Inject
Annotation is needed by Guice, all other Annotations come from
stripes.

The ActionBean for displaying the list:
public class CashAccountMonitoringActionBean extends BaseActionBean {
        private static final Logger logger =
Logger.getLogger(CashAccountMonitoringActionBean.class);
        private List<CashAccountMonitoringEvent> events;
        private ICashAccountMonitoringService cashAccountMonitoringService;

        @DefaultHandler
        @DontBind
        public Resolution view() {
                if (logger.isTraceEnabled())
                        logger.trace("view()");
                try {
                        events = cashAccountMonitoringService.getUnreadEvents();
                } catch (ServiceException e) {
                        logger.error("Error on 
cashAccountMonitoringService.getUnreadEvents()", e);
                        getContext().getValidationErrors().addGlobalError(new 
LocalizableError(
                                        e.getMessage()));
                }
                return new ForwardResolution(
                                getJsp());
        }

        public List<CashAccountMonitoringEvent> getEvents() {
                return events;
        }

        @Inject
        public void 
setCashAccountMonitoringService(ICashAccountMonitoringService
cashAccountMonitoringService) {
                this.cashAccountMonitoringService = 
cashAccountMonitoringService;
        }
}

The actionBean to mark them as read:
public class CashAccountMonitoringManipulationActionBean extends
BaseActionBean {
        private static final Logger logger =
Logger.getLogger(CashAccountMonitoringManipulationActionBean.class);
        private List<SelectedPersistantObject<Long>> events;
        private ICashAccountMonitoringService cashAccountMonitoringService;
        private ISelectedPersistantObjectActionBeanHelper
selectedPersistantObjectActionBeanHelper;

        @ValidationMethod(on = "markAsDone")
        public void validateSelectedEventIds(ValidationErrors validationErrors) 
{
                
selectedPersistantObjectActionBeanHelper.validateSelectedIds(events,
validationErrors);
        }

        public Resolution markAsDone() {
                if (logger.isTraceEnabled()) {
                        logger.trace(MessageFormat.format("Submitted objects: 
{0}",
Arrays.toString(events.toArray())));
                }
                try {
                        
cashAccountMonitoringService.markAsDone(selectedPersistantObjectActionBeanHelper.extractSelectedIds(events,
logger));
                        getContext().getMessages().add(new LocalizableMessage(
                                        "success.update"));
                } catch (ServiceException e) {
                        logger.error("Error on marking cashMonitoringEvent as 
done", e);
                        getContext().getValidationErrors().addGlobalError(new 
LocalizableError(
                                        e.getMessage()));
                } catch (NoEventSelectedException e) {
                        logger.debug(e, e);
                }

                return new RedirectResolution(
                                CashAccountMonitoringActionBean.class);
        }

        @ValidateNestedProperties(
        { @Validate(on = "markAsDone", field = "id", encrypted = true),
@Validate(on = "markAsDone", field = "selected") })
        public List<SelectedPersistantObject<Long>> getEvents() {
                return events;
        }

        public void setEvents(List<SelectedPersistantObject<Long>> 
selectedEvents) {
                this.events = selectedEvents;
        }

        @Inject
        public void setSelectedPersistantObjectActionBeanHelper(
                        ISelectedPersistantObjectActionBeanHelper
selectedPersistantObjectActionBeanHelper) {
                this.selectedPersistantObjectActionBeanHelper =
selectedPersistantObjectActionBeanHelper;
        }

        @Inject
        public void 
setCashAccountMonitoringService(ICashAccountMonitoringService
cashAccountMonitoringService) {
                this.cashAccountMonitoringService = 
cashAccountMonitoringService;
        }
}

The jsp:
<%@ include file="/WEB-INF/jsp-commons/Taglib.jsp"%>
<s:layout-render name="/WEB-INF/jsp-layouts/controllingPage.jsp">
        <s:layout-component name="pageTitle">
                <fmt:message key="page.controlling.cashMonitoring.pageTitle" />
        </s:layout-component>
        <s:layout-component name="head"><%@ include
file="/WEB-INF/jsp-commons/AjaxHead.jsp"%></s:layout-component>
        <s:layout-component name="onLoad"></s:layout-component>
        <s:layout-component name="content">
                <h1><fmt:message key="page.controlling.cashMonitoring.header" 
/></h1>
                <hr />
                <p><fmt:message key="page.controlling.cashMonitoring.intro" 
/></p>
                <s:messages />
                <s:errors />
                <s:form 
beanclass="de.dser.dwh.fe.controllers.controller.app.controlling.CashAccountMonitoringManipulationActionBean">
                        <table class="display">
                                <thead>
                                        <tr>
                                                <th></th>
                                                <th><fmt:message 
key="page.controlling.cashMonitoring.accountId" /></th>
                                                <th><fmt:message 
key="page.controlling.cashMonitoring.date" /></th>
                                                <th><fmt:message
key="page.controlling.cashMonitoring.overview.customer" /></th>
                                                <th><fmt:message
key="page.controlling.cashMonitoring.overview.depotBank" /></th>
                                                <th><fmt:message
key="page.controlling.cashMonitoring.overview.amount" /></th>
                                                <th><fmt:message
key="page.controlling.cashMonitoring.overview.type" /></th>
                                                <th><fmt:message
key="page.controlling.cashMonitoring.overview.consultant" /></th>
                                        </tr>
                                </thead>
                                <tbody>
                                        <c:if test="${empty actionBean.events}">
                                                <tr>
                                                        <td 
colspan="8"><fmt:message key="noEntriesMessage" /></td>
                                                </tr>
                                        </c:if>
                                        <c:forEach var="event" 
items="${actionBean.events}" varStatus="status">
                                                <tr>
                                                        <td><s:checkbox 
name="events[${status.index}].selected"
/><s:hidden name="events[${status.index}].id" value="${event.id}"
/></td>
                                                        
<td>${event.cashAccountTransaction.cashAccount.cashAccountId}</td>
                                                        <td><s:format 
value="${event.date.time}" formatType="date" /></td>
                                                        
<td>${event.cashAccountTransaction.cashAccount.customer.firstname}
${event.cashAccountTransaction.cashAccount.customer.lastname}</td>
                                                        
<td>${event.cashAccountTransaction.cashAccount.bank}</td>
                                                        <td><s:format 
value="${event.cashAccountTransaction.amount}"
formatPattern="0.00" /> ${event.cashAccountTransaction.currency}</td>
                                                        <td><fmt:message
key="${event.cashAccountTransaction.cashAccountTransactionType.translationId}"
/></td>
                                                        
<td>${event.cashAccountTransaction.cashAccount.customer.consultant.firstname}
                                                        
${event.cashAccountTransaction.cashAccount.customer.consultant.lastname}</td>
                                                </tr>
                                        </c:forEach>
                                </tbody>
                        </table>
                        <c:if test="${not empty actionBean.events}">
                                <fmt:message var="tmp"
key="page.controlling.cashMonitoring.overview.done" />
                                <div class="layoutBoxAlignRight"><s:submit 
class="fg-button
ui-state-default ui-corner-all" name="markAsDone" value="${tmp}"
/></div>
                        </c:if>
                </s:form>
        </s:layout-component>
</s:layout-render>

Let me know if you have any questions I'm always interested in discussions :-)

------------------------------------------------------------------------------
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H
_______________________________________________
Stripes-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-users

Reply via email to