35
Creative Commons Attribution- NonCommercial-ShareAlike 2.5 License RSF Wiki Introduction to Reasonable Server Faces Aaron Zeckoski [email protected]

Creative Commons Attribution- NonCommercial-ShareAlike 2.5 License RSF Wiki Introduction to Reasonable Server Faces Aaron Zeckoski [email protected]

Embed Size (px)

Citation preview

  • Reasonable Server FacesRSF is a Java web programming frameworkRoughly the same scope as Suns JSFIncludes the followingNavigation and View renderingServer-side and client-side state managementRequest cycle handling and abstractionAPIs for UI components and view producersPure XHTML templatingLightweight Expression Language (EL)Based on the Spring Framework

  • RSF major featuresPure XHTML templatesTightly integrated with Spring frameworkRESTful navigationEL based data accessExcellent support for internationalizationUser feedback messages supportEasy AJAX integration

  • Theory vs. Practice

  • In theoryWeb applications that are as easy to create as PHP but still well structuredEasier to programStandard HTTP request cycle, zero server stateBetter scoping and separationApplication/Session/RequestComponent bindings from UI to modelTrue separation of the logic and presentationWireframe is the view definition (easy design)Easy to configure for different environments

  • In practiceHarder to work with than PHP but easier than most Java based frameworksBasic understanding of the request cycle neededEspecially if using Session beansNo in-code dependence on ServletsCan use all of the capability of HTMLTruly pure HTML templating (excellent for designers)Complete separation of UI and logicKnowledge of Spring importantDoes provide flexibility and configurability via SpringFull support for IoC and AOP for backing beans and producersAdds support for request scope IoCNo globally visible state maintainers (stateless)

  • RSF structure and code

  • RSF structureThe template (always html) defines the interfaceThe producer (java or xml) defines the view, populates the template, and handles navigationViewParams define the values passed between views (get)The requestContext defines producer and backing beansThe applicationContext defines app scope beans and handles rsf app config (via spring)Backing beans handle action processingLogic layer beans can be injected as defined in the context xml filesModel is basic data POJOTemplate(html)Backing Bean(java)Logic Layer(rest of app)requestContext(xml)model(java)Producer(java)applicationContext(xml)ViewParams(java)

  • RSF templatesXHTML filesMust be valid XML or runtime error will occurNo custom tags used or neededTruly is a pure XHTML templateOnly uses one custom attributersf:id - identifies this component for the producerTemplate(html)

  • Sample template

    RSF ItemsHello, Current User

    Non updateable item New item title Sep 15, 2006 1:26 AM

  • RSF producerControls displays logic and populates the template with dynamic informationDefines a view uniquelyBy setting a ViewIDRecommend you create a public static VIEW_IDImplements ViewComponentProducerDefine start page by implementing DefaultViewImplement NavigationCaseReporter to control submit navigationImplement ViewParamsReporter to receive query parameters from http requestProducer(java)

  • Sample producerpublic class ItemsProducer implements ViewComponentProducer, DefaultView { public static final String VIEW_ID = "Items"; public String getViewID() { return VIEW_ID; } private CrudPlusLogic logic; public void setLogic(CrudPlusLogic logic) { this.logic = logic; } public void fillComponents(UIContainer tofill, ViewParameters viewparams, ComponentChecker checker) { UIOutput.make(tofill, "current-user-name", logic.getCurrentUserDisplayName()); UIForm listform = UIForm.make(tofill, "listItemsForm"); List l = logic.getAllVisibleItems(); for (Iterator iter = l.iterator(); iter.hasNext();) { CrudPlusItem item = (CrudPlusItem) iter.next(); UIBranchContainer itemrow = UIBranchContainer.make(listform, "item-row:", item.getId().toString() ); if (logic.canWriteItem(item)) { UIInternalLink.make(itemrow, "item-update", item.getTitle(), new AddItemViewParameters(AddItemProducer.VIEW_ID, item.getId()) ); } else { UIOutput.make(itemrow, "item-title", item.getTitle() ); } UIOutput.make(itemrow, "item-dateCreated", item.getDateCreated() ); } }}

  • RSF ViewParamsControls the passing of data between page viewsUses query parameters (GET)extends SimpleViewParametersShould be used when data needs to be sent from one view to anotherWorks like standard web variables shouldCan be reused on multiple pagesViewParams(java)

  • Sample ViewParamspublic class AddItemViewParameters extends SimpleViewParameters {public Long id; // an identifier for an itempublic AddItemViewParameters() {}public AddItemViewParameters(String viewID, Long id) {this.id = id;this.viewID = viewID;}public String getParseSpec() {// include a comma delimited list of the // public properties in this classreturn super.getParseSpec() + ",id";}}

  • RSF requestContextRequest Scope ContextOften called RSACAll RSAC beans are lazy by defaultStandard spring bean definition fileUses the Spring file parser codeOnly includes a subset of the standard functionality to increase speedLocation of this file is set in the web.xmlrequestContext(xml)

  • Sample requestContext

  • RSF applicationContextA standard Spring bean definition filePuts the beans in the application contextMostly used for configuring RSFDefine child of requestAddressibleParent to specify beans which can be the target of ELDefine child of beanScopeParent to create a new session scope for session beansDefine a child of CRITemplateResolverStrategy to control the location of templatesLocation of this file set in web.xmlapplicationContext(xml)

  • Sample applicationContext

  • RSF Backing BeanTypical bean with methods to handle actions and public propertiesNo RSF dependenciesStore data needed for processing the user actions using public propertiesControl data model objects with public properties (using EL from producer)Process actions using methodsCan interact with logic layerBut so can the producersCreated and destroyed in the request cycle by default (recommended practice)Can override this behaviorBacking Bean(java)

  • Sample backing beanpublic class ItemsBean { public CrudPlusItem newItem = new CrudPlusItem(); public Map selectedIds = new HashMap();... private CrudPlusLogic logic; public void setLogic(CrudPlusLogic logic) { this.logic = logic; }... public String processActionAdd() { if (newItem.getHidden() == null) { // null here means that the box was not checked newItem.setHidden( DEFAULT_HIDDEN ); } logic.saveItem(newItem); return "added"; }}

  • Web app basics4 key things you need to do in a webappOutput dynamic textRender data to the screenLoop structuresOutput collection or render tablesOptional rendering of componentsRender some components based on stateTrigger ActionsUser actions or data transmissionIn RSF, these all are done using one part in the template and another in the producer (and maybe the backing bean for an action method)

  • Output dynamic textUses an rsf:id on an HTML entity to show where to place the dynamic textDoes not have to be a span or div only!UIOutput will send the escaped string to the id location in the component treeNon-escaped output using UIVerbatimNot recommended thoughHello, Current UserUIOutput.make(tofill, "current-user-name", logic.getCurrentUserDisplayName());1

  • Loop structureList l = logic.getAllVisibleItems();for (Iterator iter = l.iterator(); iter.hasNext();) { Item item = (Item) iter.next(); UIBranchContainer itemrow = UIBranchContainer.make(listform, "item-row:", item.getId().toString() ); if (logic.canWriteItem(item)) { UIInternalLink.make(itemrow, "item-update", item.getTitle(), new AddItemViewParameters(AddItemProducer.VIEW_ID, item.getId()) ); } else { UIOutput.make(itemrow, "item-title", item.getTitle() ); } UIOutput.make(itemrow, "item-dateCreated", item.getDateCreated() );}

    Non updateable item New item title Sep 15, 2006 1:26 AM

    2

  • Optional renderingHTML entities are rendered if the component is tied via the rsf:idIf there is no UI component for the id then the render skips over itCan do this for single entities or for UIBranchContainers to do a blockExample: a surrounding if (item.getHidden().booleanValue()) { UIOutput.make(itemrow, "item-title", item.getTitle() );}Hidden item title3

  • Trigger actionsUse a normal submit button with an idUse UICommand to tie to an action method in a backing bean using ELReturn string ties to a navigation case in the producer

    UICommand.make(addupdateitem, "add-update-item", "#{itemsBean.processActionAdd}");public String processActionAdd() {logic.saveItem(updateItem);return "added";}4

  • RSF in practice

  • RSF experienceRSF has a moderate learning curveMostly unlearning poor practicesUI components are comprehensiveCover all HTML entities, fairly flexibleAJAX integration easyDesigned to work well with AJAX and JSWorks like a webapp shouldNormal REST, back button worksEasy for UI designers to work with

  • RSF ELA subset of the functionality of JSF Expression LanguageNo logic in the expressionSometimes called Value Language (VL)Works with any bean in the request or application contextMore info on the RSF EL page#{requestwriteablebean.property1.subproperty2}URL: http://www2.caret.cam.ac.uk/rsfwiki/Wiki.jsp?page=EL

  • Internationalization (i18n)Well supported with UIMessage concrete classAlso MessageLocatorTakes advantage of the standard Java language properties bundle handlingUses the Spring MessageSource for resource (properties file) loadingConfigurable in applicationContextremove.item.text=Are you sure you want to remove item ({0})?UIMessage.make(tofill, remove-item", "remove.item.text", new Object[] { item.getTitle() } );
  • User feedbackAllows for messages generated in a previous request to appear in the templateNo code is required in the receiving template, only the element with the rsf:idFormat of the output messages is configurable

    Message for user here

    messages.addMessage( new TargettedMessage(user.message", new Object[] { item.getTitle() }, TargettedMessage.SEVERITY_INFO));user.message=New item saved ({0})

  • Javascript and AJAXRSF does not use AJAX for its own purposes so there are no issues with collisionsThere are some widgets and helpers that are included with RSF which use AJAX thoughRSF includes a javascript library to make it easy to work with the rsf generated element idsCan be tricky to work with because of the way the branch nesting works

  • RSF component trees Binds the markup to the modelrsf:id in the templateEL in the producerTree and components created and destroyed during the request cycleShort lived, frees up resourcesRooted in a view and only kept around long enough to render the viewURL: http://www2.caret.cam.ac.uk/rsfwiki/Wiki.jsp?page=Component

  • RSF structure revisitThe template is pure htmlEasy for UI designersThe producer is simple and cleanly defines a viewViewParams abstract out the passing of valuesThe requestContext and applicationContext are pure spring configCan be mixed up sometimesBacking beans are really just simple beansTemplate(html)Backing Bean(java)Logic Layer(rest of app)requestContext(xml)model(java)Producer(java)applicationContext(xml)ViewParams(java)

  • RSF resourcesRSF Wiki (online documentation)http://www2.caret.cam.ac.uk/rsfwiki/RSF forumshttp://ponder.org.uk/rsf/RSF APIshttp://saffron.caret.cam.ac.uk/projects/RSFUtil/apidocs/RSF SVNhttps://saffron.caret.cam.ac.uk/svn/

  • Questions?RSFhttp://www2.caret.cam.ac.uk/rsfwiki/