SlideShare a Scribd company logo
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 Tale of Two Frameworks: Surf vs. Django
• Heavy Share Customization: A real-world example
• Conclusions & Advice
PATTERNS OF ALFRESCO
CUSTOMIZATION
© 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
© 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, 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
© 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
© 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”
© 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
© 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.
© 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
© 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
© 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
© 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
© 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
© 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)
© 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
© 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
© 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
© 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
HEAVY SHARE
CUSTOMIZATION
© 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
© 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
© 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
© 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,552 lines
t = 192,925 lines t = 118,586 lines
Share LOC Share JS
Customization
LOC
Customization
JS
© 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
© 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
THANK YOU!
Tweet me with questions/feedback @jeffpotts01
Get up to speed and stay informed
with Alfresco news, tips, & tutorials!

More Related Content

PPTX
OpenCMIS Part 1
PPTX
Getting Started with CMIS
PPTX
Getting Started With CMIS
PDF
PLAT-1 CMIS in the Real World
PDF
PLAT-2 CMIS - What’s coming next?
PPTX
CMIS Introduction
PDF
BP-7 Share Customization Best Practices
PPT
Intro To Alfresco Part 1
OpenCMIS Part 1
Getting Started with CMIS
Getting Started With CMIS
PLAT-1 CMIS in the Real World
PLAT-2 CMIS - What’s coming next?
CMIS Introduction
BP-7 Share Customization Best Practices
Intro To Alfresco Part 1

What's hot (20)

PDF
Connecting Content Management Applications with CMIS
PDF
CUST-2 New Client Configuration & Extension Points in Share
PDF
WCM-5 WCM Solutions with Drupal and Alfresco
PPTX
Connecting Content Management Apps with CMIS
PPT
Intro To Alfresco Part 2
PPTX
Web Apps atop a Content Repository
PPTX
Intro to Alfresco for Developers
PPTX
Alfresco 5.0 Technology Review
PPT
Alfresco Architecture
PDF
Spring In Alfresco Ecm
PDF
CQ 5.4 Deep-Dive
PPTX
Rapid RESTful Web Applications with Apache Sling and Jackrabbit
PPTX
Survey of restful web services frameworks
PPTX
AEM (CQ) Dispatcher Caching Webinar 2013
PPTX
AEM (CQ) Dispatcher Security and CDN+Browser Caching
PPTX
Integrating Microservices with Apache Camel
PDF
Crx 2.2 Deep-Dive
PDF
facebook architecture for 600M users
PPTX
Gabriele Columbro - Maurizio Pillitu - Get your Alfresco project from Zero to...
PDF
FATC UK - Real time collaborative Flex apps
Connecting Content Management Applications with CMIS
CUST-2 New Client Configuration & Extension Points in Share
WCM-5 WCM Solutions with Drupal and Alfresco
Connecting Content Management Apps with CMIS
Intro To Alfresco Part 2
Web Apps atop a Content Repository
Intro to Alfresco for Developers
Alfresco 5.0 Technology Review
Alfresco Architecture
Spring In Alfresco Ecm
CQ 5.4 Deep-Dive
Rapid RESTful Web Applications with Apache Sling and Jackrabbit
Survey of restful web services frameworks
AEM (CQ) Dispatcher Caching Webinar 2013
AEM (CQ) Dispatcher Security and CDN+Browser Caching
Integrating Microservices with Apache Camel
Crx 2.2 Deep-Dive
facebook architecture for 600M users
Gabriele Columbro - Maurizio Pillitu - Get your Alfresco project from Zero to...
FATC UK - Real time collaborative Flex apps
Ad

Viewers also liked (15)

PDF
A Match Made In The Cloud
PDF
Contributing to drupal
PPTX
Workflow Initiative
PPT
Drupal Single Page Website
PPT
More better core profiles
PPTX
Using Empathy Maps to Better Understand your Jury - Drupal Camp London 2015
PDF
Multilenguaje en Drupal 8
PDF
Contribuir en Drupal: Por dónde empiezo?
PDF
Faster Drupal sites using Queue API
PDF
Life after the hack
PDF
Drupal and Devops , the Survey Results
PDF
Crowds and Creativity
PDF
Better understanding your prospects, clients, stakeholders and end users usin...
PDF
Could Alfresco Survive a Zombie Attack?
PDF
Introducing Assetic: Asset Management for PHP 5.3
A Match Made In The Cloud
Contributing to drupal
Workflow Initiative
Drupal Single Page Website
More better core profiles
Using Empathy Maps to Better Understand your Jury - Drupal Camp London 2015
Multilenguaje en Drupal 8
Contribuir en Drupal: Por dónde empiezo?
Faster Drupal sites using Queue API
Life after the hack
Drupal and Devops , the Survey Results
Crowds and Creativity
Better understanding your prospects, clients, stakeholders and end users usin...
Could Alfresco Survive a Zombie Attack?
Introducing Assetic: Asset Management for PHP 5.3
Ad

Similar to Alfresco from an agile framework perspective (20)

