1.91k likes | 2.08k Views
Taming Cocoon. ApacheCon Europe 2005 Gianugo Rabellino. Agenda. Introduction Installing Cocoon Dissecting Cocoon Management and configuration A sitemap tour Cocoon components and blocks Understanding continuations and flow Dealing with forms Patterns, best practices, pitfalls.
E N D
Taming Cocoon ApacheCon Europe 2005 Gianugo Rabellino
Agenda • Introduction • Installing Cocoon • Dissecting Cocoon • Management and configuration • A sitemap tour • Cocoon components and blocks • Understanding continuations and flow • Dealing with forms • Patterns, best practices, pitfalls
Introduction: web developer nightmares out.println(“<table border=\”0\”>\n\t<tr>\n\t\t” + “<td align=\”left\”><font size=\”+1\”>” + request.getParameter(“lousyjob”) + “Does your boss know you\'re typing HTML?” + “</td>\n\t</tr>\n</table>\n”);
Nightmare: managing HTML • Your IDE can't deal with HTML • Dreamweaver can't deal with business logic • Period. • Oh, and JSPs suck. Big time. “Separate concerns” - Edsger Dijkstra - 1974
Nightmare: handling state • HTTP is stateless (did you notice already?) • Where am I now? • Restart required • Sessions == overpopulated mess of dictionaries
Nightmare: managing user input • Validation hell • Conversion ordeal • Binding torture • The infamous Back button, oh my!
There has to be a better way “Never let a man do what a machine can do for him” Blaise Pascal
Apache Cocoon A fast-paced overview
Apache Cocoon: facts and figures • Origins • Started by the Italian student Stefano Mazzocchi • Redesign of Apache.org • Frustrated by the limitations of HTML • Wanted to use emerging technologies (XML/XSL) • Today • Now one of the most important Apache projects • Incorporates technologies from various project • Just under 2000 registered on all mailing lists • Includes major companies such as HP, IBM
Key Cocoon concepts • URI space decoupling • Componentized resource assembling • Datasource connections and decoupling • Stateful applications
And their implementation... • URI space decoupling • Sitemap • Componentized resource assembling • Pipelines • Datasource connections and decoupling • Source interface and implementations (file, URL, database, WebDAV, XMLDB...) • Stateful applications • Web continuations
URI space decoupling: the sitemap • Think <servlet-mapping> on steroids • Pattern freaks think FrontController • Uses pluggable algorithms: • Wildcard • Regexp • Your own • Matching the whole HTTP environment: • Request URI/parameters/attributes • Session attributes • Cookies, context, etc... • Welcome to the sitemap
A sitemap example • <map:match pattern="news/*" type="wildcard"> • <map:generate src="newsfeeds/{1}.xml" type="file"/> • <map:transform src="news2html.xsl" type="xslt"/> • <map:serialize type="html"/> • </map:match> • <map:match pattern="products/*" type="wildcard"> • <map:generate src="products/infos/product_{1}.xml" type="file"/> • <map:transform src="products2html.xsl" type="xslt"/> • <map:serialize type="html"/> • </map:match>
Resource assembling: the pipeline • Task: find the total number of unique hosts visiting the home page of your site • Windows solution: #include <stdlib.h> ... • Unix solution: $ grep index.html access.log | awk '{print $2 }' | sort | uniq | wc -l • Welcome to the pipeline: specialized components glued together
The Cocoon pipeline • Two simple rules: • Data stream is based on SAX events • Pipelines start with one Generator (and only one), have 0-n Transformers, end with one (and only one) Serializer • Generators: adapters from the outside world to SAX events • Transformers: SAX event manglers • Serializers: adapters from SAX events to the outside world
A pipeline example <map:matchpattern="*.html"> <map:generatesrc=”xdocs/{1}.xml"/> <map:transformsrc=“style/xdocs2html.xsl”/> <map:serialize/> </map:match>
Datasource virtualization • Virtualization layer over stream-based data sources • Provides a java.io.File like interface for a number of data sources • Think URLs on steroids
A datasource example • <map:match pattern="news/*" type="wildcard"> • <map:generate src="webdav://repo/newsfeeds/{1}.xml" type="file"/> • <map:transform src="xmldb://localhost/db/news2html.xsl" type="xslt"/> • <map:serialize type="html"/> • </map:match> • <map:match pattern="products/*" type="wildcard"> • <map:generate src="cocoon://products/infos/product_{1}.xml"/> • <map:transform src="resource://products2html.xsl" type="xslt"/> • <map:serialize type="html"/> • </map:match>
Summing it up • The sitemap decouplesURI space from physical resources • The pipelinedecouplesresults from the way they're built • XML decouplescontent from presentation • The source abstractiondecouplesdata sources from physical locations Result:full Separation of Concerns (and you ain’t seen nothing yet...)
Web Continuations The next revolution
But wait, this is stateless HTTP • Webapps are finite state machines • Upon every click, processing starts from the beginning • Again, and again, and again
What are continuations? “A continuation is an entire set of closures that make up a point of execution” “A continuation is an object that, for a given point in your program, contains a snapshot of the stack trace, including all the local variables, and the program counter” Hmmm... so what?
A flowscript example: where the magic happens var cart; var user; function checkout() { while(user == null) { cocoon.sendPageAndWait("login.html"); user = UserRegistry.getUser(cocoon.request.get("name")); } cocoon.sendPageAndWait("shippingAddress.html", {who: user}); var address = cocoon.request.get("address"); cocoon.sendPageAndWait("creditCard.html"); var creditCard = cocoon.request.get("creditCard"); cocoon.sendPageAndWait("confirmOrder.html"); EnterpriseSystem.placeOrder(user, cart, address, creditCard); cocoon.sendPage("orderPlaced.html"); }
What are continuations, again? • Contents of a continuation • Stack of function calls • Value of local variables • Most often a lightweight object • Creating a continuation does not halt a thread !! • A continuation object is associated with a unique identifier available to the view • Later used to "resurrect" it
Flowscript example, revisited saved continuations var cart; var user; function checkout() { while(user == null) { cocoon.sendPageAndWait("login.html"); user = UserRegistry.getUser(cocoon.request.get("name")); } cocoon.sendPageAndWait("shippingAddress.html", {who: user}); var address = cocoon.request.get("address"); cocoon.sendPageAndWait("creditCard.html"); var creditCard = cocoon.request.get("creditCard"); cocoon.sendPageAndWait("confirmOrder.html"); EnterpriseSystem.placeOrder(user, cart, address, creditCard); cocoon.sendPage("orderPlaced.html"); }
Continuations tree var cart; var user; function checkout() { while(user == null) { cocoon.sendPageAndWait("login.html"); user = UserRegistry.getUser(cocoon.request.get("name")); } cocoon.sendPageAndWait("shippingAddress.html", {who: user}); var address = cocoon.request.get("address"); cocoon.sendPageAndWait("creditCard.html"); var creditCard = cocoon.request.get("creditCard"); cocoon.sendPageAndWait("confirmOrder.html"); EnterpriseSystem.placeOrder(user, cart, address, creditCard); cocoon.sendPage("orderPlaced.html"); } Don't fear the Back button anymore!
Summing it up • Continuations give control back to the server • We always know "where" the browser is • Allow sophisticated flow screens • No need for state automata • Increase security and robustness • Forbids direct access to form submission URLs • Handling of "back" and "new window"
A word about forms Managing user input
Cocoon Forms: nightmares solved! • MVC based form framework • Provides: • Strongly-typed data: a date field is a java.util.Date. Automatically. • Validation: declarative. Handled for you. Automatically. • Binding: to objects (EJB, POJOs...) or to XML, your choice. Automatically.
Cocoon Forms, a functional view • Separation of Concerns in forms: • Model: data typing, validation rules • View: widget presentation • selections could be drop down lists or checkboxes • Controller: • flowscript (continuations based) • custom actions (à la Struts) – not recommended • Data binding: • declarative • JXPath based
Cocoon Forms: a rich framework • Powerful widget library • Fields, aggregated fields, dates, selectors, trees and repeaters • AJAX compliant infrastructure • Boosts perceived performance • Integrated add-ons • HTML editor • calendar pop-ups • dynamic double selection lists
Summing it up: RAD development • Configure, don't code • Continuations make webapp development a breeze • Powerful form frameworks ease managing user input • Separation of Concerns brings maintainability ... and they lived happily ever after.
Installing Cocoon Finding your way through compilation and blocks
Downloading Cocoon • http://cocoon.apache.org • Subversion for the latest version: http://svn.apache.org/repos/asf/cocoon/branches/BRANCH_2.1.X http://svn.apache.org/repos/asf/cocoon/trunk • … or even WebDAV
Preparing Cocoon • Task list: • Edit local.build.properties • Exclude unneeded and heavy tasks (e.g. javadocs / documentation) • Edit local.blocks.properties • Beware of dependencies • All done, now run: $ ./build.sh (Unix) C\> build.bat (Windows)
Testing the install • Embedded Jetty: • Run $ ./cocoon.sh servlet (Unix) C\> cocoon.bat servlet (Windows) • Point your browser to http://localhost:8888/ • Other servlet engines: • Run $ ./build.sh war (Unix) C\> build.bat war (Windows) • Deploy dist/cocoon*.war
Beware the classloader • Cocoon uses its own version of Rhino (Javascript engine) • Might clash with vendor-provided ones (e.g. Websphere/BEA) • Make sure that your appserver is configured to run Cocoon in an isolated classloader (as per servlet spec): • ask your vendor to fix his bug if it doesn’t work • If it doesn’t work, use the “paranoid” block and the ParanoidCocoonServlet (but you shouldn’t) • Mind redirects on WebSphere!
Eclipse integration • Run: $ ./build.sh eclipse-project (Unix) C\> build.bat eclipse-project (Windows) • Inside Eclipse: • New Java Project • Navigate to $COCOON_HOME • Your project will appear automagically!
Files you want to know • Main sitemap: $COCOON_HOME/build/webapp/sitemap.xmap • Log configuration: $COCOON_HOME/build/webapp/WEB-INF/logkit.xconf • Component configuration: $COCOON_HOME/build/webapp/WEB-INF/cocoon.xconf • Mount table: $COCOON_HOME/mount-table.xml
Management and configuration Handling Cocoon in production
Configuring Cocoon • Web Application Configuration • Cocoon runs as a servlet • Configuration controlled by web.xml • Find it in the WEB-INF directory • Most important entry • Name and location of the actual configuration file • Default: WEB-INF/cocoon.xconf <!-- This parameter points to the main configuration file for Cocoon. Note that the path is specified in absolute notation but it will be resolved relative to the servlets webapp context path --> <init-param> <param-name>configurations</param-name> <param-value>/WEB-INF/cocoon.xconf</param-value> </init-param>
Configuring Cocoon • cocoon.xconf • XML format • Contains Avalon component configuration • But not (!!) the sitemap components • They are in the sitemap • cocoon.xconf rarely needs changing • Moving from test to production • Replacing the XML parser
Configuring Cocoon • cocoon.xconf <?xml version="1.0"?> <cocoon version="2.0"> <parser class="org.apache.cocoon.components.parser.XercesParser"/> <hsqldb-server class="org.apache.cocoon.components.hsqldb.ServerImpl" pool-max="1" pool-min="1"> <parameter name="port" value="9002"/> <parameter name="silent" value="true"/> <parameter name="trace" value="false"/> </hsqldb-server>... </cocoon>
Configuring Cocoon • cocoon.xconf • No namespace • Each component defined inside <cocoon> • Logical names matched to implementations • e.g. parser; hsqldb-server • Configuration using <parameter> • Contains name-value pairs • pool-min and pool-max • We will look at those later (pooling)
Configuring Cocoon • cocoon.xconf • Another important piece of information • Location and name of the sitemap <sitemap file="context://sitemap.xmap" check-reload="yes"/> • Reloading • Triggers on incoming request • Synchronous • New sitemap will be generated and then handles the request • What do you do if an error occurs ............