A first presentation of the Dandelion project, recently released in v0.10.0.
Slides are available online here: http://dandelion.github.io/slides/dandelion-0.10.0
3. Quick introduction
Free & Open Source Java framework
Focused on two aspects of Web development:
Assets management (js, css): organization in bundles, HTML
injection, soon asset minification and merging
Integration of powerful Javascript librairies thanks to a set of
components
Licensed under BSD 3-Clause
Hosted on Github
Current version: 0.10.0
3 / 101
9. Asset bundles
Declarative approach, via JSON (soon XML and JavaConfig)
{
"bundle":"jquery",
"assets":[
{
"name":"jquery",
"version":"1.11.1",
"type":"js",
"locations":{
"webapp":"/assets/js/jquery-1.11.1.js"
}
}
]
}
Several locations are allowed for each asset: webapp, classpath, CDN, JAR,
WebJar and API!
See the docs
9 / 101
10. Dependencies between bundles
You can declare one or more bundles as dependencies
{
"bundle":"select2",
"dependencies":["jquery"],
"assets":[
{
"name":"select2",
"version":"3.4.8",
"type":"js",
"locations":{
"webapp":"/assets/js/select2.js"
}
},{
"name":"select2",
"version":"3.4.8",
"type":"css",
"locations":{
"webapp":"/assets/css/select2.css"
}
}
]
}
10 / 101
11. Asset locators
Internal components used by Dandelion to fetch assets in
different ways
Used via the corresponding location key in the bundle declaration
See the docs
11 / 101
22. JAR
Bundle
HTML
Inside a Servlet 2.0+ container:
<scriptsrc="/[contextPath]
/dandelion-assets
/[cacheKey]
/app.js"></script>
Inside a Servlet 3.0+ container:
<scriptsrc="/[contextPath]/folder/js/app.js"></script>
Dandelion automatically detects whether the
running server is using the Servlet 3.x API or lower
Asset locators — jar
22 / 101
26. New
dependency
WebJar
Bundle
HTML
Inside a Servlet 2.0+ container:
<linkrel="stylesheet"href="/[contextPath]
/dandelion-assets
/[cacheKey]
/bootstrap.css"/>
Inside a Servlet 3.0+ container:
<linkrel="stylesheet"href="/[contextPath]
/webjars
/bootstrap
/3.2.0
/css
/bootstrap.css"/>
Dandelion automatically detects whether the
running server is using the Servlet 3.x API or lower
Asset locators — webjar
26 / 101
27. Asset locators — delegate
Reads the content of an asset from a special parameter stored inside the
AssetRequestContext
This special parameter:
must be stored under the DelegateLocator.DELEGATED_CONTENT_PARAM
key
must be a class that implements DelegatedContentand where the
getContent()method must return the asset content to be injected ]
27 / 101
32. Bundle loaders
Scan for bundles in the classpath, in the following order:
VendorBundleLoader: intended to load vendor bundles (e.g. jquery.json)
ComponentBundleLoader: intended to load components bundles (e.g. ddl-
dt.json)
DandelionBundleLoader: intended to load user bundles (e.g. custom-
bundle.json)
See the docs
32 / 101
33. Bundle graph
On the application startup, Dandelion creates a Contextthat will be injected
into each request.
This Contextprovide several information:
all configuration options (coming from the properties files)
a bundle graph (DAG), built from all scanned bundles
Example:
src
|__main
|__resources
|__dandelion
|__jquery.json
|__select2.json
See the docs
33 / 101
34. Interacting with the bundle graph
1/4) Using the JSP taglib
<%@taglibprefix="dandelion"uri="http://github.com/dandelion"%>
<dandelion:bundleincludes="select2"/>
2/4) Using the Thymeleaf dialect
<!DOCTYPEhtml>
<htmlxmlns:th="http://www.thymeleaf.org"
xmlns:ddl="http://github.com/dandelion"
ddl:bundle-includes="select2">
...
</html>
See the docs
34 / 101
35. Interacting with the bundle graph
3/4) Using the fluent API
AssetRequestContext
.get((HttpServletRequest)request)
.addBundle("select2");
4/4) Using the configuration file ("permanent" bundles)
bundle.includes=select2
See the docs
35 / 101
36. Interacting with the bundle graph
Whatever the technology used, Dandelion automatically injects all
requested assets into the HTML code:
in the right order
in the configured position, by default CSS in <head>and JS just before
</body>
and (soon) applies the right HTTP headers, therefore optimizing browser
caching
<html>
<head>
<linkhref="/context/assets/css/select2.css"/>
</head>
<body>
...
<scriptsrc="/context/assets/js/jquery-1.11.1.js"></script>
<scriptsrc="/context/assets/js/select2.js"></script>
</body>
</html>
36 / 101
37. Asset processors
Intended to process assets, in different ways...
Built-in processors:
jsMinYui:JS minification based on Yahoo's YUI Compressor
cssMinYui:CSS minification based on Yahoo's YUI Compressor
cssMin:CSS minification based on a fork of YUI
jsMin:JS minification based on a fork of YUI
cssUrlRewriting:Image URLs rewriting in CSS
Soon:
cssLess: Convert Less resources to CSS
cssSass: Convert Sass resources to CSS
cssImport: Processes @import
coffeeScript: Convert CoffeeScript to JavaScript
...
See the docs
37 / 101
38. Development/production modes
Development mode
Built-in dev tools available
Server-side caching disabled
Browser caching disabled
Production mode
No bundle graph viewer, no bundle reloading
Minification enabled
Server-side caching enabled
(soon) Browser caching enabled
(soon) GZIP compression
(soon) Asset versioning
(soon) JMX monitoring
38 / 101
39. Devtools
Bundle graph
viewer
Dev tool allowing to visualize how Dandelion-Core
handles assets, in the current request
http://example.com/context/some/uri?showGraph
Available in development mode only
See the docs
39 / 101
40. Devtools
Bundle graph
viewer
Asset
reloading
During development, both server-side and client-side
caching are disabled.
Client-side, Dandelion-Core applies the following HTTP
headers:
Cache-Control = no-cache,no-store,must-
revalidate(HTTP 1.1)
Pragma = no-cache(HTTP 1.0)
Expires = 0(Proxies)
40 / 101
41. Devtools
Bundle graph
viewer
Asset
reloading
Bundle
reloading
During development, all changes made in asset bundles
can be reflected.
Just manually append a new reloadBundlesrequest
parameter to the current URL to perform a full bundle
reloading.
http://example.com/context/some/uri?reloadBundles
Available in development mode only
41 / 101
46. Introducing Dandelion-Datatables
First and most advanced component of the Dandelion framework
Facilitates the integration of DataTables, an awesome jQuery
plugin which will add advanced interaction controls to any HTML
table
Easy to use
Easy to extend
Inspired by the excellent DisplayTag library
46 / 101
47. Key features
JSP & Thymeleaf support
Typical features such as paging, filtering and sorting
DOM sources, AJAX sources and server-side processing
Responsive design
Export in multiple formats
Several themes available: Bootstrap 2, Bootstrap 3, jQueryUI
I18n
Integration with Spring/Spring MVC and other projects
47 / 101
48. What it looks like with JSP?
<%@taglibprefix="datatables"uri="http://github.com/dandelion/datatables"%>
<datatables:tableid="myTableId"data="${persons}">
<datatables:columntitle="Id"property="id"/>
<datatables:columntitle="LastName"property="lastName"/>
<datatables:columntitle="FirstName"property="firstName"/>
<datatables:columntitle="City"property="address.town.name"/>
<datatables:columntitle="Mail"property="mail"/>
</datatables:table>
id: HTML pass-through attribute
data: DOM source, collection of POJOs
title: sets the content of the column header
property: name of the object's attribute of the collection being iterated on
48 / 101
49. What it looks like with Thymeleaf?
<tableid="myTableId"dt:table="true">
<thead>
<tr>
<th>Id</th>
<th>Firstname</th>
<th>Lastname</th>
<th>City</th>
<th>Mail</th>
</tr>
</thead>
<tbody>
<trth:each="person:${persons}">
<tdth:text="${person.id}">1</td>
<tdth:text="${person.firstName}">John</td>
<tdth:text="${person.lastName}">Doe</td>
<tdth:text="${person?.address?.town?.name}">Nobodyknows!</td>
<tdth:text="${person.mail}">john@doe.com</td>
</tr>
</tbody>
</table>
dt:table: enables the Dandelion-Datatables dialect in the current table
49 / 101
50. HTML The HTML is generated:
either by Dandelion-Datatables (JSP)
or directly by Thymeleaf
<tableid="myTableId">
<thead>
<tr>
<th>Id</th>
<th>Firstname</th>
<th>Lastname</th>
<th>City</th>
<th>Mail</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Wing</td>
<td>Cunningham</td>
<td></td>
<td>ornare.libero@mail.edu</td>
</tr>
...
</tbody>
</table>
How it works?
50 / 101
51. HTML
JavaScript
As well as the JS code that initializes DataTables
varoTable_myTableId=$('#myTableId');
varoTable_myTableId_params={
"aoColumns":[
{"mData":"id","sDefaultContent":""},
{"mData":"lastName","sDefaultContent":""},
{"mData":"firstName","sDefaultContent":""},
{"mData":"address.town.name","sDefaultContent":""},
{"mData":"mail","sDefaultContent":""}
]
}
$(document).ready(function(){
oTable_myTableId.dataTable(oTable_myTableId_params);
});
How it works?
51 / 101
52. HTML
JavaScript
Required
assets
An AssetRequestContextis filled with the required assets,
either by the JSP taglib or by the Thymeleaf dialect...
AssetRequestContext
.get(request)
.addBundle("datatables")
.addBundle("ddl-dt")
...;
... so that they will be injected by Dandelion-Core into the
response
<linkhref="//cdn/jquery.dataTables.css"/>
...
<scriptsrc="//cdn/jquery.js"></script>
<scriptsrc="//cdn/jquery.dataTables.js"></script>
<scriptsrc="/[contextPath]
/dandelion-assets
/[SHA]
/dandelion-datatables-0.10.0.js"></script>
How it works?
52 / 101
54. HTML (DOM) sources
Read data directly from the DOM
Works well with small/medium data sources
54 / 101
55. Controller Example with a Spring MVC controller
@Controller
publicclassController{
@ModelAttribute("persons")
publicList<Person>populateTable(){
returnpersonService.findAll();
}
}
HTML sources — example
55 / 101
58. AJAX sources
Read data from virtually any JSON data source that can be obtained by
AJAX
Client-side processing
Works well with small/medium data sources
58 / 101
59. Controller Example with a Spring MVC controller
@Controller
publicclassAjaxController{
@RequestMapping(value="/persons")
public@ResponseBodyList<Person>findAll(){
returnpersonService.findAll();
}
}
AJAX sources
59 / 101
62. AJAX sources + server-side processing
Read data from virtually any JSON data source that can be obtained by
AJAX
Server-side processing
Each draw of the table will result in a new AJAX request being made to
get the required data
Works well with small/medium/large data sources
62 / 101
63. AJAX sources + server-side processing
Dandelion-Datatables provides a convenient API
DatatablesCriterias
Stores all DataTables parameters (current page, entries to display,
sorted columns, ...)
@RequestMapping(value="/persons")
public@ResponseBodyDatatablesResponse<Person>
filter(HttpServletRequestrequest){
//MapsrequestparametertoaDatatablesCriteriasinstance
DatatablesCriteriascriterias=
DatatablesCriterias.getFromRequest(request);
...
63 / 101
64. AJAX sources + server-side processing
Dandelion-Datatables provides a convenient API
DataSet
All entries returned by the data access layer should be wrapped in this
class in order to build a DataTablesResponse
...
//Getfilteredandpageddata
DataSet<Person>persons=
personService.findPersons(criterias);
...
64 / 101
65. AJAX sources + server-side processing
Dandelion-Datatables provides a convenient API
DataTablesResponse
Contains a builder that helps to return the data in the format required
by DataTables
Must be converted into JSON
...
//BuildtheresponsethatwillbeconvertedtoJSON
returnDatatablesResponse.build(persons,criterias);
}
65 / 101
66. Controller Example with a Spring MVC AJAX controller
@RequestMapping(value="/persons")
public@ResponseBodyDatatablesResponse<Person>
filter(HttpServletRequestrequest){
//MapsrequestparametertoaDatatablesCriteriasinstance
DatatablesCriteriascriterias=
DatatablesCriterias.getFromRequest(request);
//Getfilteredandpageddata
DataSet<Person>persons=
personService.findPersons(criterias);
//BuildtheresponsethatwillbeconvertedtoJSON
returnDatatablesResponse.build(persons,criterias);
}
AJAX sources + server-side processing
66 / 101
71. Export — what formats?
Text-basedformats: CSV, XML
Built-in support, no dependency or extra required.
71 / 101
72. Export — what formats?
Binary-basedformats: PDF, XLS, XLSX
Some extras already exist and provide:
an export class that is used by default if the corresponding export format
is enabled
the corresponding library in compile scope (e.g. Apache POI for the XLS
format)
Available extras:
PDF: datatables-export-itext
XLS: datatables-export-poi
XLSX: datatables-export-poi-ooxml
72 / 101
73. Export — 2 ways
Filter-based
Fast to set up
Always export full data source
Only compatible with DOM sources
Controller-based
Requires a bit more work to set up
WYSIWYE => What You See Is What You ... Export!
Compatible with DOM and AJAX sources
73 / 101
97. Dandelion-
Core
Full support for asset minification and merging
Improvements on asset bundles: externalization,
configuration via XML, JavaConfig
Add new processors for meta-frameworks
(CoffeeScript, Less, ...)
Add support for conditionnal assets (e.g. IE8+, IE9+)
Add support for CSS sprites
New AssetCacheimplementation based on Hazelcast
JBoss Forge plugin allowing to scaffold a project based
on Dandelion
Add support for RequireJS
Bower integration
Future
97 / 101
98. Dandelion-
Core
Dandelion-
Datatables
New extension for editable tables (Editor, jEditable, ...)
Add support for more DataTables' extensions
Add support for DataTables 1.10.0
New theme for Foundation
Add WebSocket support for continously-updating
tables (Atmosphere, Spring MVC 4)
Add support for Spring Data REST
Future
98 / 101