Spring Surf 101


Published on

In this session, we will examine the basics of the SpringSurf view composition framework for Spring MVC applications. It will show how to easily construct pages, templates and components.

Published in: Technology, Business
  • Be the first to comment

  • Be the first to like this

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • Quick bio:Kevin Roast - UI Team Leader, one of the founding Alfresco developers, worked on the Explorer JSF based client, the JavaScript and FreeMarker services and repository APIs, impl some of the features in Alfresco WebScripts, came up with the PageRenderer WebScript runtime which is the “core” of the SpringSurf rendering tech used in Alfresco Share – i.e. “WebScripts as UI components” – more on to that later…Introduction to SpringSurf – not a deep dive - we will examine the basics of the SpringSurf view composition framework for Spring MVC applications. Hope to show how to easy to construct pages, templates and components that can be used to quickly build web applications fromsimple scripts and templates.
  • WebScripts been around for more than 3 years in some form or anotherSurf has been around for over 2 yearsElaborate on important points in the history
  • M3 -> RC1 we’ve come a long way...RC1 is a revelation compared to stability, performance and test coverage since M3... Features a large suite of tests for functional area coverage.
  • What can you do with it? – Simple REST APIs to complete Rich web applications!WebScript pure REST API tier i.e. separate application – Activiti project; has a pure WebScript based REST API tier exposing new BPM engine (server), plus a SpringSurf based web-application consuming the REST APIs (UI). A mix of Java and JavaScript backed webscripts and FTL based pages <- mention Erik’s blog posts, download Activiti etc.WebQS, Mobile.
  • Why should you use it?Familiar with SpringMVC? Then this will make building views quicker, less (a lot less!) Java code (annotations yuk) and can use lovely WebScripts.Fast, powerful APIs, rapidRAPID dev cycle. Extend Share – jar packaging.Share uses it, WebQS, OpenCMIS and Activiti use itDeveloper tools coming!
  • Views (pages), templates, components – WebScripts, FreeMarker, JS, head templates, JSP, chrome.Page, can specify template instance to use (another xml descriptor) – otherwise Surf will “use template with the same name” but can reuse templates i.e. a product template can be used by multiple pages. Reused of pages, templates.Components can be global, template or page scoped – also uri or theme scope – unique to the URL (mostly same as page, but not if you use URL templates) and theme specific
  • Helps to identify the link between pages, template instances, templates and components
  • Surf model objects can be created, modified and persisted – they all respond to APIs – think dynamic dashboards in Share – could have real-time drag and drop if you felt that would provide the best UI experience...
  • Helps to identify the link between pages, template instances, templates and components
  • Example page def – note embedded page scoped component defs (since 3.3)Custom properties
  • If you have no template scoped components, or template specific properties - then you don’t need this! Surf will automatically attempt to find “products.ftl” and internally generate an intermediary object to represent the template instanceNote the embedded template scoped component defs
  • Note the ${head} freemarker model value – combined result of all components .head.ftl templates – well formed HTMLRegion tags themselves can be dynamic!i.e.<#list comps as c><@region id=“${c}" scope=“${something}" /></#list>Surf will work out what components are present on the page before pre-generating the ${head} contents.Simple DIV structure, use CSS for layout magic (also YUI in Share – entirely up to you what libs you use! JQuery etc.)Example template with region component bindings, examples of global, template and page scoped (next slide for detail)
  • <scope>page</scope> <region-id>title</region-id> <source-id>console</source-id>For uri/theme scopeWith nested components defs, only global scoped components tend to be defined in individual XML files – lot, lot less XML files than in 3.2 – see Share 3.4 for comparison!
  • Allows simple urls and multiple URLs (i.e. Spring Views) to Share the same SpringSurf Page instance
  • UI component WebScript component “contract”:Don’t output full page HTML i.e. Just an HTML fragmentOutput clean HTML consistent with parent page i.e. XHTML, HTML5Use .head.ftl template for dependant client-side files i.e. CSS, JSCan assume running in page context i.e. use of “page.url.args” is ok – but better to “bind” args into component URLEncode HTML with ?html and encode JS with ?js_string <- XSS!
  • If GET, can simplify to – remote.call(“/...”);Use eval() for JSON response – or use E4X to process XML responsePlace any processed JS objects into the “model” – generally an array of objects or just an object – will automatically be marshelled into FreeMarker object equivalents i.e Array to List, Object to MapCan just put the eval-ed resulting object directly into the model without further processing if required, but most scripts do some processing of the data in JS – remember if “production” mode the JS is compiled so quick (but not as quick as Java or modern JS engine like V8...)Get/post/put/delete on the connector objectImagine processing formdata form client, placing into a json structure and POSTing to an API – very quick and easy to do.
  • Walk arrays as lists or access object properties from the model – easy and fast
  • Full component model not available (special template – not running as a true WebScript presentation template) – but access to “page” etc. as you would expect i.e. args available
  • Adding a persister via SpringSurfModel objects will now be retrieved from remote Alfresco store by default (cached of course)Model objects can be save()ed to the remote store
  • Runtime: selects the “persister” group – WEB-INF (webapp), classpath locations (surf/), local is a folder on disk, alfresco is alfresco specific classpaths (alfresco/) i.e. Old Surf apps and Alfresco ShareDevelopment mode: selects the caching settings for the model objects loaded by the persitsers – runtime uses aggressive caching – will *need* to Refresh via console if adding files at runtime. The “development” mode disables caches. Note that WebScript components will still need Refresh-ing as the WebScript registry is populated once during server startup.
  • Mention blog post on JAR packaging for ShareSince 3.4.b it is possible to override Share web-assets also (fixed to use the /res resource controller for all assets – so can override on classpath or JARs)
  • Spring Surf 101

    1. 1. SpringSurf 101<br />2<br />Kevin Roast<br />UI Team Leader, Alfresco<br />twitter: @kevinroast<br />
    2. 2. SpringSurf 101<br />3<br />Introduction<br />Who am I?<br />What is this all about?<br />Just a quick history lesson...<br />What can you do with it?<br />Why should you use it?<br />Views, templates, components.<br />URL mapping<br />Remote API<br />How do I use it?<br />Where is it going and what is missing?<br />
    3. 3. SpringSurf 101<br />4<br />2007<br />Alfresco 2.0 introduces first REST API (early WebScripts concepts)<br />Alfresco 2.1 introduces WebScripts<br />REST framework, JSR-311 (Jax-RS) URI Index<br />Scriptable controllers (or backed by Spring Java Beans)<br />FreeMarker template output (or Java output stream)<br />2008<br />Alfresco Web Framework demo-ware (model objects, JSP, FTL)<br />Alfresco Page Render (WebScripts as components on a page)<br />Combined, productised and renamed to Surf<br />Alfresco Share 3.0, 3.1 – Alfresco collaboration and DM – modern XHTML and Ajax based interface<br />Just a quick history lesson...<br />
    4. 4. SpringSurf 101<br />5<br />Early 2009<br />Alfresco Share 3.2<br />First contact between Alfresco and SpringSource<br />Late 2009<br />Alfresco Surf and WebScripts integrated with SpringMVC<br />Alfresco Surf and WebScripts contributed as Spring Extension – SpringWebScripts and SpringSurf<br />Alfresco Share 3.3 – refactored onto SpringWebScripts and SpringSurf!<br />2010<br />3 Milestones and RC1 release<br />Alfresco Share 3.4 – using SpringSurf RC1<br />2010-2011?<br />RC2, 1.0<br />Just a quick history lesson...<br />
    5. 5. SpringSurf 101<br />6<br />Rapid web-tier view composition – SpringMVC View Resolver<br />FreeMarker, JSP, Groovy, PHP pages<br />WebScript, FTL, JSP, Groovy, PHP components<br />Simple JavaScript, Groovy controllers<br />Remote API – REST request/response processing<br />WebScripts – standalone REST API tier<br />Portlets (RC1)<br />What can you do with it?<br />
    6. 6. SpringSurf 101<br />7<br />View composition plug-in for Spring Web MVC<br />Varied choice of scripting/templating technologies<br />Simple but powerful APIs<br />URI template mappings – clean URLs, page reuse<br />Rapid *rapid* development cycle<br />Output any text format, any HTML format (i.e. XHTML, HTML5)<br />Extensions for Alfresco Share – JAR packaging<br />Alfresco Share, WebQS, OpenCMIS and Apache Activiti<br />Developer tools in progress<br />Continuing development via SpringSource<br />Why should you use it?<br />
    7. 7. SpringSurf 101<br />8<br />Views (pages) – simple XML definition<br />FreeMarker HTML templates, simple DIV based structure, component bindings, that’s it.<br />Page->Template->Component<br />products.xml<br />products.ftl<br />Region component bindings<br />Views, Templates, Components<br />
    8. 8. SpringSurf Model<br />9<br />Pages<br />Home<br />Profile<br />Products<br />Regions<br />Component<br />varconn = remote.connect("alfresco");<br />varjson = conn.get("/api/products/" + args.filter);<br />if (json.status == 200)<br />{<br /> // Create JavaScript objects from the response<br />varobj = eval('(' + json + ')');<br /> if (obj)<br /> {<br /> ... Perform processing on the js objects<br /> // set results into the model for the template<br />model.results = somearray;<br /> }<br />}<br />Template Instance<br />
    9. 9. SpringSurf 101<br />10<br />Everything is an object! Including component bindings.<br />CRUD operations via web-tier JS API<br />Easy dynamic get/set of object properties<br />object.properties["name"] = value;<br />new() and save() objects to persist dynamically i.e. Alfresco Share dashboards<br />Model Objects<br />
    10. 10. SpringSurf Model<br />11<br />Page<br />Instance<br />SiteConfig<br />Template Instance<br />Template<br />Theme<br />Template type<br />Regions<br />Chrome<br />Component<br />Binding<br />Component<br />Component type<br />
    11. 11. products.xml (page)<br />12<br /><?xml version='1.0' encoding='UTF-8'?><br /><page><br /> <title>New Products Page</title><br /> <description>Page displaying newest products</description><br /> <template-instance>products-template</template-instance><br /> <authentication>user</authentication><br /><components><br /> <component><br /> <region-id>productlist</region-id><br /> <url>/components/productlist?filter=new</url><br /> </component><br /> </components><br /> <properties><br /> <maxresults>100</maxresults><br /> </properties><br /></page><br />
    12. 12. products-template.xml (template instance)<br />13<br /><?xml version='1.0' encoding='UTF-8'?><br /><template-instance><br /> <title>Product Template</title><br /> <description>Common products template</description><br /><template-type>products</template-type><br /> <components><br /> <component><br /> <region-id>treeview</region-id><br /> <url>/components/navigation/treeview</url><br /> </component><br /> </components><br /></template-instance><br />
    13. 13. products.ftl<br />14<br /><html><br /> <head>${head}</head><br /> <body><br /> <div id="..." class="..."><br /> <@region id="header" scope="global" /><br /> </div><br /> <div><br /> <@region id="treeview" scope="template" /><br /> <@region id="productlist" scope="page" /><br /> </div><br /> <div><br /> <@region id="footer" scope="global" /><br /> </div><br /> </body><br /></html><br />
    14. 14. SpringSurf 101<br />15<br />Components defined in page XML are page scope – “single use” components specific to a particular page e.g. admin console widget<br />Components defined in template instance XML are template scoped – e.g. common tree navigation component<br />Can define component bindings by declaration – like WebScript artifacts e.g. page.title.console.xml<br />Global scoped component – header, footer etc.<br />Template scoped components<br />Page scoped components<br />Component Scopes<br />
    15. 15. SpringSurf 101<br />16<br />Chrome<br />Template fragment executed to wrap “chrome” around a component – for example default “region” chrome:<br /><div id="${htmlid}"><br /> <@component/><br /></div><br />Themes<br />Objects that encapsulate the information required to define a new look and feel for an app<br />Alfresco Share 3.4 – good example<br />Chrome and Themes<br />
    16. 16. SpringSurf 101<br />17<br />http://yourserver:8080/yourapp/products<br />/all/products /new/products<br />/old/products /bestselling/products<br />Don’t want to define multiple pages that do same thing (even with reuse of templates)<br />Either want to reuse the same page instance<br />And or require some information from the url<br />Can use: urlrewrite.xml<br />Can use: UriTemplateconfig<br />URL Mapping<br />
    17. 17. UriTemplate configuration<br />18<br /><config evaluator="string-compare" condition="UriTemplate"><br /> <uri-templates><br /> <uri-template id="products"><br /> /{filter}/products<br /> </uri-template><br /> <uri-template id="userprofile"><br /> /user/{userid}/{pageid}<br /> </uri-template><br /> </uri-templates><br /></config><br />
    18. 18. SpringSurf 101<br />19<br />UI Components must “behave” and follow loose contract<br />Usual WebScript artifacts – bound by URL<br />I18N messages via localisable properties file<br />Component configuration (XML) via config.xml file<br />GET/POST to page – automatic fall back to GET impl<br />HEAD template webscriptid.get.head.ftl${head}<br />argsmap<br />formdataform fields (including files)<br />page, page.url, config, user, htmlidobjects<br />Request Context - context<br />Request parameters, attributes, headers<br />WebScript Component APIs<br />
    19. 19. SpringSurf 101<br />20<br />Connectors<br />Authenticators<br />XML configure access to “endpoints” – obtained by id<br />Access HTTP methods through JS code or Ajax via proxy controller<br />Endpoints hide the URL stem from scripts – authentication encapsulated by connectors and authenticators<br /><endpoint><br /> <id>alfresco</id><br /> <name>Alfresco - user access</name><br /> <connector-id>alfresco</connector-id><br /> <endpoint-url>http://myserver/alfresco/s</endpoint-url><br /> <identity>user</identity><br /></endpoint><br />Connect to multiple REST sources; alfresco, wiki, search<br />Remoting API<br />
    20. 20. Remote API – component controller<br />21<br />products.get.js<br />varconn = remote.connect("alfresco");<br />varjson = conn.get("/api/products/" + args.filter);<br />if (json.status == 200)<br />{<br /> // Create JavaScript objects from the response<br />varobj = eval('(' + json + ')');<br /> if (obj)<br /> {<br /> ... Perform processing on the js objects<br /> // set results into the model for the template<br />model.results = somearray;<br /> }<br />}<br />
    21. 21. Remote API – component template<br />22<br />products.get.html.ftl<br /><div class="products" id="${htmlid}-products"><br /> <#list results as r><br /> <div class="product">Name: ${r.name?html}</div><br /> </#list><br /></div><br />
    22. 22. Component .head.ftl template<br />23<br />products.get.head.ftl<br /><link rel="stylesheet" type="text/css" href="${page.url.context}/products/products.css" /><br /><script src="${page.url.context}/products/products.js"></script><br />
    23. 23. SpringSurf 101<br />24<br />Persisters – read model object definitions from classpath, WEB-INF, JARs<br />Alfresco legacy locations and Spring “friendly” locations<br />Migration of Alfresco Surf 3.2 apps<br />New locations require less files, folders<br />Read and write to remote location and local file system<br />Example - Alfresco Share stores pages and components for dynamic dashboards in the repository<br />Model Object Stores<br />
    24. 24. Remote Persister Spring Config<br />25<br /><bean id="webframework.slingshot.persister.remote" <br /> class="org.springframework.extensions.surf.persister.PathStoreObjectPersister”<br /> parent="webframework.sitedata.persister.abstract"><br /> <property name="store" ref="webframework.webapp.store.remote" /><br /> <property name="pathPrefix"><br /> <value>alfresco/site-data/${objectTypeIds}</value><br /> </property><br /></bean><br /><bean id="webframework.objects.persister"<br /> class="org.springframework.extensions.surf.persister.MultiObjectPersister"><br /> <property name="serviceRegistry" ref="webframework.service.registry" /><br /> <property name="persisters"><br /> <list><br /> <!-- Slingshot remote store persisters --><br /> <ref bean="webframework.slingshot.persister.remote" /><br /> ...<br /> </list><br /> </property><br /> <property name="defaultPersister"><br /> <ref bean="webframework.slingshot.persister.remote" /><br /> </property><br /></bean><br />
    25. 25. Page, templates, components, webscripts – ALL dynamically refresh via WebScripts and Surf console pages<br />/service/index<br />/service/console<br />Console Information View<br />Refresh WebScripts, Refresh Object Registry<br />Use exploded WAR folders/files during development – copy over and Refresh<br />SpringSurf 101<br />26<br />Rapid Development Lifecycle<br />
    26. 26. Development Configuration (surf.xml)<br />27<br /><alfresco-config><br /> <config evaluator="string-compare" condition="WebFramework"><br /> <web-framework><br /> <!-- Autowire Runtime Settings --><br /> <autowire><br /> <!-- Runtime: classpath, webapp, local, alfresco --> <br /> <!-- <runtime>classpath</runtime> --><br /> <runtime>webapp</runtime><br /> <!-- <runtime>local</runtime> --><br /> <!-- <runtime>alfresco</runtime> --><br /> <!-- Pick the mode: development, production --> <br /> <mode>development</mode><br /> <!-- <mode>production</mode> --><br /> </autowire><br /> </web-framework><br /> </config><br /></alfresco-config><br />
    27. 27. SpringSurf 101<br />28<br />SVN checkout, maven build – www.springsurf.org<br />https://src.springframework.org/svn/se-surf/trunk<br />https://src.springframework.org/svn/se-surf/tags/release-1.0.0-RC1<br />Maven project<br />Example application WAR files (initial config etc.)<br />Quick Start, Spring Pet Clinic, Spring Travel<br />Look at Share, WebQS, Mobile, Activiti...<br />Dev tools!<br />How do I use it?<br />
    28. 28. SpringSurf 101<br />29<br />Alfresco Share JAR file extensions<br />Add or extend Alfresco features via simple JAR file packaging<br />Drop in JAR to Share, restart app-server – done.<br />See Alfresco blogs:<br />alfresco-share-33-extensions-and-springsurf<br />How do I use it?<br />
    29. 29. SpringSurf 101<br />30<br />Continue use by Alfresco projects, customers, partners...<br />DOCUMENTATION!!! (sorry)<br />Where is it going and what is missing?<br />
    30. 30. Learn More<br />31<br />Blog posts:<br />http://blogs.alfresco.com/wp/ewinlof/<br />http://blogs.alfresco.com/wp/kevinr/<br />http://mindthegab.com/<br />http://drquyong.com/myblog/<br />SpringSurf site and forums:<br />http://www.springsurf.org<br />http://forum.springsource.org/forumdisplay.php?f=72<br />
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.