1 / 35

Introduction to Reasonable Server Faces

Introduction to Reasonable Server Faces. Aaron Zeckoski and Antranig Basman. Core RSF Values: Completely pure HTML templating Roundtrip with designers without loss Preview behaviour as well as appearance from the file system

jscheer
Download Presentation

Introduction to Reasonable Server Faces

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Introduction to Reasonable Server Faces Aaron Zeckoski and Antranig Basman

  2. Core RSF Values: Completely pure HTML templating Roundtrip with designers without loss Preview behaviour as well as appearance from the file system Templates can be reloaded on a live server just by dropping in files IoC is built-in No need to "integrate with" Spring, RSF is built from Spring IoC in the request scope "refreshes the parts other IoC cannot reach" (universal portability without code changes) Why use RSF?

  3. Core RSF Values: Stateless design Lightweight EL system allows talk of data "in the future" as well as via web services/AJAX Request scope is completely flushed at the end of the request Sakai sessions can be > 50Mb per user. RSF encourages designs where session sizes are minimized Uses a more PHP-like "running off the DB" model Why use RSF? (contd.)

  4. A Sample RSF template <?xml version="1.0" encoding="UTF-8" ?> <html><head><title>RSF Items</title></head><body> Hello, <span rsf:id="current-user-name" >Current User</span> <form rsf:id="listItemsForm" method="post"> <table class="listHier"> <tr rsf:id="item-row:" > <td class="firstColumn"> <span rsf:id="item-title" >Non updateable item</span> <a rsf:id="item-update" href="AddItem.html?id=1">New item title</a> </td> <td rsf:id="item-dateCreated" class="secondColumn"> Oct 29, 2007 10:26 AM </td> </tr> </table> </form> </body></html>

  5. In RSF, there is a complete separation between markup and render logic Markup: held in an XHTML template decorated with rsf:id markers Logic: held in a Spring-managed (Java) bean known as a Producer The job of a Producer is to produce a tree of elementary ("primitive") UI components To see how this all fits together, let's look at the overall RSF app structure How to use this template?

  6. RSF structure and code

  7. The template (always html) defines the interface The producer (java or xml) defines the view, populates the template, and handles navigation ViewParams define the values passed between views (get) The requestContext defines producer and backing beans The applicationContext defines app scope beans and handles rsf app config (via spring) Backing beans handle action processing Logic layer beans can be injected as defined in the context xml files Model is basic data POJO RSF structure Template (html) ViewParams (java) Producer (java) requestContext (xml) Backing Bean (java) applicationContext (xml) Logic Layer (rest of app) model (java)

  8. XHTML files Must be valid XML or runtime error will occur No custom tags used or needed Truly is a pure XHTML template Only uses one custom attribute rsf:id - identifies this component for the producer Template (html) RSF templates

  9. Sample template <?xml version="1.0" encoding="UTF-8" ?> <html><head><title>RSF Items</title></head><body> Hello, <span rsf:id="current-user-name" >Current User</span> <form rsf:id="listItemsForm" method="post"> <table class="listHier"> <tr rsf:id="item-row:" > <td class="firstColumn"> <span rsf:id="item-title" >Non updateable item</span> <a rsf:id="item-update" href="AddItem.html?id=1">New item title</a> </td> <td rsf:id="item-dateCreated" class="secondColumn"> Oct 29, 2007 10:26 AM </td> </tr> </table> </form> </body></html>

  10. Controls displays logic and populates the template with dynamic information Defines a view uniquely By setting a ViewID Recommend you create a public static VIEW_ID Implements ViewComponentProducer Define start page by implementing DefaultView Implement NavigationCaseReporter to control “submit” navigation Implement ViewParamsReporter to receive query parameters from http request Producer (java) RSF producer

  11. Sample producer public 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<CrudPlusItem> l = logic.getAllVisibleItems(); for (CrudPlusItem item: l) { UIBranchContainer itemrow = UIBranchContainer.make(listform, "item-row:"); 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() ); } } }

  12. Controls the passing of data between page views Represents query parameters (GET) and URL trunk in the abstract extends SimpleViewParameters Should be used when data needs to be sent from one view to another Uses URLs in the RESTful way they were designed However, is abstract and typesafe Can be reused on multiple pages ViewParams (java) RSF ViewParams

  13. Is a "Pea" (uses fields rather than getters/setters) getParseSpec method is unnecessary unless you want fine control over URL structure public class AddItemViewParameters extends SimpleViewParameters { public Long id; // an identifier for an item public 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 class return super.getParseSpec() + ",id"; } } Sample ViewParams

  14. Request Scope Context Often called RSAC All RSAC beans are lazy by default Standard Spring bean definition file Uses the Spring file parser code Only includes a subset of the standard functionality to increase speed Location of this file is set in the web.xml requestContext (xml) RSF requestContext

  15. Sample requestContext <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <!-- list the backing beans here --> <bean id="itemsBean" class="org.sakaiproject.crudplus.tool.ItemsBean" init-method="init"> <property name="logic" ref="org.sakaiproject.crudplus.logic.CrudPlusLogic" /> </bean> <!-- list the producer beans here --> <bean class="org.sakaiproject.crudplus.tool.producers.ItemsProducer"> <property name="logic" ref="org.sakaiproject.crudplus.logic.CrudPlusLogic" /> </bean> <bean class="org.sakaiproject.crudplus.tool.producers.AddItemProducer"> <property name="logic" ref="org.sakaiproject.crudplus.logic.CrudPlusLogic" /> </bean> </beans>

  16. A standard Spring bean definition file Puts the beans in the application context Mostly used for configuring RSF Define child of requestAddressibleParent to specify beans which can be the target of EL Define child of beanScopeParent to create a new session scope for session beans Define a child of CRITemplateResolverStrategy to control the location of templates Location of this file set in web.xml applicationContext (xml) RSF applicationContext

  17. Sample applicationContext <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <!-- For security purposes, only beans listed in the comma separated value list may be the target of EL operations coming in over the request --> <bean parent="requestAddressibleParent"> <property name="value" value="itemsBean, infoMessages"/> </bean> <!-- Put this backing bean in session scope --> <bean id="messageBeanScope" parent="beanScopeParent"> <property name="copyPreservingBeans" value="infoMessages" /> <property name="exclusive" value="true" /> </bean> </beans>

  18. Typical bean with methods to handle actions and public properties No RSF dependencies Store data needed for processing the user actions using public properties Control data model objects with public properties (using EL from producer) Process actions using methods Can interact with logic layer But so can the producers Created and destroyed in the request cycle by default (recommended practice) Can override this behavior Backing Bean (java) RSF Backing Bean

  19. Sample backing bean public 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"; } }

  20. 4 key things you need to do in a webapp Output dynamic text Render data to the screen Loop structures Output collection or render tables Optional rendering of components Render some components based on state Trigger Actions User actions or data transmission In 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) Web app basics

  21. Uses an rsf:id on an HTML entity to show where to place the dynamic text Does not have to be a span or div only! UIOutput will send the escaped string to the ID location in the component tree Non-escaped output using UIVerbatim Avoid this unless truly necessary 1 Output dynamic text Hello, <span rsf:id="current-user-name">Current User</span> UIOutput.make(tofill, "current-user-name", logic.getCurrentUserDisplayName());

  22. 2 Loop structure Use UIBranchContainer and colon tags for looping structures List<Item> l = logic.getAllVisibleItems(); for (Item item: l) { UIBranchContainer itemrow = UIBranchContainer.make(listform, "item-row:"); 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() ); } <table class="listHier"> <tr rsf:id="item-row:"> <td class="firstColumn"> <span rsf:id="item-title">Non updateable item</span> <a rsf:id="item-update" href="AddItem.html?id=1">New item title</a> </td> <td rsf:id="item-dateCreated">Oct 29, 2007 10:26 AM</td> </tr> </table>

  23. HTML entities are rendered if the component is tied via the rsf:id If there is no UI component matching the id then the renderer skips over it A UIOutput can also peer with a tag in the template with further component children, to swap in or out a whole block of markup 3 Optional rendering if (item.getHidden().booleanValue()) { UIOutput.make(itemrow, "item-title", item.getTitle() ); } <span rsf:id="item-title">Hidden item title</span>

  24. Use a normal submit button with an id Use UICommand to tie to an action method in a backing bean using EL NB – "action methods" are considered an old-fashioned form of programming – try to use BeanGuards instead (more later) Return string ties to a navigation case in the producer 4 Trigger actions <input rsf:id="add-update-item" type="submit" value="Add/Update Item" /> UICommand.make(addupdateitem, "add-update-item", "#{itemsBean.processActionAdd}"); public String processActionAdd() { logic.saveItem(updateItem); return"added"; }

  25. RSF in practice

  26. RSF has a moderate learning curve Mostly unlearning poor practices UI components are comprehensive Cover all HTML entities, fairly flexible AJAX integration easy Designed to work well with AJAX and JS Works like a webapp should Normal REST, back button works Easy for UI designers to work with RSF experience

  27. A tiny subset of the functionality of JSF Expression Language No logic in the expression Sometimes called Value Language (VL) Works with any bean in the request or application context More info on the RSF EL page RSF EL #{requestwriteablebean.property1.subproperty2} URL: http://www2.caret.cam.ac.uk/rsfwiki/Wiki.jsp?page=EL

  28. Defines a single path (EL) to your data Points to a BeanLocator which allows you to tell RSF where to find your data Point it at your logic/dao layer RSF 0.7.2+ has an automated "EntityBeanLocator" which will map to most DAO APIs OTP (One True Path) <input rsf:id="title-input" size="60" name="title" type="text"/> UIInput.make(form, "title-input", “EntryLocator.1.title"); publicclass EntryLocator implements BeanLocator { … } <bean id="EntryLocator" class=“uk.ac.cam.blogwow.tool.otp.EntryLocator“ />

  29. Well supported with UIMessage concrete class Also MessageLocator Simple cases can be handled in the template with rsf:id="msg=key" Takes advantage of the standard Java language properties bundle handling Uses the Spring MessageSource for resource (properties file) loading Configurable in applicationContext Internationalization (I18n) <b rsf:id=“remove-item">Are you sure you want to remove item (title)?</b> UIMessage.make(tofill, “remove-item", "remove.item.text", new Object[] { item.getTitle() } ); remove.item.text=Areyousureyouwanttoremoveitem({0})? URL: http://www2.caret.cam.ac.uk/rsfwiki/Wiki.jsp?page=I18N

  30. Allows for messages generated in a previous request to appear in the template No code is required in the receiving template, only the element with the rsf:id Format of the output messages is configurable User feedback <div rsf:id="message-for:*" class="alertMessage"> <ul style="margin:0px;"><li>Message for user here</li></ul> </div> messages.addMessage( new TargettedMessage(“user.message", new Object[] { item.getTitle() }, TargettedMessage.SEVERITY_INFO)); user.message=New itemsaved({0})

  31. RSF does not use AJAX for its own purposes (not embedded) so there are no issues with collisions There are some widgets and helpers that are included with RSF which use AJAX though RSF includes a Javascript library to make it easy to work with the RSF generated element ids Can be tricky to work with because of the way the branch nesting works Javascript and AJAX

  32. Binds the markup to the model rsf:id in the template EL in the producer Tree and components created and destroyed during the request cycle Short lived, frees up resources Rooted in a view and only kept around long enough to render the view RSF component trees URL: http://www2.caret.cam.ac.uk/rsfwiki/Wiki.jsp?page=Component

  33. The template is pure XHTML Easy for UI designers The producer is simple and cleanly defines a view ViewParams abstract out the passing of values The requestContext and applicationContext are pure spring config Can be mixed up sometimes Backing beans are really just simple beans RSF structure revisit Template (html) ViewParams (java) Producer (java) requestContext (xml) Backing Bean (java) applicationContext (xml) Logic Layer (rest of app) model (java)

  34. RSF Wiki (online documentation) http://www2.caret.cam.ac.uk/rsfwiki/ RSF forums http://ponder.org.uk/rsf/ RSF APIs http://saffron.caret.cam.ac.uk/projects/RSFUtil/apidocs/ RSF SVN https://saffron.caret.cam.ac.uk/svn/ RSF resources

  35. RSF http://www2.caret.cam.ac.uk/rsfwiki/ Questions?

More Related