SoftShake 2013 - Vaadin componentization

1,420 views

Published on

Published in: Self Improvement, Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,420
On SlideShare
0
From Embeds
0
Number of Embeds
20
Actions
Shares
0
Downloads
13
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • skinparam dpi 150package com::vaadin::client::ui { abstract class AbstractConnector}package com::vaadin::client::extensions { abstract class AbstractExtensionConnector}package com::vaadin::server { abstract class AbstractClientConnector abstract class AbstractComponent abstract class AbstractExtension { {abstract} extend(connector:AbstractClientConnector) }}MyExtension -up-|> AbstractExtensionAbstractExtension -up-|> AbstractClientConnectorAbstractComponent -up-|> AbstractClientConnectorAbstractExtensionConnector -up-|> AbstractConnectorMyExtensionConnector -up-|> AbstractExtensionConnectorMyExtensionConnector .left.> MyExtension
  • SoftShake 2013 - Vaadin componentization

    1. 1. Vaadin Componentize your UI extension points
    2. 2. Who am I • Java (EE) Dev/Architect • Vaadin enthusiast • General blog • http://blog.frankel.ch • @nicolas_frankel • Vaadin specific • http://morevaadin.com • @learnvaadin
    3. 3. Extension points 1. Compose base components 2. Wrap GWT widgets 3. Extensions 4. Wrap JavaScript 5. Theme This presentation requires you have a bare minimum knowledge of Vaadin and how it works
    4. 4. Extension points 1. Compose base components 2. Wrap GWT widgets 3. Extensions 4. Wrap JavaScript 5. Theme
    5. 5. Composition • It can’t be that hard  Just compose… • Let’s create an Address component  And see for ourselves
    6. 6. First step public class Address extends VerticalLayout { public Address() { } } addComponent(new addComponent(new addComponent(new addComponent(new TextField("Ligne 1")); TextField("Ligne 2")); TextField("Ville")); TextField("NPA"));
    7. 7. Input vs label TextField ligne1 = new TextField(); TextField ligne2 = new TextField(); TextField ville = new TextField(); TextField npa = new TextField(); ligne1.setInputPrompt("Ligne 1"); ligne2.setInputPrompt("Ligne 2"); ville.setInputPrompt("Ville"); npa.setInputPrompt("NPA"); addComponent(ligne1); addComponent(ligne2); addComponent(ville); addComponent(npa);
    8. 8. Spacing setSpacing(true); TextField ligne1 = new TextField(); TextField ligne2 = new TextField(); TextField ville = new TextField(); TextField npa = new TextField(); ligne1.setInputPrompt("Ligne 1"); ligne2.setInputPrompt("Ligne 2"); ville.setInputPrompt("Ville"); npa.setInputPrompt("NPA"); addComponent(ligne1); addComponent(ligne2); addComponent(ville); addComponent(npa);
    9. 9. Problems?  No choice between labels and input prompts  No choice between spacing or not  i18n  Fixed layout  And so on  No configuration feature!
    10. 10. Configuration design  Expose your configuration features  Wrap the rest  As for API  Introduce middle-components for decoupling  For layout, use CustomComponent
    11. 11. public class Address extends CustomComponent { private Layout layout; private TextField ligne1 = new TextField(); // Declare other components public Address(Layout layout) { this.layout = layout; setCompositionRoot(layout); } } layout.addComponent(ligne1); // Add other components public void setSpacing(boolean spacing) {…} public boolean isSpacing() {…} public String getLigne1Caption() {…} // Other getters and setters
    12. 12. UI design vs data design Address address = new Address(); address.getLigne1().setValue("M. Nicolas Frankel"); address.getLigne2().setValue("Route du Simplon 1"); address.getVille().setValue("Paudex"); address.getNpa().setValue("1094");  Tight coupling  No abstraction  No validation as a whole  No JSR-303
    13. 13. Simple data design  An address component should display an address bean!
    14. 14. Better data design  Enable data buffering  Commit / discard
    15. 15. Even better data design
    16. 16. (Near-)Final data design  Provide a default concrete class  Help 80% of the time
    17. 17. Composition summary  Think about UI configuration  Think about the wrapped model  Make it easy for your developers, they are your users  This makes it hard for you as the designer!
    18. 18. Extension points 1. Compose base components 2. Wrap GWT widgets 3. Extensions 4. Wrap JavaScript 5. Theme
    19. 19. Connector architecture
    20. 20. Connector architecture  This let us use a server-side component  MyComponent  Displayed client-side  MyWidget
    21. 21. YouTubePlayer widget  Simple widget displaying a YouTube video  For example purpose only  Deprecated
    22. 22. YouTubePlayer server-side public class YouTubePlayer extends AbstractComponent { }
    23. 23. YouTubeConnector client-side @Connect(YouTubePlayer.class) public class YouTubeConnector extends AbstractComponentConnector { public YouTubeViewer getWidget() { return (YouTubeViewer) super.getWidget(); } } protected Widget createWidget() { return new YouTubeViewer("GOKX-bGmi0k"); }
    24. 24. Shared state
    25. 25. Shared state  Create API server-side  Create a getter/setter on the shared state  Implement onStateChanged() on the connector  Call widget’s methods accordingly
    26. 26. YouTubeState client-side public class YouTubeState extends AbstractComponentState { private String movieId; public String getMovieId() { } return movieId; public void setMovieId(String movieId) { } } this.movieId = movieId;
    27. 27. YouTubePlayer server-side public class YouTubePlayer extends AbstractComponent { public YouTubePlayer(String movieId) { } getState().setMovieId(movieId); @Override public YouTubeState getState() { } } return (YouTubeState ) super.getState();
    28. 28. YouTubeConnector client-side @Connect(YouTubePlayer.class) public class YouTubeConnector extends AbstractComponentConnector { // get & create widget as previously public void onStateChanged(StateChangeEvent e) { } } super.onStateChanged(e); String movieId = getState().getMovieId(); getWidget().setMovieID(movieId);
    29. 29. hasPropertyChanged public void onStateChanged(StateChangeEvent e) { super.onStateChanged(e); if (e.hasPropertyChanged(“movieId”) { String movieId = getState().getMovieId(); getWidget().setMovieID(movieId); } }
    30. 30. Project structure <root-package> client ClientWidget ServerComponent ClientConnector gwt.xml SharedState
    31. 31. Configuration  Reference widget(s) in gwt.xml  Reference gwt.xml in servlet configuration  Either web.xml  Or annotation
    32. 32. Client compilation  Only a single GWT compiled package per WAR  Compile once in the final WAR whatever the number of widgets  And be done with it!
    33. 33. GWT widget wrap summary 1. Create server-side component API 2. Then develop what is needed  Client-side widget (if necessary)  Connector  State 3. No need to package compiled-client code more than once
    34. 34. Extension points 1. Compose base components 2. Wrap GWT widgets 3. Extensions 4. Wrap JavaScript 5. Theme
    35. 35. Extensions  Extensions are a way to add client-side features to an existing component  Examples:  Tooltip on labels  Icon on text fields  Caps lock warning on password fields  Etc.
    36. 36. Extension architecture
    37. 37. Extension server-side public class Tooltip extends AbstractExtension { public void extend(TextField field) { super.extend(field); } }
    38. 38. Extension client-side @Connect(Tooltip.class) public class TooltipConnector extends AbstractExtensionConnector { @Override protected void extend(ServerConnector target) { final Widget tf = ((ComponentConnector) target).getWidget(); final VOverlay tooltip = new VOverlay(); tooltip.add(new HTML("<div class='c-tooltip'>Static tooltip</div>"));
    39. 39. Extension client-side tf.addDomHandler(new MouseOverHandler() { @Override public void onMouseOver(MouseOverEvent event) { tooltip.showRelativeTo(tf); } }, MouseOverEvent.getType()); tf.addDomHandler(new MouseOutHandler() { @Override public void onMouseOut(MouseOutEvent event) { tooltip.hide(); } } } }, MouseOutEvent.getType()); continued
    40. 40. Usage TextField tf = new TextField("Name"); new Tooltip().extend(tf);  And that’s all!  But you need GWT skills...  Noticed the tooltip is static?  "<div class='c-tooltip'>Static tooltip</div>"
    41. 41. Client-side state extension public class TooltipState extends SharedState { private String tooltip; public String getTooltip() { } return tooltip; public void setTooltip (String tooltip) { } } this.tooltip = tooltip;
    42. 42. Dynamic extension server-side public class Tooltip extends AbstractExtension { @Override public TooltipState getState() { } return (TooltipState) super.getState(); public void extend(TextField tf, String tooltip) { getState().setTooltip(tooltip); } } super.extend(link);
    43. 43. Dynamic Extension client-side @Connect(TooltipExtension.class) public class TooltipConnector extends AbstractExtensionConnector { @Override public TooltipState getState() { } return (TooltipState) super.getState(); @Override protected void extend(ServerConnector target) { … String text = getState().getTooltip(); } } tooltip.add(new HTML("<div class='c-tooltip'>" + text + "</div>")); …
    44. 44. Dynamic usage TextField tf = new TextField("Name"); new Tooltip().extend(tf, "really useful tooltip");
    45. 45. Extension summary 1. For added client-side capacity 2. Simple usage server-side 3. Requires GWT skills 4. State to the rescue  For runtime changes
    46. 46. Wrap JavaScript 1. Compose base components 2. Wrap GWT widgets 3. Extensions 4. Wrap JavaScript 5. Theme
    47. 47. JavaScript before 7 window.executeJavascript(String script) “ Executes JavaScript in this window. This method allows one to inject JavaScript from the server to client. A client implementation is not required to implement this functionality, but currently all web-based clients do implement this. Use of this method should be avoided and instead it is recommended to create new widgets with GWT.”
    48. 48. JavaScript before 7  Not always feasible to wrap JavaScript in GWT  Not always available GWT skills  Not always possible to use JavaScript directly  Nor maintainable when it is
    49. 49. JavaScript in 7  To embed scripts client-side 1. JavaScript extension  To improve existing widgets 2. JavaScript component  To add
    50. 50. JavaScript extension architecture
    51. 51. @JavaScript usage  On server-side JavaScript extension  Absolute resources  https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js  Local resources  bootstrap.js  bootstrap_connector.js
    52. 52. Calling JS function  callFunction("functionName", arguments)  Provides a way to call JavaScript scripts server-side
    53. 53. JavaScript extension server-side @JavaScript({ "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js", "bootstrap.js", "bootstrap_connector.js" }) public class JsTooltipExtension extends AbstractJavaScriptExtension { public void extend(TextField tf, String tooltip) { super.extend(tf); } } callFunction("attach", tooltip);
    54. 54. Binding with JavaScript  There’s no connector per se  As there’s no GWT widget  But we still need to bind betwen server and client  All local scripts have to be in the same package as the extension
    55. 55. JavaScript extension client-side window.package_JavascriptTooltipExtension = function() { this.attach = function(options) { var connectorId = this.getParentId(); var element = this.getElement(connectorId); var tf = element.childNodes[0]; tf.rel = "tooltip"; tf.title = options[0]; } } $(tf).tooltip();
    56. 56. JavaScript and state  State as seen previously applies  com.vaadin.shared.ui.JavaScriptComponentState  On client-side window.package_JavascriptExtension = function() { this.onChange = function() { this.getState() … } }
    57. 57. JavaScript component  Very alike to extension  But will create the HTML DIV  Hopefully… never played with it 
    58. 58. JavaScript component architecture
    59. 59. Wrap JavaScript summary  When JavaScript is available  Just need a JS connector script  Pros  No need to use GWT  Can still be packaged as JARs  Cons  Loses all static typing
    60. 60. Themes 1. Compose base components 2. Wrap GWT widgets 3. Extensions 4. Wrap JavaScript 5. Theme
    61. 61. Themes  Themes are an easy way to change applications appearance  CSS / SASS  Images  HTML layouts  @Theme  Provided OOTB  reindeer (default)  runo  chameleon
    62. 62. Theme structure VAADIN/themes mytheme.scss styles.scss img layouts
    63. 63. Themes are undervalued  SASS is extra-powerful  Very easy to use  Packaged in JARs  Front-end and Java developers can work in parallel
    64. 64. Summary  Vaadin is Component-Oriented  Create your own  Design for reusability  Use it to your advantage!
    65. 65. Thanks for your attention

    ×