Web applications implemented with
multiple web frameworks
preserving a consistent experience
Senior Software Engineer at Red Hat
RichFaces Project Lead
We want to mix web frameworks so we can:
modernize a legacy application
accomodate teams with disparate expertise
use the best tool for the job
Client-side
Consistent L&F
Consistent behaviour
Server-side
Shared state
Programming model
Web-framework independent
Re-usable accross frameworks
Bootstrap: http://twitter.github.com/bootstrap
Foundation: http://foundation.zurb.com/
GroundWorkCSS: http://groundwork.sidereel.com
Ink: http://ink.sapo.pt/
Gumby: http://gumbyframework.com/
Maxmertkit: http://www.maxmert.com/
Responsive Grid System: http://www.responsivegridsystem.com/
http://twitter.github.io/bootstrap/scaffolding.html
http://twitter.github.io/bootstrap/base-css.html
http://twitter.github.io/bootstrap/components.html
http://twitter.github.io/bootstrap/customize.html#variables
@nice-blue: #5B83AD;
@light-blue: (@nice-blue + #111);
#header { color: @light-blue; }
css output:
#header { color: #6c94be; }
.bordered {
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
mix in:
#menu a {
color: #111;
.bordered;
}
.post a {
color: red;
.bordered;
}
.border-radius (@radius) {
border-radius: @radius;
-moz-border-radius: @radius;
-webkit-border-radius: @radius;
}
mix in:
#header {
.border-radius(4px);
}
.button {
.border-radius(6px);
}
#header {
color: black;
}
#header .navigation {
font-size: 12px;
}
#header .logo {
width: 300px;
}
#header .logo:hover {
text-decoration: none;
}
#header {
color: black;
.navigation {
font-size: 12px;
}
.logo {
width: 300px;
&:hover {text-decoration: none}
}
}
@base: 5%;
@filler: (@base * 2);
@other: (@base + @filler);
color: (#888 / 4);
background-color: (@base-color + #111);
height: (100% / 2 + @filler);
@base: #f04615;
@width: 0.5;
.class {
width: percentage(0.5); // returns `50%`
color: saturate(@base, 5%);
background-color: spin(lighten(@base, 25%), 8);
}
Javascript:
Java (less.js via rhino):
@import "lib/bootstrap/less/variables.less";
@import "lib/bootstrap/less/mixins.less";
.skin {
.rf-ac, .rf-ac-itm-hdr, .rf-ac-itm-cnt, .rf-ac-itm-hdr {
font-size: @baseFontSize;
font-family: @baseFontFamily;
line-height: @baseLineHeight;
border-color: @navbarBorder;
background-color: @white;
border: none;
}
.rf-ac {
border: 1px solid @navbarBorder;
border-top: none;
.border-radius(@baseBorderRadius);
overflow:hidden;
}
.rf-ac-itm-hdr {
border-top: 1px solid @navbarBorder;
background-image: none;
padding: 5px 15px;
color: @linkColor;
}
.rf-ac-itm-cnt {
border-top: 1px solid @navbarBorder;
padding: 10px 16px;
}
}
Behaviour
"Moving" parts
Standalone javascript widgets
Framework independent
Used in RichFaces 5
Event based architecture
Loosely coupled to backend framework
PickList Widget:
Shared server state
Consistent programming model
Front-end independent
Retrieve a contextual instance of a Bean
public class CapitalsObserver {
@Inject
CapitalsBean capitalsBean;
@Inject @Push(topic = "capitalsSelected")
private Event jsfEvent;
...
}
Scope:
determines lifecycle of instances
maps clients to instances
Context:
implements the scope
@SessionScoped @RequestScoped @DependentScoped @ConversationScoped @ApplicationScoped
...
@SessionScoped
public class CapitalsBean {
...
@PostConstruct
public void init() {
selectedCapitals = new ArrayList();
selectedCapitals.add(capitals.get(0));
}
...
}
Event producer:
public class CapitalsBean {
@Inject @Server
private Event serverEvent;
...
public void setSelectedCapitals(List selected) {
this.selectedCapitals = selected;
serverEvent.fire(new CapitalsSelected(selected));
}
}
Event observer:
public class CapitalsObserver {
public void observeClientEvent(
@Observes @Client
CapitalsSelected capitalsSelected) {
...
}
public void observeServerEvent(
@Observes @Server
CapitalsSelected capitalsSelected) {
...
}
}
Project: |
|
Twitter (me): |
|
Google+: |
|
Forums: |
|
IRC |
#richfaces |
Slides: |