Your SlideShare is downloading. ×
Alfresco from an agile framework perspective
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Alfresco from an agile framework perspective

2,880
views

Published on

This is a presentation I gave at Alfresco DevCon 2010 in the Best Practices track. It covers patterns of Alfresco customization, compares Spring Surf to agile application development frameworks like …

This is a presentation I gave at Alfresco DevCon 2010 in the Best Practices track. It covers patterns of Alfresco customization, compares Spring Surf to agile application development frameworks like Django, and provides best practices and advice around developing Share customizations.


0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,880
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
74
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • LOC count excludes YUI, TinyMCE, Share/Surf Java source
    Server-side JavaScript total includes both Share tier and Repository tier JavaScript
  • Transcript

    • 1. Alfresco from an agile framework perspective Jeff Potts jpotts@metaversant.com
    • 2. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Agenda • Patterns of Alfresco Customization • A Tale of Two Frameworks: Surf vs. Django • Heavy Share Customization: A real-world example • Conclusions & Advice
    • 3. PATTERNS OF ALFRESCO CUSTOMIZATION
    • 4. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Custom Alfresco Patterns • Non-Alfresco framework on top of Alfresco • Surf on top of Alfresco • Light Share Customizations • Heavy Share Customizations • Patterns we aren’t going to talk about: – Explorer client customizations – Portal integration – Embedded Alfresco Source: thomas hawk
    • 5. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Non-Alfresco Framework Source: Optaros +
    • 6. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Surf on Alfresco Source: Optaros
    • 7. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Light Share Customizations
    • 8. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Heavy Share Customizations
    • 9. A TALE OF TWO FRAMEWORKS
    • 10. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Surf or Something Else? • Share is a popular, extensible client with a great UI • When Share is too much or too far from your business requirements… – Which framework on top of Alfresco? – An experiment… Source: irargerich
    • 11. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com A word on agile frameworks • Agile frameworks and scripting languages are very popular • Examples: Rails, Grails, Django, Wicket, Symfony, Cake, etc. • Productive, fast dev cycles • Built-in Bootstrapping, ORM, MVC, tests/fixtures, administrative UI’s • Hundreds available across every language imaginable • Can be trendy, like frozen yogurt Source: mswine
    • 12. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Common requirements • Let content authors create "chunks" and upload files • Chunks and files get tagged and categorized • Not all objects have files--the UI can't freak out when it comes across "content-less" objects • Front-end web site needs to be able to query for chunks, files, and content-less objects • The front-end web site cannot look like Share – Our users aren't teams – They don't care about “document libraries”
    • 13. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com A simple example: To Do • Basic requirements – End users create/manage to do list items – To do list items are tagged – End users can upload documents related to To Do’s • Extended requirements – Certain categories of To Do Lists have associated content chunks that need to be displayed. • Example: To do list that is categorized as "Writing" should display with content chunks that give advice on writing. – Groupings of To Do lists • Friends/Co-workers • Projects, etc. – RSS feeds
    • 14. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Approaches • To Do’s, Users, and Files are objects. • I’ll map URLs to various views on those objects. • I’ll probably use a relational database to persist everything except the files, which I’ll let my framework handle. • Files are documents. That’s easy. • To Do’s are “content-less” objects. • I need to figure out a folder for all of this stuff to live in and how I want to relate To Do’s to files. • I’ll map URLs to various views which will request data from the repository via REST.
    • 15. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Five-minute look at Django • Creating a new Django app • Defining a content model • Creating a template • Model View Controller • Using the admin site to edit object instances Source: William Gottlieb Fun Django Facts: •Started as an internal project in 2003 at the Journal-World newspaper (Lawrence, KS) •Named after jazz guitarist, Django Reinhardt •The Onion recently migrated to Django from Drupal Fun Django Facts: •Started as an internal project in 2003 at the Journal-World newspaper (Lawrence, KS) •Named after jazz guitarist, Django Reinhardt •The Onion recently migrated to Django from Drupal
    • 16. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Model from django.db import models from django.contrib.auth.models import User from datetime import date, datetime class ToDoItem(models.Model): title = models.CharField(max_length=200) dueDate = models.DateField(default=date.today()) priority = models.IntegerField(default=3) status = models.TextField() notes = models.TextField() createdDate = models.DateTimeField(default=datetime.today()) creator = models.ForeignKey(User, related_name='todo_creator') assignee = models.ForeignKey(User, null=True, blank=True, related_name='todo_assignee') #attachments = Document # Array of CMIS documents def __unicode__(self): return self.title class Tag(models.Model): name = models.CharField(max_length=64, unique=True) toDoItems = models.ManyToManyField(ToDoItem) def __unicode__(self): return self.name from django.db import models from django.contrib.auth.models import User from datetime import date, datetime class ToDoItem(models.Model): title = models.CharField(max_length=200) dueDate = models.DateField(default=date.today()) priority = models.IntegerField(default=3) status = models.TextField() notes = models.TextField() createdDate = models.DateTimeField(default=datetime.today()) creator = models.ForeignKey(User, related_name='todo_creator') assignee = models.ForeignKey(User, null=True, blank=True, related_name='todo_assignee') #attachments = Document # Array of CMIS documents def __unicode__(self): return self.title class Tag(models.Model): name = models.CharField(max_length=64, unique=True) toDoItems = models.ManyToManyField(ToDoItem) def __unicode__(self): return self.name models.py
    • 17. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com URLs map to Views urlpatterns = patterns('', (r'^admin/', include(admin.site.urls)), (r'^$', main_page), (r'^user/(w+)/$', user_page), (r'^login/$', 'django.contrib.auth.views.login'), (r'^logout/$', logout_page), (r'^register/$', register_page), (r'^register/success/$', direct_to_template, {'template': 'registration/register_success.html'}), (r'^create/$', todo_create_page), (r'^save/(d+)/$', todo_save_page), (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': site_media}), (r'^tag/([^s]+)/$', tag_page), (r'^tag/$', tag_cloud_page), ) urlpatterns = patterns('', (r'^admin/', include(admin.site.urls)), (r'^$', main_page), (r'^user/(w+)/$', user_page), (r'^login/$', 'django.contrib.auth.views.login'), (r'^logout/$', logout_page), (r'^register/$', register_page), (r'^register/success/$', direct_to_template, {'template': 'registration/register_success.html'}), (r'^create/$', todo_create_page), (r'^save/(d+)/$', todo_save_page), (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': site_media}), (r'^tag/([^s]+)/$', tag_page), (r'^tag/$', tag_cloud_page), ) settings.py def user_page(request, username): user = get_object_or_404(User, username=username) todos = user.todo_assignee.order_by('-id') variables = RequestContext(request, { 'username': username, 'todos': todos, 'show_tags': True, 'show_assignee': False, 'show_creator': True, 'show_edit': username == request.user.username, }) return render_to_response( 'user_page.html', variables ) def user_page(request, username): user = get_object_or_404(User, username=username) todos = user.todo_assignee.order_by('-id') variables = RequestContext(request, { 'username': username, 'todos': todos, 'show_tags': True, 'show_assignee': False, 'show_creator': True, 'show_edit': username == request.user.username, }) return render_to_response( 'user_page.html', variables ) views.py
    • 18. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com <html> <head> <title>Django To Do's | {% block title %}{% endblock %}</title> <link rel="stylesheet" href="/site_media/style.css" type="text/css" /> </head> <body> <div id="nav"> <a href="/">home</a> {% if user.is_authenticated %} welcome, <a href="/user/{{ user.username }}/">{{ user.username }}</a>! | <a href="/create/">new to do</a> | <a href="/logout">logout</a> {% else %} <a href="/login/">login</a> <a href="/register/">register</a> {% endif %} </div> <h1>{% block head %}{% endblock %}</h1> {% block content %}{% endblock %} </body> </html> <html> <head> <title>Django To Do's | {% block title %}{% endblock %}</title> <link rel="stylesheet" href="/site_media/style.css" type="text/css" /> </head> <body> <div id="nav"> <a href="/">home</a> {% if user.is_authenticated %} welcome, <a href="/user/{{ user.username }}/">{{ user.username }}</a>! | <a href="/create/">new to do</a> | <a href="/logout">logout</a> {% else %} <a href="/login/">login</a> <a href="/register/">register</a> {% endif %} </div> <h1>{% block head %}{% endblock %}</h1> {% block content %}{% endblock %} </body> </html> base.html {% extends "base.html" %} {% block title %}{{ username }}{% endblock %} {% block head %}To Do's for {{ username }}{% endblock %} {% block content %} {% include "todo_list.html" %} {% endblock %} {% extends "base.html" %} {% block title %}{{ username }}{% endblock %} {% block head %}To Do's for {{ username }}{% endblock %} {% block content %} {% include "todo_list.html" %} {% endblock %} user_page.html {% if todos %} <ul class="todos"> {% for todo in todos %} <li> <a href="/todo/{{ todo.id }}" class="title">{{ todo.title }}</a> {% if show_edit %} … {% if todos %} <ul class="todos"> {% for todo in todos %} <li> <a href="/todo/{{ todo.id }}" class="title">{{ todo.title }}</a> {% if show_edit %} … todo_list.html Template Inheritance
    • 19. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Alfresco approach • Content Consumer UI – Custom Surf pages/templates/components for the "front-end" user interface • Administrative UI – Lightly-customized Alfresco Share • Data Persistence – Custom content model for properties, associations (To Do data list happens to already exist) – Document library for files and content chunks – Data List objects for To Do items – Rule on a folder to add taggable and classifiable aspects to new objects
    • 20. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Alfresco approach • Business Logic – Share web scripts to generate UI and handle form posts – Repo web scripts to handle JSON POSTs that create new data (file upload, new to do) – Repo web scripts to handle GETs that retrieve existing data (chunks for a given category, to do list info) – JavaScript for all web-tier and repo-tier web script controllers (fast dev, cuts down on restarts)
    • 21. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Demo: A tale of two frameworks • Share site • Data list content model • Surf pages & web scripts (XML, FreeMarker, JavaScript) • Repository web scripts (minimal) • Surf config – Alfresco user factory • Share config (minimal) • RDB back-end – Schema managed by Django • Python classes – Model – Controllers (“Views”) – Forms • URL mapping • Admin UI
    • 22. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Work Remaining • Add file upload to both Django and Alfresco To Do’s – Django has a File type – Django supports custom File Managers (Hello, CMIS!) – Refactor django-alfresco to use CMIS; e.g., CmisDocument type • Add “categorizable chunk” to both • Search • Friends list Source: jphilipg
    • 23. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Comparison • Both have decent tooling – pydev for Django – Eclipse/STS, Roo, Maven, Ant for Alfresco • Model, forms, query much easier in Django • “Learning where stuff goes” – Much faster in Django • Surf documentation is “still evolving” Source: TheBusyBrain To Do Demo App Alfresco Django Number of files 75 23Alfresco # of Files by Type Django # of Files by Type
    • 24. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Comparison (cont’d) • Gotchas – Lack of query-able associations in DM repo was painful – Add user to Share site on user registration post – Create a rule on the data list folder to set owner – Keep track of assignee add/remove • Attempt to simplify actually made Surf site harder – Forms without JavaScript – No pickers – Not fully leveraging Alfresco’s form service Source: automania To Do Demo Alfresco Django Lines of Code 1,578 674 Alfresco LOC by Type Django LOC by Type
    • 25. HEAVY SHARE CUSTOMIZATION
    • 26. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com A real-world example • SaaS platform wants a community site with resources their customers need to leverage the platform better • Content chunks & files • Discussion threads, blogs • Everything tagged against multiple taxonomies • Consumer UI • Content Management / Admin UI
    • 27. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Architecture Lightly customized Share Admin UI Consumer UI Heavily customized Share •Content Model •Behaviors •Rules •Web Scripts •Theme •YUI •Form Service •Web Scripts Content Managers Community Users
    • 28. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Data Model Global Share Site Client Share Sites Project Share Sites Users & Groups Client ID on cm:user One group per client Client Data List Snippets & Resources Categories Categories for products, topics, processes Project Data List Client Logos Process State Data List User-uploaded Content Share Site HierarchyAdmin Data Team Data List
    • 29. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Content Consumer UI
    • 30. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Content Chunks
    • 31. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com File Resources
    • 32. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
    • 33. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Administrative UI
    • 34. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Customization by the Numbers t = 17,153 lines t = 6,552 lines t = 192,925 lines t = 118,586 lines Share LOC Share JS Customization LOC Customization JS
    • 35. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Conclusions & Advice • Use JavaScript controllers • Turn on Share client debug • Develop on two Tomcats • Don’t deploy to Share as a JAR • Incorporate minification into your build up-front • Learn something about YUI, JavaScript closures • Extend, override, augment. Replace as last resort • Actions, Behaviors, & Form Filters are your friends Source: hiram_college Helpful tools: •curl •Firebug •Tamper Data •www.jsonlint.com •Rhino command-line Helpful tools: •curl •Firebug •Tamper Data •www.jsonlint.com •Rhino command-line
    • 36. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Get Involved! • Apache Chemistry - http://incubator.apache.org/chemistry/ – OpenCMIS – cmislib – PHP CMIS Client • Django Framework – http://www.djangoproject.com/ – Django 1.0 Web Site Development (Packt), Ayman Hourieh • django-alfresco on Google Code (non-CMIS) – http://code.google.com/p/django-alfresco/ • Drupal CMIS Module – http://drupal.org/project/cmis • Spring Surf – http://www.springsurf.org
    • 37. THANK YOU! Tweet me with questions/feedback @jeffpotts01 Get up to speed and stay informed with Alfresco news, tips, & tutorials!