prettyfaces: simplified jsf navigation, actions, and url-rewriting: lincoln baxter iii
DESCRIPTION
Java EE is already the perfect solution for complex business/enterprise systems, and the improvements in JavaServer Faces 2.x provide the perfect chance to reach out to the consumer and small business market; JSF is easier to use than it's ever been before, now making it accessible to businesses of all sizes. In order to complete the user-experience, however, one must not overlook the URL. How PrettyFaces works: The talk introduces you to URL rewriting, storing contextual information – safely – and managing page configuration data with address and query parameters. PrettyFaces’ centralized approach uses URLs to retain the state of pages, meaning less information must be stored in session and application scoped beans. Rethinking navigation: Navigation from the eye of the client. JSF supports page flows well, but managing simple transitions from one page to another can be complex. Examples of PrettyFaces integrated navigation, hyper-linking via Bijection and Components will show how developers gain increased control over all aspects of navigation out of the box, and how this is accomplished without extra configuration. SEO: You will be presented with brief concepts of how to improve client experience, search rank, and conversions through URL parameterization and linking – the importance the browser URL plays an in establishing trust through all client interactions. Examples & Community: What better to wrap up a presentation other than real examples of how to use and tie together what you’ve learned? A few short demos will be followed up with a brief summary of what’s coming up in the URL-rewriting community, how new advancements will benefit everyone, and what we can all do to keep advancement coming.TRANSCRIPT
Lincoln Baxter IIIhttp://ocpsoft.com
Lincoln Baxter IIIhttp://ocpsoft.com
PrettyFacesSimplified JSF Navigation, Actions, and URL-rewriting.
Lincoln Baxter IIIhttp://ocpsoft.com
( At this time, the audience is encouraged to use PDAs, cell phones, and other portable electronic devices... )
#jaxconf #prettyfaces
Lincoln Baxter IIIhttp://ocpsoft.com
/ PrettyFaces/ background/ basics/ navigation
/ demos/ wrap-up
Lincoln Baxter IIIhttp://ocpsoft.com
“A URL rewriting extension for Servlet containers, Java EE, with optional tight-integration for JSF and
other frameworks.”
Lincoln Baxter IIIhttp://ocpsoft.com
http://example.com/faces/store.jsf
http://example.com/store
Lincoln Baxter IIIhttp://ocpsoft.com
http://example.com/faces/item.xhtml?item=Z34SD498
http://example.com/store/item/Z34SD498
Lincoln Baxter IIIhttp://ocpsoft.com
/ PrettyFaces/ background/ basics/ navigation
/ demos/ wrap-up
Lincoln Baxter IIIhttp://ocpsoft.com
Initially
a bookmarking extension for JSF 1.2
Grown
a feature-rich URL-rewriting solution
Evolved
supports pure Servlet and Java EE
Future
a JSR for URL-rewriting in Java EE
Lincoln Baxter IIIhttp://ocpsoft.com
Why Pretty URLs?
•Build trust
•Enhance user experience
•Self-promote
Lincoln Baxter IIIhttp://ocpsoft.com
/ PrettyFaces/ background/ basics/ navigation
/ demos/ wrap-up
Lincoln Baxter IIIhttp://ocpsoft.com
/ PrettyFaces/ background/ basics/ navigation
/ demos/ wrap-up
/ clean/ parameterize/ load
Lincoln Baxter IIIhttp://ocpsoft.com
Build trust by reducing clutter.
Before:
http://example.com/news.xhtml?p=my-new-post
After:
http://example.com/news/my-new-post/
Lincoln Baxter IIIhttp://ocpsoft.com
http://www.llbean.com/webapp/wcs/stores/servlet/CategoryDisplay?categoryId=28&storeId=1&catalogId=1&langId=-1&nav=hp-gndp
http://www.llbean.com/webapp/wcs/stores/servlet/CategoryDisplay?categoryId=28&storeId=1&catalogId=1&langId=-1&nav=hp-gndp
Vulnerable!
Cluttered!
Real-life:wtf?
wtf?
Lincoln Baxter IIIhttp://ocpsoft.com
Should have been:
http://llbean.com/kids
Lincoln Baxter IIIhttp://ocpsoft.com
<url-mapping><pattern value=”/kids” /><view-id value=”/webapp/wcs/stores/servlet/CategoryDisplay?categoryId=28“ />
</url-mapping>
Lincoln Baxter IIIhttp://ocpsoft.com
A fictitious, malicious example:
http://acme.com/store& catCode=ZfSd41& lang=en_US& account=lincolnthree& autoLoginCd=S3fds94Zd03& oneClickPurchase=true& item=veryExpensive& redirectAfter=www.google.com?q=Have+a+nice+day+sucker!
$$$$!!! or... $#@!
Lincoln Baxter IIIhttp://ocpsoft.com
Clean that URL.Why do you think people are afraid of buying used cars?
Lincoln Baxter IIIhttp://ocpsoft.com
http://www.youtube.com/watch?v=dQw4w9WgXcQ
Trust Me?
Lincoln Baxter IIIhttp://ocpsoft.com
http://www.linkedin.com/in/lincolnthreehttp://twitter.com/lincolnthree http://ocpsoft.com/prettyfaces/
Trust Me.
Lincoln Baxter IIIhttp://ocpsoft.com
A clean, readable URL:
•Builds trust
•Is self-promoting, benefits SEO
•Reduces vulnerability
Lincoln Baxter IIIhttp://ocpsoft.com
/ PrettyFaces/ background/ basics/ navigation
/ demos/ wrap-up
/ clean/ parameterize/ load
Lincoln Baxter IIIhttp://ocpsoft.com
/ root / the / user
•Be consistent, always.
•Be general, progress to specific.
•Think hard about using a query string.
Lincoln Baxter IIIhttp://ocpsoft.com
•Where you are, what you're looking at.
•In the “request” scope; relevant.
•User accessible!
The URL and p14n are:
Lincoln Baxter IIIhttp://ocpsoft.com
http://example.com/storehttp://example.com/store/item/12http://example.com/store/item/12/reviewshttp://example.com/store/item/12/reviews/34
Bad :(http://example.com/store/12/reviews/23/item
Examples:
Good :)
Lincoln Baxter IIIhttp://ocpsoft.com
<url-mapping><pattern value=”/store/item/#{ itemBean.number }” /><view-id value=”/faces/item.xhtml“ >
</url-mapping>
Inject directly.
Lincoln Baxter IIIhttp://ocpsoft.com
<url-mapping><pattern value=”/store/item/#{ number }” /><view-id value=”/faces/item.xhtml” />
</url-mapping>
Add a request parameter.
item.xhtml?number=#{...}
Lincoln Baxter IIIhttp://ocpsoft.com
<url-mapping><pattern value=”/store/item/#{ number : itemBean.number }” /><view-id value=”/faces/item.xhtml” />
</url-mapping>
Both.
Lincoln Baxter IIIhttp://ocpsoft.com
/ PrettyFaces/ background/ basics/ navigation
/ demos/ wrap-up
/ clean/ parameterize/ load
Lincoln Baxter IIIhttp://ocpsoft.com
Loading your data.
•Eagerly (On construction)
•Lazily (On access)
•Declaratively (On event, or request)
Lincoln Baxter IIIhttp://ocpsoft.com
Nothing fancy.
<url-mapping><pattern value=”/store/item/#{itemBean.number}” /><view-id value=”/faces/store/view.xhtml” /><action> #{ currentProjectBean.load } </action>
</url-mapping>
Lincoln Baxter IIIhttp://ocpsoft.com
You decide.
<url-mapping><pattern value=”/store/item/#{itemBean.number}” /><view-id value=”/faces/store/view.xhtml” /><action phaseId=”RENDER_RESPONSE”>
#{ currentProjectBean.load } </action>
</url-mapping>
Lincoln Baxter IIIhttp://ocpsoft.com
Alternatives.
2.0 viewparams
Url RewriteFilter
2.0 eventlisteners
1.x: requiresseam or other
More Configuration
+3 +8 +1+n +4Lines:
pretty-config.xml
= ~4 :)
PrettyFaces
= ~17!
Lincoln Baxter IIIhttp://ocpsoft.com
Annotations
@Named@RequestScoped@URLMapping(
id = "barcode", pattern = "/#{ /[0-9]+/ barcodeBean.value }.png",
viewId = "/barcode.jsf")
public class BarcodeBean{ private String value;
@URLAction(phaseId=PhaseId.RENDER_RESPONSE) public void load() throws IOException { // do the work }}
Lincoln Baxter IIIhttp://ocpsoft.com
@ViewConfigpublic interface MyAppViewConfig {
static enum Pages {
@ViewPattern("/admin.xhtml") @Admin ADMIN, @ViewPattern("/item.xhtml") @UrlMapping(pattern="/item/#{id}/") @Owner ITEM, @ViewPattern("/*") @FacesRedirect @AccessDeniedView("/denied.xhtml") @LoginView("/login.xhtml") ALL; }}
SeamFaces @ViewConfig
Lincoln Baxter IIIhttp://ocpsoft.com
Your own source!
com.ocpsoft.pretty.faces.spi.ConfigurationProvider
Lincoln Baxter IIIhttp://ocpsoft.com
The Basics.
•Clean that URL! - build trust, self promote.
•Parameterize logically, in order – root the user
•Load data declaratively (Validate everything)
•You choose the configuration!
Lincoln Baxter IIIhttp://ocpsoft.com
/ PrettyFaces/ background/ basics/ navigation
/ demos/ wrap-up
Lincoln Baxter IIIhttp://ocpsoft.com
<navigation-rule> <from-view-id> * </from-view-id> <navigation-case> <from-action> * </from-action> <from-outcome> viewStore </from-outcome> <to-view-id> /faces/store/view.xhtml </to-view-id> <redirect /> </navigation-case></navigation-rule>
<h:commandLink action=”viewStore” value=”Go to store> <f:setPropertyActionListener target=”#{itemBean.name}” value=”prettyfaces” /></h:commandLink>
Lincoln Baxter IIIhttp://ocpsoft.com
<h:link action=”/faces/item.xhtml”> <f:param name=”item” value=”prettyfaces”/></h:link>
<f:metadata> <f:viewParam name=”item” value=”#{itemBean.number}” /></f:metadata>
Lincoln Baxter IIIhttp://ocpsoft.com
That Same Configuration.
<url-mapping id=”viewStore”><pattern value=”/store/item/#{ item : itemBean.number }” /><view-id value=”/faces/item.xhtml” />
</url-mapping>
The Mapping ID:
<pretty:link mappingId=”viewStore”> <f:param value=”prettyfaces”/></pretty:link>
Renders: /store/item/prettyfaces
Lincoln Baxter IIIhttp://ocpsoft.com
Go where you want.
private String createItem(){
if(dao.createItem(newitem)){
itemBean.setItem(newitem.getId());return “pretty:viewItem”;
}FacesUtils.addError(“Something went wrong! Try again.”);return “pretty:”;
}
Lincoln Baxter IIIhttp://ocpsoft.com
Or... do “nothing.”
•Write a normal Java EE / JSF 2.0 application.
•Add PrettyFaces outbound URL-rewriting.
•Request-parameter mapping #{name} is power.
Lincoln Baxter IIIhttp://ocpsoft.com
Look familiar?
<h:link outcome=”/item.xhtml”> <f:param name=”item” value=”prettyfaces”/></h:link>
Renders: /store/item/prettyfaces
Lincoln Baxter IIIhttp://ocpsoft.com
<url-mapping id=”viewStore”><pattern value=”/item/#{ item }” /><view-id value=”/faces/item.xhtml” />
</url-mapping>
http://example.com/store/item/23
http://example.com/faces/item.xhtml ? item=23
inbound outbound
Lincoln Baxter IIIhttp://ocpsoft.com
In summary.
•You do not need to use pretty-navigation or links.
•But they're there if you want them
•PrettyFaces is non-invasive... seriously.
Lincoln Baxter IIIhttp://ocpsoft.com
/ PrettyFaces/ background/ basics/ navigation
/ demos/ wrap-up
Lincoln Baxter IIIhttp://ocpsoft.com
/ PrettyFaces/ background/ basics/ navigation
/ demos ? plan for change=true
/ wrap-up
Lincoln Baxter IIIhttp://ocpsoft.com
/ PrettyFaces/ background/ basics/ navigation
/ demos/ wrap-up
Lincoln Baxter IIIhttp://ocpsoft.com
PrettyFaces in two minutes.“A masterpiece.” ~non-fictional user.
Lincoln Baxter IIIhttp://ocpsoft.com
Add PrettyFaces
via Maven.
<dependency> <groupId>com.ocpsoft</groupId> <artifactId>prettyfaces-jsf2</artifactId> <version>${most-recent-version}</version></dependency>
Yeah this works with pure Servlets, too. I know...
Lincoln Baxter IIIhttp://ocpsoft.com
Add PrettyFaces
via Seam Forge.
$ forge git-plugin git://github.com/ocpsoft/prettyfaces-forge-plugin.git
$ setup prettyfaces
$ prettyfaces mapping –pattern {...} --resource {...}
Lincoln Baxter IIIhttp://ocpsoft.com
Map something.
Create /WEB-INF/pretty-config.xml
<pretty-config>
<!-- Begin Mappings --> <url-mapping id="home"> <pattern value="/home" /> <view-id value="/faces/home.jsf" > </url-mapping>
<url-mapping id="viewComment"> <pattern value="/story/#{myBean.currentStoryId}/#{myBean.commentId}" /> <view-id value="/faces/story/comment.jsf" > </url-mapping>
</pretty-config>
Lincoln Baxter IIIhttp://ocpsoft.com
Make it work.
Take action ;)
<pretty-config>
<!-- Begin Mappings --> <url-mapping id="home"> <pattern value="/home" /> <view-id value="/faces/home.jsf”> <action> #{homeBean.loadUserLayout} </action> </url-mapping>
<url-mapping id="viewComment"> <pattern value="/story/#{myBean.currentStoryId}/#{myBean.commentId}" /> <view-id value="/faces/story/comment.jsf” /> </url-mapping>
</pretty-config>
Lincoln Baxter IIIhttp://ocpsoft.com
Navigate.
../viewComment.jsf
<html xmlns:pretty="http://ocpsoft.com/prettyfaces" >
<pretty:link mappingId="comment"> <f:param value="23" /> <f:param value="5" /> Go to Comment. (This is Link Text)</pretty:link>
<h:link outcome="pretty:comment"> <f:param name="sid" value="#{myBean.storyId}" /> <f:param name="cid" value="#{myBean.nextCommentId}" /> View next comment. (This is Link Text)</h:link>
Lincoln Baxter IIIhttp://ocpsoft.com
The Site-map.
If this presentation were a website...<pretty-config>
<url-mapping id="home"> <pattern value=”/prettyfaces” /> <view-id value=”faces/home.jsf” /> </url-mapping>
<url-mapping id="levelOne"> <pattern value=”/prettyfaces/#{presBean.levelOne}” /> <view-id value=”/faces/present.jsf” /> </url-mapping>
<url-mapping id="levelTwo"> <pattern value=”/prettyfaces/#{presBean.levelOne}/#{presBean.levelTwo}” /> <view-id value=”/faces/present.jsf” /> </url-mapping>
</pretty-config>
Lincoln Baxter IIIhttp://ocpsoft.com
/ PrettyFaces/ background/ basics/ navigation
/ demo/ wrap-up
Lincoln Baxter IIIhttp://ocpsoft.com
PrettyFaces is...
● URL-rewriting● URL-parameterization● Action-framework for JSF (Servlet soon)● Navigation framework for JSF (Servlet soon)● Extendable, configurable (SPI is growing!)● Waiting for your ideas!
Lincoln Baxter IIIhttp://ocpsoft.com
Get Involved!
Get Started
http://ocpsoft.com/prettyfaces/
Get Help
http://ocpsoft.com/support/
Get the code!
http://github.com/ocpsoft/prettyfaces
Lincoln Baxter IIIhttp://ocpsoft.com
PrettyFaces is...
“Beautiful Java EE: URL-rewriting for the next generation web-user”
Lincoln Baxter IIIhttp://ocpsoft.com
Questions.I've been talking for nearly an hour; please,
somebody say something.
“wtf?”