Alfresco from an agile framework
perspective
Jeff Potts
jpotts@metaversant.com
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Agenda
• Patterns of Alfresco Customization
• A Tal...
PATTERNS OF ALFRESCO
CUSTOMIZATION
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Custom Alfresco Patterns
• Non-Alfresco framework o...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Non-Alfresco Framework
Source: Optaros
+
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Surf on Alfresco
Source: Optaros
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Light Share Customizations
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Heavy Share Customizations
A TALE OF TWO
FRAMEWORKS
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Surf or Something Else?
• Share is a popular, exten...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
A word on agile frameworks
• Agile frameworks and s...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Common requirements
• Let content authors create "c...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
A simple example: To Do
• Basic requirements
– End ...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Approaches
• To Do’s, Users, and Files are objects....
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Five-minute look at Django
• Creating a new Django ...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Model
from django.db import models
from django.cont...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
URLs map to Views
urlpatterns = patterns('',
(r'^ad...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
<html>
<head>
<title>Django To Do's | {% block titl...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Alfresco approach
• Content Consumer UI
– Custom Su...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Alfresco approach
• Business Logic
– Share web scri...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Demo: A tale of two frameworks
• Share site
• Data ...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Work Remaining
• Add file upload to both Django and...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Comparison
• Both have decent tooling
– pydev for D...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Comparison (cont’d)
• Gotchas
– Lack of query-able ...
HEAVY SHARE
CUSTOMIZATION
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
A real-world example
• SaaS platform wants a commun...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Architecture
Lightly
customized Share
Admin UI Cons...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Data Model
Global Share
Site
Client Share
Sites
Pro...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Content Consumer UI
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Content Chunks
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
File Resources
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Administrative UI
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Customization by the Numbers
t = 17,153 lines t = 6...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Conclusions & Advice
• Use JavaScript controllers
•...
© Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
Get Involved!
• Apache Chemistry - http://incubator...
THANK YOU!
Tweet me with questions/feedback @jeffpotts01
Get up to speed and stay informed
with Alfresco news, tips, & tut...
Upcoming SlideShare
Loading in...5
×

Alfresco from an agile framework perspective

2,985

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 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,985
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
77
Comments
0
Likes
1
Embeds 0
No embeds

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
  • Alfresco from an agile framework perspective

    1. 1. Alfresco from an agile framework perspective Jeff Potts jpotts@metaversant.com
    2. 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. 3. PATTERNS OF ALFRESCO CUSTOMIZATION
    4. 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. 5. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Non-Alfresco Framework Source: Optaros +
    6. 6. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Surf on Alfresco Source: Optaros
    7. 7. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Light Share Customizations
    8. 8. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Heavy Share Customizations
    9. 9. A TALE OF TWO FRAMEWORKS
    10. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 25. HEAVY SHARE CUSTOMIZATION
    26. 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. 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. 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. 29. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Content Consumer UI
    30. 30. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Content Chunks
    31. 31. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com File Resources
    32. 32. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com
    33. 33. © Copyright 2010, Metaversant Group, Inc. | http://www.metaversant.com Administrative UI
    34. 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. 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. 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. 37. THANK YOU! Tweet me with questions/feedback @jeffpotts01 Get up to speed and stay informed with Alfresco news, tips, & tutorials!
    1. A particular slide catching your eye?

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

    ×