GWT@Jazoon08 - Part 3/6 - Personalization & Customization
-
Upload
maarten-volders -
Category
Technology
-
view
2.856 -
download
0
description
Transcript of GWT@Jazoon08 - Part 3/6 - Personalization & Customization
LOGO SPEAKER‘S COMPANY
# 3
personalizationand customization.
LOGO SPEAKER‘S COMPANY
identify yourself with the product ...
LOGO SPEAKER‘S COMPANY
the barmaid remembering your favourite drink ...
LOGO SPEAKER‘S COMPANY
customize your drink at Starbucks ...
LOGO SPEAKER‘S COMPANY
+6.6 billion people can’t all be the same ...
LOGO SPEAKER‘S COMPANY
+/- 191 currencies ...
LOGO SPEAKER‘S COMPANY
let’s meet on 01/02/2008 ...
LOGO SPEAKER‘S COMPANYcan you pick me up at 9 o’clock ...
LOGO SPEAKER‘S COMPANY
annoying.
my favourite application doesn’t run in an OpenSocial container nor on my IPhone nor does it have offline access
LOGO SPEAKER‘S COMPANY
linker.[ overview ]
LOGO SPEAKER‘S COMPANY
linker.“In computer science, a linker is a program
that takes one or more objects generated by the compiler and assembles them into a single executable program.”
- Wikipedia
LOGO SPEAKER‘S COMPANY
objectobject objectobject objectobject
linker
iPhoneiPhoneAdobe Air
Adobe Air AndroidAndroidGearsGearsOpen
Social
OpenSocial
LOGO SPEAKER‘S COMPANY
PRIMARY LINKERS
the primary linker is responsible for module bootstrap
pre- and post-linkers run before and after the primary Linker
linkers are only run during web-mode compile
SelectionScriptLinker // Bootstrap is an external script
HostedModeLinker // Only for hosted mode
XSLinker // Cross site linker
SingleScriptLinker // Provides single JS file
IFrameLinker [default] // Loads JS in Iframe
@LinkerOrder(Order.PRIMARY)
public class IFrameLinker extends SelectionScriptLinker { … }
LOGO SPEAKER‘S COMPANY
ENABLE AN EXISTING LINKER
<add-linker name=“std”/> IFrame linker
<add-linker name=“xs”/> Cross site linker
<add-linker name=“sso”/> Single script linker
LOGO SPEAKER‘S COMPANY
ARTIFACTS
Linker operate on a set of Artifacts:
CompilationResult // unique chunk of JavaScript permutation
EmittedArtifact // emitted to output directory
GeneratedSource // GeneratorContext.tryCreateResource
PublicResource // files in public path
SyntheticArtifact // created by Linker
ScriptReference // external script ref. in .gwt.xml
StylesheetReference // external CSS ref. in .gwt.xml
Communicate with Linker stack via GeneratorContext.commitArtifact();
Linkers can transform one ArtifactSet into another
LinkerContext contains global data (module name, selection properties…)
LOGO SPEAKER‘S COMPANY
linker.[ build your own linker ]
LOGO SPEAKER‘S COMPANY
customize.synthesize additional output-dependent files Google Gears ManagedResourceStore manifest file
integrate with other environments iGoogle, OpenSocial …
provide an alternate bootstrap or packaging Gadgets and single stage bootstraps
generally solve “GWT and … “ integration
LOGO SPEAKER‘S COMPANY
BUILD YOUR OWN LINKER (1/2)
@LinkerOrder(Order.POST)
public class FileListLinker extends AbstractLinker {
public ArtifactSet link(TreeLogger logger, LinkerContext context,
ArtifactSet artifacts) throws UnableToCompleteException {
ArtifactSet toReturn = new ArtifactSet(artifacts);
toReturn.add(createFileListArtifact(toReturn));
return toReturn;
}
LOGO SPEAKER‘S COMPANY
BUILD YOUR OWN LINKER (2/2)
public Artifact createFileListArtifact(ArtifactSet toReturn) {
SortedSet<EmittedArtifact> emitted = toReturn.find(EmittedArtifact.class);
StringBuffer fileList = new StringBuffer(“<html><body>”);
for (EmittedArtifact artifact : emitted) {
fileList.append(artifact.toString() + “<br/>”);
}
fileList.append(“</body></html>”);
return emitBytes(logger, Util.getBytes(fileList.toString()), "fileList.html“));
}
LOGO SPEAKER‘S COMPANY
DEFINE THE NEW LINKER
<define-linker name=“fileListLinker" class=“com.FileListLinker" />
ENABLE THE NEW LINKER
<add-linker name=“fileListLinker”/>
LOGO SPEAKER‘S COMPANY
LOGO SPEAKER‘S COMPANY
linker.[ advanced use case ]
LOGO SPEAKER‘S COMPANY
INLINE SELECTION SCRIPT INTO HOST PAGE (1/2)
public ArtifactSet link(TreeLogger logger, LinkerContext
context, ArtifactSet artifacts) throws UnableToCompleteException {
artifacts = new ArtifactSet(artifacts);
EmittedArtifact script = getSelectionScript(artifacts); artifacts.remove(script);
for (EmittedArtifact e : artifacts.find(EmittedArtifact.class)) {
if (e.getPartialPath().toLowerCase().endsWith(".html")) {
EmittedArtifact newArtifact = replaceScripts(logger, e, script);
artifacts.replace(newArtifact); } } return artifacts;
}
LOGO SPEAKER‘S COMPANY
INLINE SELECTION SCRIPT INTO HOST PAGE (2/2)
private EmittedArtifact replaceScript(TreeLogger logger,
EmittedArtifact e, EmittedArtifact script) throws
UnableToCompleteException {
String page = Util.readStreamAsString(e.getContents(logger));
// ... replacements happen ... EmittedArtifact toReturn = emitString(logger, page,
e.getPartialPath()); return toReturn;
}
LOGO SPEAKER‘S COMPANY
localization.[ for dummies ]
LOGO SPEAKER‘S COMPANY
CREATE INTERFACE TO DEFINE TYPE-SAFE TEMPLATES
public interface ErrorMessages extends Messages {
String accessDenied(int code, String userName);
}
CREATE CORRESPONDING PROPERTY FILE
accessDenied=Error {0}: {1} cannot access {2}
LOGO SPEAKER‘S COMPANY
ADD LOCALE CHOICES TO A MODULE
<module> <inherits name=“com.google.gwt.i18n.I18N”/> <extend-property name=“locale” values=“fr”/> </module>
APPLY MESSAGE
ErrorMessages msgs = GWT.create(ErrorMessages.class);
Window.alert(msgs.accessDenied(502, username));
LOGO SPEAKER‘S COMPANY
CHOOSE A LOCALE AT RUNTIME
url based: http://localhost:808/example?locale=nl meta tag: <meta name=“gwt:property” content=“locale=fr”>
OTHER LOCALE OPTIONS
messages = templated messages constants = simple messages withLookup = extra lookup functionality dictionary = for locale data encapsulated in the page [runtime]
LOGO SPEAKER‘S COMPANY
localization.[ demystified ]
LOGO SPEAKER‘S COMPANY
CODE GENERATION
a Java source file is generated for each defined language generation is based upon the Localizable interface at runtime a property provider determines the locale based upon the ‘locale=nl’ URL argument or Meta property
no data structure in the middle no runtime loading or resolution they work because they passed the compiler format must be UTF-8 locale fallback mechanism en_US -> en -> default DateTime and NumberFormat have local backend-in
LOGO SPEAKER‘S COMPANY
COMPILER OPTIMIZATION
MyConstants constants = GWT.create(MyConstants.class); String hello = constants.hello(); Window.alert(hello);
compiles into:
$intern_2 = ‘hello’; $wnd.alert($intern_2);
and not into:
$wnd.alert(‘hello’); // some browsers actually create a new literal object
LOGO SPEAKER‘S COMPANY
localization.[ real life issues ]
LOGO SPEAKER‘S COMPANY
DYNAMIC LOCALES
locales tend to change many use cases include database driven locales
so how do we deal with runtime changing locales????
options
- locale data stored in project locale files recompile
- locale data stored in database extract to project locale files + recompile (Thread changes as bugs)
reload page + embed new locales in HTML file + Dictionary support runtime locales in the client
LOGO SPEAKER‘S COMPANY
DYNAMIC LOCALES
runtime locales in the client
Label aLabel = new Label(); // HasText
LocaleSupport.addListener(aLabel); // Updates all HasText on locale change
there goes the lazy developer .. let’s think …
But how does the LocaleSupport know that a locale has been updated? - server needs to figure out what to do ??? state on the server - poll at regular interval - piggy bagging - do I lock the client while I update all the labels ??? - or do I only update the current labels and updates the others later ??? - so the client needs to download this complete update mechanism
LOGO SPEAKER‘S COMPANY
MAARTENVOLDERS.comPASSIONATE ABOUT PEOPLE AND TECHNOLOGY