PDF
An Introduction to Tornado
PPT
Web2 And Java
PDF
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
PDF
HTML5, just another presentation :)
PDF
Advanced guide to develop ajax applications using dojo
PDF
Django Overview
PDF
Challenges of Simple Documents: When Basic isn't so Basic - Cassandra Targett...
KEY
Darwin web standards
PPTX
From WordPress With Love
PDF
Frontend for developers
PPT
WordPress theme frameworks
PPT
Site Manager rocks!
PDF
Django introduction @ UGent
PDF
T5 Oli Aro
KEY
2022 HTML5: The future is now
PPT
Getting Started with Drupal
PDF
GDG Addis - An Introduction to Django and App Engine
KEY
Html5 Brown Bag
PPTX
Smwcon spring2011 tutorial applied semantic mediawiki
PPT
Drupal - Introduction to Drupal and Web Content Management
An Introduction to Tornado
Web2 And Java
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
HTML5, just another presentation :)
Advanced guide to develop ajax applications using dojo
Django Overview
Challenges of Simple Documents: When Basic isn't so Basic - Cassandra Targett...
Darwin web standards
From WordPress With Love
Frontend for developers
WordPress theme frameworks
Site Manager rocks!
Django introduction @ UGent
T5 Oli Aro
2022 HTML5: The future is now
Getting Started with Drupal
GDG Addis - An Introduction to Django and App Engine
Html5 Brown Bag
Smwcon spring2011 tutorial applied semantic mediawiki
Drupal - Introduction to Drupal and Web Content Management

More from Jeff Potts (20)

PPTX
No Docker? No Problem: Automating installation and config with Ansible
PPTX
Moving From Actions & Behaviors to Microservices
PPTX
Flexible Permissions Management with ACL Templates
PPTX
Moving Gigantic Files Into and Out of the Alfresco Repository
PPTX
The Challenges of Keeping Bees
PPTX
Alfresco: What every developer should know
PPTX
CMIS: An Open API for Managing Content
PPTX
Apache Chemistry in Action: Using CMIS and your favorite language to unlock c...
PPTX
Alfresco: The Story of How Open Source Disrupted the ECM Market
PPTX
Join the Alfresco community
PPTX
Intro to the Alfresco Public API
PPTX
Apache Chemistry in Action
PPTX
Building Content-Rich Java Apps in the Cloud with the Alfresco API
PPTX
Alfresco Community Survey 2012 Results
PPTX
Relational Won't Cut It: Architecting Content Centric Apps
PPTX
Alfresco SAUG: State of ECM
PPTX
Alfresco SAUG: CMIS & Integrations
PDF
Should You Attend Alfresco Devcon 2011
PPTX
2011 Alfresco Community Survey Results
PPTX
Good Chemistry: Alfresco, JBoss and CMIS
No Docker? No Problem: Automating installation and config with Ansible
Moving From Actions & Behaviors to Microservices
Flexible Permissions Management with ACL Templates
Moving Gigantic Files Into and Out of the Alfresco Repository
The Challenges of Keeping Bees
Alfresco: What every developer should know
CMIS: An Open API for Managing Content
Apache Chemistry in Action: Using CMIS and your favorite language to unlock c...
Alfresco: The Story of How Open Source Disrupted the ECM Market
Join the Alfresco community
Intro to the Alfresco Public API
Apache Chemistry in Action
Building Content-Rich Java Apps in the Cloud with the Alfresco API
Alfresco Community Survey 2012 Results
Relational Won't Cut It: Architecting Content Centric Apps
Alfresco SAUG: State of ECM
Alfresco SAUG: CMIS & Integrations
Should You Attend Alfresco Devcon 2011
2011 Alfresco Community Survey Results
Good Chemistry: Alfresco, JBoss and CMIS

Recently uploaded (20)

PPTX
Big Data Technologies - Introduction.pptx
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PDF
Encapsulation theory and applications.pdf
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
sap open course for s4hana steps from ECC to s4
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Machine learning based COVID-19 study performance prediction
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPT
Teaching material agriculture food technology
Big Data Technologies - Introduction.pptx
NewMind AI Weekly Chronicles - August'25 Week I
Encapsulation theory and applications.pdf
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Chapter 3 Spatial Domain Image Processing.pdf
Dropbox Q2 2025 Financial Results & Investor Presentation
The AUB Centre for AI in Media Proposal.docx
sap open course for s4hana steps from ECC to s4
Programs and apps: productivity, graphics, security and other tools
Per capita expenditure prediction using model stacking based on satellite ima...
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Building Integrated photovoltaic BIPV_UPV.pdf
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
“AI and Expert System Decision Support & Business Intelligence Systems”
Machine learning based COVID-19 study performance prediction
MIND Revenue Release Quarter 2 2025 Press Release
The Rise and Fall of 3GPP – Time for a Sabbatical?
Diabetes mellitus diagnosis method based random forest with bat algorithm
Teaching material agriculture food technology

Alfresco from an agile framework perspective

  • 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
  • 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
  • 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!

Editor's Notes

  • #35: LOC count excludes YUI, TinyMCE, Share/Surf Java source Server-side JavaScript total includes both Share tier and Repository tier JavaScript