340 likes | 430 Views
Web programming. The rendering layer is clearly an important stress point. For example, to appear as a “1st-class” Sakai tool, a lot of control is required over the HTML level (CSS class, Javascript, etc.)
E N D
Web programming • The rendering layer is clearly an important stress point. • For example, to appear as a “1st-class” Sakai tool, a lot of control is required over the HTML level (CSS class, Javascript, etc.) • Initially a JSF implementation produced (with much pain) – however, much of JSF thrown away in the process. • Considering variety of uses cases implies costs of JSF-like solution for skinning (RenderKits + JSF Components, JSPs) would be EXTREME • CSS can only reskin so far (cannot reorder elements), and cannot “remap” – e.g. Sakai CSS classes cannot be exchanged for another set.
What has JSF got right? • One of the first web systems with a “clean” bean model (no external dependencies) • With JSF-Spring integration, can be extended from request to application scope. • Abstract component tree helps to separate logic from content. • Clear 7-stage pipeline for handling of request logic. • (Relatively) minimal internal interfaces allow replacement of key functionality (ViewHandler, StateHandler) Antranig Basman, CARET, University of Cambridge
What is so terrible about JSF? (part 1) • Default model is reliant on JSPs, the heart of evil. However, this can be replaced (see Hans Bergsten’s “ClassViewHandler”, basis of first FlowTalk system. • “Jackboot” event processing pipeline leads to events happening at “awkward” times, with little control. Many extremely obscure timing problems. • It is too complex and heavyweight. UIComponent is 750 lines, UIComponentBase is 2200, and you probably need to know them well to develop effectively. Many extraneous dependencies. Antranig Basman, CARET, University of Cambridge
What is so terrible about JSF? (part 2) • Very poor, restrictive HTTP semantics - no GET/POST redirect, browser “back” button or browser forking are impossible. Too much session reliance. • Reskinning is VERY HARD. Creating a new JSF component is a lot of work, and difficult to preview one’s results. • JSF component tree is rather inefficient and unnecessary. Perennial problem of “where to keep it”, either on client or server, both involving various penalties. Antranig Basman, CARET, University of Cambridge
What is so terrible about JSF? (part 3) • Default JSF rendering REQUIRES Javascript to operate. Already a philosophical problem, BUT • As a result, JSF is VERY designer-unfriendly. Web designers like to move around HTML in, e.g. Dreamweaver, and apply Javascript and test it at will. JSF/JSP destroys this model. • NB – web designers are experts in their field, and in general also cost less per man-hour/results than programmers! Their design model should be respected. Antranig Basman, CARET, University of Cambridge
The GREAT BEAST — is LOGIC in the PRESENTATION LAYER • Fosters an amorphous, intractable design on a project – no clear point of control, and multi-way, circular dependencies • Confuses designers who have the power to cause devastating effects, and have to tread extremely carefully through reams of incomprehensible tags/code • Is GENERALLY BAD.
Web Technologies compared – part 1 • On these grounds, JSP is the ultimate evil, allowing entirely arbitrary Java code to appear at the presentation level. • JSPs appear(ed) attractive owing to near-magic performance – once compiled, pile out output at close to the maximum possible rate. • However, JSP and still worse JSF/JSP applications are intractable, not least because the presentation files are “not anything” – neither XML or even HTML of any kind, nor are they Java. • Special tools required, that somehow magically manage to be optimised for both designers and coders. • It ain’t gonna happen!
Web Technologies compared – part 2 • There are more web technologies in the world than almost anything else. (Why do you think?) • Almost all try to improve matters in some respects by introducing some from of MVC separation. Survey a few: • Struts/Tiles: Claims view-neutral, but really a JSP shop (loads of taglibs). Also intrudes on controller layer with Actions. • Spring MVC: Actually IS view-neutral, but doesn’t actually do a lot! Takes care of dispatch, some navigation and decoding but has no ideas about view Antranig Basman, CARET, University of Cambridge
Web Technologies compared – part 3 (Tapestry) • Tapestry – interesting in that view layer IS valid HTML. However still contains logic!! • Full OGNL allowable, library of 12 “parameter binding prefixes” including HiveMind. • However, main problem is at the other end – highly intrusive at the Java level with mandatory interfaces and base classes – “everything is an IComponent” • Spring/beans integration not planned until “Tapestry 5.0” (if ever) Antranig Basman, CARET, University of Cambridge
Web Technologies compared – part 4 (Velocity) • Velocity is admirably simple and fast – however actually TOO simple to serve as the entire UI of a webapp! • Understands nothing about document and tag structure, nor about HTTP submission model. • And despite being so simple STILL depends on logic embedded in the template – macro directives #if, looping with #for. • One of the few “safe” technologies, but continues to fall into the error of trying to be a “one-stop-shop” for specifying render behaviour.
The Holy Grail • Technology based on pure HTML view templates, for complete pages that can be rapidly shoved around by designers or even end clients. • Pure backing beans model, easy to integrate with other bean-friendly technologies (Hibernate data model, Spring webapp + IDEs) • Extremely rapid rendering, simple execution model. • Easy to write new components.
RSF/IKAT • RSF is a programming model with roughly the same scope as JSF (in fact derived from all the bits of it that were hacked off) • Content rendering model is codenamed “IKAT” – largely functionally independent (in particular can be used to render pages without any active web context) • Incorporates “Request Scope Application Context” (RSAC) which bridges Spring to provide equivalent of JSF’s request-scope beans Antranig Basman, CARET, University of Cambridge
IKAT • A kind of Javanese weaving. Most of the catchy Java-name gimmicks were taken years ago!
IKAT • IKAT is extremely fast. • Parse 10k template file in 5ms (almost no need to cache structures) • Render 10k document in 2.5ms (cost dominated largely by writing bytes – avoiding use of Java.io.Writer saved 25%). • Like Tapestry, the template looks EXACTLY like a rendered page, but system is much simpler. • Only addition to DOM is ONE special attribute – rsf:id. Can easily ensure validating X(HT)ML for designer by inline internal subset. Antranig Basman, CARET, University of Cambridge
IKAT rendering • During render time, IKAT template file is “paired up” with a component tree, matching template rsf:id attribute to component ID. • Unlike JSF, component tree exists only momentarily, between construction by producer (main app) logic and rendering – THROWN AWAY between request cycles. • RSF UIComponent – 50 lines of code. 4 fields and one method. • IKAT remains logic-free, while alternating (weaving) between template-driven order and component-driven order to render desired view. Antranig Basman, CARET, University of Cambridge
RSF Component Hierarchy Looks a little familiar…. ?
rsf:id • The only template attribute added to the target render (XML) language. • Only three interpretations: • simple string denotes a (leaf) component peer, e.g. UIOutput • string containing colon denotes a container peer (UIContainer), which is a function call/branch point • string containing equals sign denotes target of static rewrite rule (e.g. URL rewrite or other runtime binding) Antranig Basman, CARET, University of Cambridge
How could this possibly work? • The “interesting” step involves how the template file gets structurally rewritten, while remaining a pure X(HT)ML file free of logic. • The “colon” type tag specifies a “branch point” within the template. • “Normal template processing” involves scanning through template in order, pairing up each rsf:id with a leaf UIComponent with a matching ID in the current scope. V.fast. • On hitting a “branch point” with a colon ID, renderer performs a “function call” within the template, which may resolve to ANY instance of an rsf:id attribute with matching prefix before colon. Antranig Basman, CARET, University of Cambridge
IKAT function call resolution • The resolution of the function call is performed using an “argument matching” procedure, which compares • i) the upcoming rsf:id attributes on children of the prospective function call target in the template, and • ii) the ID values on UIComponent children in the component tree, representing “producer demand on template” • Resolution is performed first in current container scope, then at global scope across template file (ultimately across multiple template files for true modular rendering architecture with reusable components) • Highest penalty is for “missing” components in template, second-level penalty for “extra components” • After function call, normal scanning resumes at the target template tag, “returning” once an XML tag is encountered with lower nesting level. • Function call is also fast, and lookup decisions are candidates for caching.
IKAT consequences • Making large scale alterations in UI skinning (not just reordering/reorganising components, but completely suppressing/restoring them is just a matter of editing HTML files. • E.g. Sakai skin (will, once a competent HTML designer looks at it!) provide a “first-class” Sakai look-and-feel with correct CSS styles/JS &c, while at the same time the same codebase can serve entirely different UI requirements. • All this while ensuring that pages are rendered ONLY ONCE – no rewrites required at consumer end, can begin copying bytes to client the moment request resolves. • Designers can experiment with complex Javascript (AJAX) interfaces in situ. Antranig Basman, CARET, University of Cambridge
MAKE YOUR WEBAPPS A LOGIC-FREE ZONE
RSF architecture • Larger-scale RSF architecture provides mapping between component contents and Actions • Very similar to JSF – components have value bindings and method bindings which are expressed in EL with the same syntax: #{beanname.methodname} • TargettedMessage system provides reliable delivery of validation/error messages across POST/GET redirect cycle (vide FacesMessage) • Unique tokens (GUIDs) allocated to each request, allowing robust and correct behaviour in the face of i) multiple submissions, ii) back button, iii) browser forking Antranig Basman, CARET, University of Cambridge
RSF Request Cycle X(HT)ML View Template Template lookup View token ViewParameters IKAT GET Rendered X(HT)ML View Component Tree (Logic or XML/XSLT)
How to write an RSF component • In general you don’t need to! • Most cases can be taken care of by just writing some HTML. • If you really need to, extremely simple. • Component class itself just holds “dumb data” (5 lines) • Renderer simply chucks Strings from template to output stream (10 lines) • Since RSF is entirely Spring-based, much less bureaucracy in registering component (RenderKit? &c) • Unlike JSF components, RSF component is only concerned with data binding function, not with rendering. Antranig Basman, CARET, University of Cambridge
UIOutputMultiline publicclassUIOutputMultilineextendsUIBound{ publicStringListvalue; publicUIOutputMultiline(UIContainerparent,StringID,Stringbinding,StringListvalue){ this.ID=ID; this.valuebinding=binding; this.value=value; parent.addComponent(this); } } Antranig Basman, CARET, University of Cambridge
UIOutputMultilineRenderer StringListvalue=((UIOutputMultiline)torendero).value; if(value==null){ RenderUtil.dumpTillLump(lumps,lumpindex+1, close.lumpindex+1, pos); } else{ RenderUtil.dumpTillLump(lumps,lumpindex+1, endopen.lumpindex+1,pos); for(inti=0;i<value.size();++i){ if(i!=0){ pos.print("<br/>"); } xmlw.write(value.stringAt(i)); } pos.print(close.text); } Antranig Basman, CARET, University of Cambridge
RSAC – Request Scope Application Context • All of RSF and its bean model is defined in pure Spring – no awkward static configuration and files to manage. • Request-scope beans have become more powerful than JSF beans, since they may contain other request-scope bean dependencies. • This has a rather interesting architectural effect, which is not yet fully understood, but seems extremely powerful. • Same “offloading” of dependency management that Spring brought to webapps happens in miniature during a request, removing much uninteresting logic and enabling static checking of application structure by Eclipse IDE. Antranig Basman, CARET, University of Cambridge
Use of RSAC within RSF • Since much of RSF’s logic itself is implemented using RSAC, there have been startling increases in cleanliness. • The ideal final evolution of a Servlet: ?? publicclassReasonableServletextendsHttpServlet{ privateWebApplicationContext wac; publicvoidinit(ServletConfigconfig){ ServletContextsc=config.getServletContext(); wac=WebApplicationContextUtils.getWebApplicationContext(sc); } protectedvoidservice(HttpServletRequestrequest, HttpServletResponseresponse){ wac.getBean(request.getMethod().equals(“GET”)? “gethandler” : “posthandler”); } } Antranig Basman, CARET, University of Cambridge
Summer Lightning • RSF’s RSAC was initially implemented very simply using a Spring GenericApplicationContext, but performance was found to be too dreadful to be conceivable for a web request cycle (sometimes over 1s for a getBean() • Since then, core Spring functionality has been reimplemented in a “fast and lean” clone (retaining Spring code for reading config files) • Available in RSAC: • Autowire dependencies back to RSAC • FactoryBeans • List and Set properties • BeanPostProcessors Antranig Basman, CARET, University of Cambridge
Reflections on Java performance • Benchmarking of Java primitive operations has led to interesting conclusions/recommendations: Antranig Basman, CARET, University of Cambridge
Results (107 its, P4-1.6Ghz) Antranig Basman, CARET, University of Cambridge
Performance Commentary • JDK 1.5 is considerably faster than 1.4 across the board (~20%), ESPECIALLY for object construction. • Reflection performance is AWFUL for all JDKs, running to be nearly 100x slower than direct equivalent. • Synchronized blocks (even uncontended) are really pretty bad, no matter what they tell you. • Since synchronized has NOT improved in 1.5, sync block has gone from equivalent of 2 object constructions to 8. • Object.clone is the real shocker. Consistently about 1.6x the cost of a reflective operation. Antranig Basman, CARET, University of Cambridge
FastClass • Part of the CGLib bytecode engineering library on sourceforge • (CGLib is used by Hibernate, AOP among other high-profile libraries) • Provides direct equivalents for java.reflect.Method, java.reflect.Constructor &c • FastClass.invokeMethod() tested at 35ns on JDK 1.4.2 • I.e. down from 100x performance penalty to 4~5x. FastClass is indeed VERY FAST. • Spring introspection uses javax.beans and so very hard to accelerate. RSAC can be easily altered however. Antranig Basman, CARET, University of Cambridge