SlideShare une entreprise Scribd logo
1  sur  25
Télécharger pour lire hors ligne
Enterprise Systems Development
Direct Web Remoting (DWR): Ajax made easy…

                          Daniel Bryant
     Department of Computing, FEPS (d.bryant@surrey.ac.uk)
            Tai-Dev Ltd, (daniel.bryant@tai-dev.co.uk)
Today’s roadmap...
•   My life story (in under 3 minutes)…

•   Quick review - so, what is Ajax? (Old school vs new school)

•   DWR
       Introduction
       Looking deeper into DWR (client-side/server-side)
       Design Patterns
       Implementation
       Demo (and debugging)


•   Quick case study – TriOpsis Ltd

•   DWR is awesome!! But are there any disadvantages?

•   Review
My life story (abridged)…

•   Studying at Surrey for 8 years
       BSc Computing and IT - Placement at DTI (now called BERR, DBIS etc. etc...)
       MSc Internet Computing


•   PhD Student within the Department of Computing
       Argumentation “how humans reason”
       Software Agents “mobile and/or intelligent code”


•   JEE, Web 2.0, J2ME & RDBMS Consultant
       Working freelance for the past 5 years
       Started Tai-Dev Ltd 1 year ago (http://tai-dev.blog.co.uk/)
       J2EE, JEE 5, JSE, J2ME
       Spring, Hibernate, MySQL, GlassFish v2
       HTML, CSS, Javascript
       Prototype, Script.aculo.us, JQuery
       Direct Web Remoting (DWR)…
So, just what is Ajax?

•   “Asynchronous JavaScript and XML”
        “…group of interrelated web development techniques used for creating interactive web
        applications or rich Internet applications.” (Wikipedia, 2008)


•   Building block for “Web 2.0” applications
        Facebook, Google Mail and many more (auto-complete forms)




•   Applications can retrieve data from the server asynchronously in the background
    without interfering with the display and behaviour of the existing page
        No browser plugins (a’la Flash, Flex, SilverLight)


•   The use of JavaScript, XML, or its asynchronous use is not required…
Ajax - the old school way…
                                               Server
        Client




                        http://java.sun.com/developer/technicalArticles/J2EE/AJAX
Old school, not so cool…

• Client-side
      Browser incompatibilities (Microsoft, and then the rest of the world...)
      Long-winded
      Error prone
      Responsible for parsing return data, often XML-based (not OO)
      Responsible for handling application errors (response codes?)
      Large amount of repeated “boiler plate” code


• Server-side
      Create Servlets (no abstraction, and limited chance to allow design patterns)
      Construct XML document of data
      Responsible for “flattening” Objects and Collections
      Set content-type of return data manually
      Manual error handing (convert Exceptions into response codes?)
Introducing the alternatives…

•   JavaScript Libraries/Frameworks
       dojo, JQuery, Prototype
       Greatly simplify client-side code
       Not so helpful on server-side…


•   JSP Taglibs/JSF Components
       jMaki, Ajax4jsf
       Very easy to utilise
       Limited server-side configuration (majority of focus on existing widgets and services)


•   Proxy-based Frameworks
       Direct Web Remoting (DWR), Rajax
       Best of both worlds
       Language specific on backend (Java)


•   Tip: Always new stuff coming out – check blogs and news sites...
Direct Web Remoting (DWR)
Overview

•   DWR allows easy implementation of Ajax functionality
        Homepage @ http://directwebremoting.org/
        Open source
        JavaScript “client-side”
        Java “server-side”


•   Proxy-based framework
        Client-side code can call Java server-side methods as if they were local
        JavaScript functions.
        Converts or “marshalls” parameters and return variable to/from Java/JavaScript

•   DWR generates the intermediate code (“piping” or boilerplate code)

•   Also provides Utility classes
DWR in pictures




                  Image from http://directwebremoting.org/dwr/overview/dwr
Client-side

•   Core components
        DWR JavaScript engine (‘engine.js’)
        JavaScript “interface” definitions of remote methods
        JavaScript Object Notation (JSON) used instead of XML


•   Call Java methods as if local JavaScript functions
        Albeit with callbacks…


•   Hides browser incompatibilities (via “engine.js”)
        XMLHttpRequest Object
        Maps function calls to URLs


•   Converts or “marshalls” data
        Java ArrayLists into JavaScript arrays
        Java Objects into JavaScript object (eg we can say user.firstname)


•   Simplifies error-handling
        Maps Java Exceptions to JavaScript errors
Server-side

•   Core components
        DWR JAR Library
        Proxy generator
        DWRServlets


•   Easy framework configuration
        XML or Annotations (Java 5+)
        Care needed…


•   Not tied to writing Servlets or Spring Controllers
        Promotes good OO coding and design patterns


•   Simply expose (existing) Application Services
        Specify order and types of parameter
        Can return any type of Collection or Object
        Can utilise Spring, Struts, JSF…
Design Patterns
•   “A design pattern in architecture and computer science is a formal way of documenting a solution
    to a design problem in a particular field of expertise.”
                       (Wikipedia, http://en.wikipedia.org/wiki/Design_patterns, accessed 30/11/2009)

•   Already covered Model, View, Controller (MVC) – utilised within Spring “MVC”

•   Difficult to use MVC with Ajax/DWR - Sacrificing some benefits
         MVC isolates business logic from input and presentation,
         MVC permits independent development, testing and maintenance of each
         With MVC we can have multiple views...


                               Spring Dispatcher-Servlet


                                                  Your Business Objects (User, Address Location)
                                                    and Business Logic (Application Services?)




       JSP
Design Patterns (continued...)
•   DWR based on other Design Patterns - We gain simplicity of implementation
        Business Objects – basic POJOs, beans
        Application Service - our business logic classes. Note, these can/should be Unit Tested
        View is determined by calling HTML/JSP and JavaScript
        Front Controller taken care of – the DWRServlet


•   When combining Spring MVC and DWR we have to be careful when managing state shared
    between the two (such as security info).
        We can overcome this using other patterns, such as the Intercepting Filter
        Could be implemented using Aspect Oriented Programming e.g. Spring AOP?
•   Images taken from http://www.corej2eepatterns.com/ (accessed 30/11/2009)



                                                         DWRServlet




       Javascript in browser
            (engine.js)
                                                                                             Your Application Services
                                                                                               and Business Objects
       Intercepting Filter
    Would be implemented here
Implementation in 5 (easy) steps…


1. Copy DWR Library files into project

2. Configure your existing framework to handle DWR requests

3. Create your Data Model (Business Objects) and Application Services

4. Inform DWR of these classes and their required exposure client-side
    1. dwr.xml configuration file
    2. Annotations (Java 5+)


5. Create your client-side functions
Handling http requests (web.xml)….


    …

        <servlet>
            <servlet-name>dispatcher</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-
        class>
            <load-on-startup>2</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>dispatcher</servlet-name>
            <url-pattern>*.htm</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>dispatcher</servlet-name>
            <url-pattern>/dwr/*</url-pattern>
        </servlet-mapping>

…
Cooking the Spring Beans…

<!-- DWR configuration (wrapping Spring ServletWrappingController around
    standard DWR Servlet, and specifying init-params (including the location
    of annotated classes -->
    <bean id="dwrController"
    class="org.springframework.web.servlet.mvc.ServletWrappingController">
        <property name="servletClass" value="org.directwebremoting.servlet.DwrServlet">
        </property>
        <property name="initParameters">
            <props>
                <!-- remember to disable in production use -->
                <prop key="debug">
                true
                </prop>
                <!—Location of annotated classes that DWR should scan for use -->
                <prop key="classes">
      esd.model.Location,
      esd.service.LocService
                </prop>
            </props>
        </property>
    </bean>
Create the Model (Business Objects)

package esd.model;

import org.directwebremoting.annotations.DataTransferObject;
import org.directwebremoting.annotations.RemoteProperty;

@DataTransferObject
public class Location {

   @RemoteProperty
   private String address1;
   @RemoteProperty
   private String address2;
   @RemoteProperty
   private String city;
   @RemoteProperty
   private String county;
   @RemoteProperty
   private String country;
   @RemoteProperty
   private String postcode;

   public Location(String address1, String address2, String city,
           String county, String country, String postcode) {
      …
Create your Application Services…

import …

@RemoteProxy
public class LocService {

    private List<Location> initialLocs = new ArrayList<Location>();
    //
    // -------------- Constructors -----------------
    //
    public LocService() {
        …
    }
    @RemoteMethod
    public List<Location> findLocs(String postcode) {
        List<Location> results = new ArrayList<Location>();
        if (postcode == null || postcode.equals("")) {
            results = initialLocs;
        } else {
            //perform search
            //TODO
        }
        return results;
    }
}
Create your client-side functions…
                                                                    import …

                                                                    @RemoteProxy
                                                                    public class LocService {
   <script src='dwr/interface/LocService.js'></script>
                                                                        private List<Location> initialLocs = new
    <script src='dwr/engine.js'></script>                                  ArrayList<Location>();
                                                                        //
                                                                        // -------------- Constructors -----------------
   <script>                                                             //
                                                                        public LocService() {
       function searchForLocs() {                                           …
                                                                        }
            LocService.findLocs("", {                                   @RemoteMethod
                callback:function(dataFromServer) {                     public List<Location> findLocs(String postcode) {
                                                                            List<Location> results = new ArrayList<Location>();
                    updateResults(dataFromServer);                          if (postcode == null || postcode.equals("")) {
                                                                                results = initialLocs;
                },                                                          } else {
                errorHandler:function(errorString, exception) {                 //perform search
                                                                                //TODO
                    alert("Error: " + errorString);                         }
                                                                            return results;
                }                                                       }
            });                                                     }

       }

       function updateResults(locList) {
           for (var i = 0, l = locList.length; i < l; i++) {
               var txt = document.createTextNode(locList[i].address1 + "," + locList[i].postcode);
               document.getElementById("results").appendChild(txt);
           }
           var br = document.createElement("br");
           document.getElementById("results").appendChild(br);
       }
   </script>
Lights, camera, action...
(oh yes, and debugging)

•   Quick demo of slide material



•   Quick look at debugging
       Client-side – Firefox’s Firebug
       Server-side – Netbeans’ debugger



•   Tip: If you want to be a professional software developer debugging
    efficiently should become as natural as breathing…
       Not emphasized enough in teaching (but this is just my opinion)
       Probably a worthwhile skill for those MSc Dissertations as well…
Real world case study... TriOpsis Ltd

 •   Highly innovative start-up company based at the Research Park (STC)
 •   Check out www.triopsis.co.uk for more information
 •   Experts in the emerging field of Visual Business Information
      • Specialising on ‘in the field’ data capture via mobile devices
      • Images and associated metadata reporting relevant to target customer
Real world case study... TriOpsis Ltd




Screenshot of TriOpsis Flagship product – the ‘Asset Manager’ (implemented by yours truly!)
And finally…
There are some disadvantages with DWR…
•   As with any framework that generates (blackbox) “piping”
        Sometimes difficult to know what is happening “in the pipe”


•   Potentially difficult to debug
        Spans across client and server domain
        Can use Netbeans debugger and FireFox’s Firebug


•   Maintaining http session information
        Hybrid of POSTed forms and Ajax


•   Can cause unexpectedly large amounts of http traffic
        Passing of complete object graphs (typically developer error ☺ )


•   Potential security implications
        Exposing incorrect methods etc.
        Easy to pass sensitive data in plaintext (passwords etc.) without knowing
Conclusions

•   We know what Ajax is…

•   We examined old school/new school approaches to implementation

•   We learned that DWR is a “proxy-based” framework
         Providing (JavaScript) client and (Java) server-side Ajax support
         Allows exposure of Java model (BOs) and services
         DWR “handles the details”..


•   We’ve seen how to implement DWR

•   We’ve had a look at an often undervalued skill – debugging

•   Seen real case study using this technology, TriOpsis, which is actively used within Industry

•   And we are always aware of potential disadvantages
         Beware of “black box” implementations…
         Security, session and http traffic
Thanks for your attention…


•   I’m happy to answer questions now or later...



•   We will learn more about DWR in the lab session
       Sorry, but I can’t promise to answer individual emails...




•   Feedback, comments, constructive criticism...

Contenu connexe

Tendances

Java Spring MVC Framework with AngularJS by Google and HTML5
Java Spring MVC Framework with AngularJS by Google and HTML5Java Spring MVC Framework with AngularJS by Google and HTML5
Java Spring MVC Framework with AngularJS by Google and HTML5Tuna Tore
 
[2015/2016] Require JS and Handlebars JS
[2015/2016] Require JS and Handlebars JS[2015/2016] Require JS and Handlebars JS
[2015/2016] Require JS and Handlebars JSIvano Malavolta
 
Modern Architectures with Spring and JavaScript
Modern Architectures with Spring and JavaScriptModern Architectures with Spring and JavaScript
Modern Architectures with Spring and JavaScriptmartinlippert
 
Spring Framework - Core
Spring Framework - CoreSpring Framework - Core
Spring Framework - CoreDzmitry Naskou
 
Struts 2 - Introduction
Struts 2 - Introduction Struts 2 - Introduction
Struts 2 - Introduction Hitesh-Java
 
Spring Framework - MVC
Spring Framework - MVCSpring Framework - MVC
Spring Framework - MVCDzmitry Naskou
 
Java EE Introduction
Java EE IntroductionJava EE Introduction
Java EE Introductionejlp12
 
Spring 3.x - Spring MVC - Advanced topics
Spring 3.x - Spring MVC - Advanced topicsSpring 3.x - Spring MVC - Advanced topics
Spring 3.x - Spring MVC - Advanced topicsGuy Nir
 
Java Web Programming [3/9] : Servlet Advanced
Java Web Programming [3/9] : Servlet AdvancedJava Web Programming [3/9] : Servlet Advanced
Java Web Programming [3/9] : Servlet AdvancedIMC Institute
 
Beginners' guide to Ruby on Rails
Beginners' guide to Ruby on RailsBeginners' guide to Ruby on Rails
Beginners' guide to Ruby on RailsVictor Porof
 
Java Web Programming [4/9] : JSP Basic
Java Web Programming [4/9] : JSP BasicJava Web Programming [4/9] : JSP Basic
Java Web Programming [4/9] : JSP BasicIMC Institute
 
Hibernate ppt
Hibernate pptHibernate ppt
Hibernate pptAneega
 
Spring 3 MVC CodeMash 2009
Spring 3 MVC   CodeMash 2009Spring 3 MVC   CodeMash 2009
Spring 3 MVC CodeMash 2009kensipe
 
Struts An Open-source Architecture for Web Applications
Struts An Open-source Architecture for Web ApplicationsStruts An Open-source Architecture for Web Applications
Struts An Open-source Architecture for Web Applicationselliando dias
 
Suportando Aplicações Multi-tenancy com Java EE
Suportando Aplicações Multi-tenancy com Java EESuportando Aplicações Multi-tenancy com Java EE
Suportando Aplicações Multi-tenancy com Java EERodrigo Cândido da Silva
 
Lecture 9 - Java Persistence, JPA 2
Lecture 9 - Java Persistence, JPA 2Lecture 9 - Java Persistence, JPA 2
Lecture 9 - Java Persistence, JPA 2Fahad Golra
 

Tendances (20)

Java Spring MVC Framework with AngularJS by Google and HTML5
Java Spring MVC Framework with AngularJS by Google and HTML5Java Spring MVC Framework with AngularJS by Google and HTML5
Java Spring MVC Framework with AngularJS by Google and HTML5
 
[2015/2016] Require JS and Handlebars JS
[2015/2016] Require JS and Handlebars JS[2015/2016] Require JS and Handlebars JS
[2015/2016] Require JS and Handlebars JS
 
Modern Architectures with Spring and JavaScript
Modern Architectures with Spring and JavaScriptModern Architectures with Spring and JavaScript
Modern Architectures with Spring and JavaScript
 
Spring Framework - Core
Spring Framework - CoreSpring Framework - Core
Spring Framework - Core
 
Struts 2 - Introduction
Struts 2 - Introduction Struts 2 - Introduction
Struts 2 - Introduction
 
Spring Framework - MVC
Spring Framework - MVCSpring Framework - MVC
Spring Framework - MVC
 
Hibernate 3
Hibernate 3Hibernate 3
Hibernate 3
 
Spring MVC
Spring MVCSpring MVC
Spring MVC
 
Java EE Introduction
Java EE IntroductionJava EE Introduction
Java EE Introduction
 
Spring 3.x - Spring MVC - Advanced topics
Spring 3.x - Spring MVC - Advanced topicsSpring 3.x - Spring MVC - Advanced topics
Spring 3.x - Spring MVC - Advanced topics
 
Java Web Programming [3/9] : Servlet Advanced
Java Web Programming [3/9] : Servlet AdvancedJava Web Programming [3/9] : Servlet Advanced
Java Web Programming [3/9] : Servlet Advanced
 
Beginners' guide to Ruby on Rails
Beginners' guide to Ruby on RailsBeginners' guide to Ruby on Rails
Beginners' guide to Ruby on Rails
 
Struts course material
Struts course materialStruts course material
Struts course material
 
Java Web Programming [4/9] : JSP Basic
Java Web Programming [4/9] : JSP BasicJava Web Programming [4/9] : JSP Basic
Java Web Programming [4/9] : JSP Basic
 
Advance Java
Advance JavaAdvance Java
Advance Java
 
Hibernate ppt
Hibernate pptHibernate ppt
Hibernate ppt
 
Spring 3 MVC CodeMash 2009
Spring 3 MVC   CodeMash 2009Spring 3 MVC   CodeMash 2009
Spring 3 MVC CodeMash 2009
 
Struts An Open-source Architecture for Web Applications
Struts An Open-source Architecture for Web ApplicationsStruts An Open-source Architecture for Web Applications
Struts An Open-source Architecture for Web Applications
 
Suportando Aplicações Multi-tenancy com Java EE
Suportando Aplicações Multi-tenancy com Java EESuportando Aplicações Multi-tenancy com Java EE
Suportando Aplicações Multi-tenancy com Java EE
 
Lecture 9 - Java Persistence, JPA 2
Lecture 9 - Java Persistence, JPA 2Lecture 9 - Java Persistence, JPA 2
Lecture 9 - Java Persistence, JPA 2
 

Similaire à MSc Enterprise Systems Development Guest Lecture at UniS (2/12/09)

MV* presentation frameworks in Javascript: en garde, pret, allez!
MV* presentation frameworks in Javascript: en garde, pret, allez!MV* presentation frameworks in Javascript: en garde, pret, allez!
MV* presentation frameworks in Javascript: en garde, pret, allez!Roberto Messora
 
Ajax with DWR
Ajax with DWRAjax with DWR
Ajax with DWRgouthamrv
 
Cloud compiler - Minor Project by students of CBPGEC
Cloud compiler - Minor Project by students of CBPGEC  Cloud compiler - Minor Project by students of CBPGEC
Cloud compiler - Minor Project by students of CBPGEC vipin kumar
 
Server-side Web development via Ruby on Rails
Server-side Web development via Ruby on RailsServer-side Web development via Ruby on Rails
Server-side Web development via Ruby on Railsg3ppy
 
Introduction to ejb and struts framework
Introduction to ejb and struts frameworkIntroduction to ejb and struts framework
Introduction to ejb and struts frameworks4al_com
 
Lecture 19 dynamic web - java - part 1
Lecture 19   dynamic web - java - part 1Lecture 19   dynamic web - java - part 1
Lecture 19 dynamic web - java - part 1Д. Ганаа
 
Struts2-Spring=Hibernate
Struts2-Spring=HibernateStruts2-Spring=Hibernate
Struts2-Spring=HibernateJay Shah
 
Rp 6 session 2 naresh bhatia
Rp 6  session 2 naresh bhatiaRp 6  session 2 naresh bhatia
Rp 6 session 2 naresh bhatiasapientindia
 
Gnizr Architecture (for developers)
Gnizr Architecture (for developers)Gnizr Architecture (for developers)
Gnizr Architecture (for developers)hchen1
 
Build Java Web Application Using Apache Struts
Build Java Web Application Using Apache Struts Build Java Web Application Using Apache Struts
Build Java Web Application Using Apache Struts weili_at_slideshare
 
Struts 2-overview2
Struts 2-overview2Struts 2-overview2
Struts 2-overview2divzi1913
 
Intro to .NET for Government Developers
Intro to .NET for Government DevelopersIntro to .NET for Government Developers
Intro to .NET for Government DevelopersFrank La Vigne
 
Web Component Development with Servlet and JSP Technologies Unit 01
Web Component Development with Servlet and JSP Technologies Unit 01Web Component Development with Servlet and JSP Technologies Unit 01
Web Component Development with Servlet and JSP Technologies Unit 01Prashanth Shivakumar
 
Java on Windows Azure
Java on Windows AzureJava on Windows Azure
Java on Windows AzureDavid Chou
 
springmvc-150923124312-lva1-app6892
springmvc-150923124312-lva1-app6892springmvc-150923124312-lva1-app6892
springmvc-150923124312-lva1-app6892Tuna Tore
 
Developing Java Web Applications
Developing Java Web ApplicationsDeveloping Java Web Applications
Developing Java Web Applicationshchen1
 

Similaire à MSc Enterprise Systems Development Guest Lecture at UniS (2/12/09) (20)

AJppt.pptx
AJppt.pptxAJppt.pptx
AJppt.pptx
 
MV* presentation frameworks in Javascript: en garde, pret, allez!
MV* presentation frameworks in Javascript: en garde, pret, allez!MV* presentation frameworks in Javascript: en garde, pret, allez!
MV* presentation frameworks in Javascript: en garde, pret, allez!
 
Ajax with DWR
Ajax with DWRAjax with DWR
Ajax with DWR
 
Oracle OpenWorld 2014 Review Part Four - PaaS Middleware
Oracle OpenWorld 2014 Review Part Four - PaaS MiddlewareOracle OpenWorld 2014 Review Part Four - PaaS Middleware
Oracle OpenWorld 2014 Review Part Four - PaaS Middleware
 
Cloud compiler - Minor Project by students of CBPGEC
Cloud compiler - Minor Project by students of CBPGEC  Cloud compiler - Minor Project by students of CBPGEC
Cloud compiler - Minor Project by students of CBPGEC
 
Server-side Web development via Ruby on Rails
Server-side Web development via Ruby on RailsServer-side Web development via Ruby on Rails
Server-side Web development via Ruby on Rails
 
Introduction to ejb and struts framework
Introduction to ejb and struts frameworkIntroduction to ejb and struts framework
Introduction to ejb and struts framework
 
Lecture 19 dynamic web - java - part 1
Lecture 19   dynamic web - java - part 1Lecture 19   dynamic web - java - part 1
Lecture 19 dynamic web - java - part 1
 
Struts2-Spring=Hibernate
Struts2-Spring=HibernateStruts2-Spring=Hibernate
Struts2-Spring=Hibernate
 
Rp 6 session 2 naresh bhatia
Rp 6  session 2 naresh bhatiaRp 6  session 2 naresh bhatia
Rp 6 session 2 naresh bhatia
 
Gnizr Architecture (for developers)
Gnizr Architecture (for developers)Gnizr Architecture (for developers)
Gnizr Architecture (for developers)
 
Build Java Web Application Using Apache Struts
Build Java Web Application Using Apache Struts Build Java Web Application Using Apache Struts
Build Java Web Application Using Apache Struts
 
CG_CS25010_Lecture
CG_CS25010_LectureCG_CS25010_Lecture
CG_CS25010_Lecture
 
Struts 2-overview2
Struts 2-overview2Struts 2-overview2
Struts 2-overview2
 
Intro to .NET for Government Developers
Intro to .NET for Government DevelopersIntro to .NET for Government Developers
Intro to .NET for Government Developers
 
Web Component Development with Servlet and JSP Technologies Unit 01
Web Component Development with Servlet and JSP Technologies Unit 01Web Component Development with Servlet and JSP Technologies Unit 01
Web Component Development with Servlet and JSP Technologies Unit 01
 
Java on Windows Azure
Java on Windows AzureJava on Windows Azure
Java on Windows Azure
 
springmvc-150923124312-lva1-app6892
springmvc-150923124312-lva1-app6892springmvc-150923124312-lva1-app6892
springmvc-150923124312-lva1-app6892
 
Developing Java Web Applications
Developing Java Web ApplicationsDeveloping Java Web Applications
Developing Java Web Applications
 
MVC
MVCMVC
MVC
 

Plus de Daniel Bryant

ITKonekt 2023: The Busy Platform Engineers Guide to API Gateways
ITKonekt 2023: The Busy Platform Engineers Guide to API GatewaysITKonekt 2023: The Busy Platform Engineers Guide to API Gateways
ITKonekt 2023: The Busy Platform Engineers Guide to API GatewaysDaniel Bryant
 
CraftConf 2023 "Microservice Testing Techniques: Mocks vs Service Virtualizat...
CraftConf 2023 "Microservice Testing Techniques: Mocks vs Service Virtualizat...CraftConf 2023 "Microservice Testing Techniques: Mocks vs Service Virtualizat...
CraftConf 2023 "Microservice Testing Techniques: Mocks vs Service Virtualizat...Daniel Bryant
 
PlatformCon 23: "The Busy Platform Engineers Guide to API Gateways"
PlatformCon 23: "The Busy Platform Engineers Guide to API Gateways"PlatformCon 23: "The Busy Platform Engineers Guide to API Gateways"
PlatformCon 23: "The Busy Platform Engineers Guide to API Gateways"Daniel Bryant
 
Java Meetup 23: 'Debugging Microservices "Remocally" in Kubernetes with Telep...
Java Meetup 23: 'Debugging Microservices "Remocally" in Kubernetes with Telep...Java Meetup 23: 'Debugging Microservices "Remocally" in Kubernetes with Telep...
Java Meetup 23: 'Debugging Microservices "Remocally" in Kubernetes with Telep...Daniel Bryant
 
DevRelCon 2022: "Is Product Led Growth (PLG) the “DevOps” of the DevRel World"
DevRelCon 2022: "Is Product Led Growth (PLG) the “DevOps” of the DevRel World"DevRelCon 2022: "Is Product Led Growth (PLG) the “DevOps” of the DevRel World"
DevRelCon 2022: "Is Product Led Growth (PLG) the “DevOps” of the DevRel World"Daniel Bryant
 
Fall 22: "From Kubernetes to PaaS to... err, what's next"
Fall 22: "From Kubernetes to PaaS to... err, what's next"Fall 22: "From Kubernetes to PaaS to... err, what's next"
Fall 22: "From Kubernetes to PaaS to... err, what's next"Daniel Bryant
 
Building Microservice Systems Without Cooking Your Laptop: Going “Remocal” wi...
Building Microservice Systems Without Cooking Your Laptop: Going “Remocal” wi...Building Microservice Systems Without Cooking Your Laptop: Going “Remocal” wi...
Building Microservice Systems Without Cooking Your Laptop: Going “Remocal” wi...Daniel Bryant
 
KubeCrash 22: Debugging Microservices "Remocally" in Kubernetes with Telepres...
KubeCrash 22: Debugging Microservices "Remocally" in Kubernetes with Telepres...KubeCrash 22: Debugging Microservices "Remocally" in Kubernetes with Telepres...
KubeCrash 22: Debugging Microservices "Remocally" in Kubernetes with Telepres...Daniel Bryant
 
JAX London 22: Debugging Microservices "Remocally" in Kubernetes with Telepre...
JAX London 22: Debugging Microservices "Remocally" in Kubernetes with Telepre...JAX London 22: Debugging Microservices "Remocally" in Kubernetes with Telepre...
JAX London 22: Debugging Microservices "Remocally" in Kubernetes with Telepre...Daniel Bryant
 
CloudBuilders 2022: "The Past, Present, and Future of Cloud Native API Gateways"
CloudBuilders 2022: "The Past, Present, and Future of Cloud Native API Gateways"CloudBuilders 2022: "The Past, Present, and Future of Cloud Native API Gateways"
CloudBuilders 2022: "The Past, Present, and Future of Cloud Native API Gateways"Daniel Bryant
 
KubeCon EU 2022: From Kubernetes to PaaS to Err What's Next
KubeCon EU 2022: From Kubernetes to PaaS to Err What's NextKubeCon EU 2022: From Kubernetes to PaaS to Err What's Next
KubeCon EU 2022: From Kubernetes to PaaS to Err What's NextDaniel Bryant
 
Devoxx UK 22: Debugging Java Microservices "Remocally" in Kubernetes with Tel...
Devoxx UK 22: Debugging Java Microservices "Remocally" in Kubernetes with Tel...Devoxx UK 22: Debugging Java Microservices "Remocally" in Kubernetes with Tel...
Devoxx UK 22: Debugging Java Microservices "Remocally" in Kubernetes with Tel...Daniel Bryant
 
DevXDay KubeCon NA 2021: "From Kubernetes to PaaS to Developer Control Planes"
DevXDay KubeCon NA 2021: "From Kubernetes to PaaS to Developer Control Planes"DevXDay KubeCon NA 2021: "From Kubernetes to PaaS to Developer Control Planes"
DevXDay KubeCon NA 2021: "From Kubernetes to PaaS to Developer Control Planes"Daniel Bryant
 
JAX London 2021: Jumpstart Your Cloud Native Development: An Overview of Prac...
JAX London 2021: Jumpstart Your Cloud Native Development: An Overview of Prac...JAX London 2021: Jumpstart Your Cloud Native Development: An Overview of Prac...
JAX London 2021: Jumpstart Your Cloud Native Development: An Overview of Prac...Daniel Bryant
 
Container Days: Easy Debugging of Microservices Running on Kubernetes with Te...
Container Days: Easy Debugging of Microservices Running on Kubernetes with Te...Container Days: Easy Debugging of Microservices Running on Kubernetes with Te...
Container Days: Easy Debugging of Microservices Running on Kubernetes with Te...Daniel Bryant
 
Canadian CNCF: "Emissary-ingress 101: An introduction to the CNCF incubation-...
Canadian CNCF: "Emissary-ingress 101: An introduction to the CNCF incubation-...Canadian CNCF: "Emissary-ingress 101: An introduction to the CNCF incubation-...
Canadian CNCF: "Emissary-ingress 101: An introduction to the CNCF incubation-...Daniel Bryant
 
MJC 2021: "Debugging Java Microservices Running on Kubernetes with Telepresence"
MJC 2021: "Debugging Java Microservices Running on Kubernetes with Telepresence"MJC 2021: "Debugging Java Microservices Running on Kubernetes with Telepresence"
MJC 2021: "Debugging Java Microservices Running on Kubernetes with Telepresence"Daniel Bryant
 
LJC 4/21"Easy Debugging of Java Microservices Running on Kubernetes with Tele...
LJC 4/21"Easy Debugging of Java Microservices Running on Kubernetes with Tele...LJC 4/21"Easy Debugging of Java Microservices Running on Kubernetes with Tele...
LJC 4/21"Easy Debugging of Java Microservices Running on Kubernetes with Tele...Daniel Bryant
 
GOTOpia 2/2021 "Cloud Native Development Without the Toil: An Overview of Pra...
GOTOpia 2/2021 "Cloud Native Development Without the Toil: An Overview of Pra...GOTOpia 2/2021 "Cloud Native Development Without the Toil: An Overview of Pra...
GOTOpia 2/2021 "Cloud Native Development Without the Toil: An Overview of Pra...Daniel Bryant
 
HashiCorp Webinar: "Getting started with Ambassador and Consul on Kubernetes ...
HashiCorp Webinar: "Getting started with Ambassador and Consul on Kubernetes ...HashiCorp Webinar: "Getting started with Ambassador and Consul on Kubernetes ...
HashiCorp Webinar: "Getting started with Ambassador and Consul on Kubernetes ...Daniel Bryant
 

Plus de Daniel Bryant (20)

ITKonekt 2023: The Busy Platform Engineers Guide to API Gateways
ITKonekt 2023: The Busy Platform Engineers Guide to API GatewaysITKonekt 2023: The Busy Platform Engineers Guide to API Gateways
ITKonekt 2023: The Busy Platform Engineers Guide to API Gateways
 
CraftConf 2023 "Microservice Testing Techniques: Mocks vs Service Virtualizat...
CraftConf 2023 "Microservice Testing Techniques: Mocks vs Service Virtualizat...CraftConf 2023 "Microservice Testing Techniques: Mocks vs Service Virtualizat...
CraftConf 2023 "Microservice Testing Techniques: Mocks vs Service Virtualizat...
 
PlatformCon 23: "The Busy Platform Engineers Guide to API Gateways"
PlatformCon 23: "The Busy Platform Engineers Guide to API Gateways"PlatformCon 23: "The Busy Platform Engineers Guide to API Gateways"
PlatformCon 23: "The Busy Platform Engineers Guide to API Gateways"
 
Java Meetup 23: 'Debugging Microservices "Remocally" in Kubernetes with Telep...
Java Meetup 23: 'Debugging Microservices "Remocally" in Kubernetes with Telep...Java Meetup 23: 'Debugging Microservices "Remocally" in Kubernetes with Telep...
Java Meetup 23: 'Debugging Microservices "Remocally" in Kubernetes with Telep...
 
DevRelCon 2022: "Is Product Led Growth (PLG) the “DevOps” of the DevRel World"
DevRelCon 2022: "Is Product Led Growth (PLG) the “DevOps” of the DevRel World"DevRelCon 2022: "Is Product Led Growth (PLG) the “DevOps” of the DevRel World"
DevRelCon 2022: "Is Product Led Growth (PLG) the “DevOps” of the DevRel World"
 
Fall 22: "From Kubernetes to PaaS to... err, what's next"
Fall 22: "From Kubernetes to PaaS to... err, what's next"Fall 22: "From Kubernetes to PaaS to... err, what's next"
Fall 22: "From Kubernetes to PaaS to... err, what's next"
 
Building Microservice Systems Without Cooking Your Laptop: Going “Remocal” wi...
Building Microservice Systems Without Cooking Your Laptop: Going “Remocal” wi...Building Microservice Systems Without Cooking Your Laptop: Going “Remocal” wi...
Building Microservice Systems Without Cooking Your Laptop: Going “Remocal” wi...
 
KubeCrash 22: Debugging Microservices "Remocally" in Kubernetes with Telepres...
KubeCrash 22: Debugging Microservices "Remocally" in Kubernetes with Telepres...KubeCrash 22: Debugging Microservices "Remocally" in Kubernetes with Telepres...
KubeCrash 22: Debugging Microservices "Remocally" in Kubernetes with Telepres...
 
JAX London 22: Debugging Microservices "Remocally" in Kubernetes with Telepre...
JAX London 22: Debugging Microservices "Remocally" in Kubernetes with Telepre...JAX London 22: Debugging Microservices "Remocally" in Kubernetes with Telepre...
JAX London 22: Debugging Microservices "Remocally" in Kubernetes with Telepre...
 
CloudBuilders 2022: "The Past, Present, and Future of Cloud Native API Gateways"
CloudBuilders 2022: "The Past, Present, and Future of Cloud Native API Gateways"CloudBuilders 2022: "The Past, Present, and Future of Cloud Native API Gateways"
CloudBuilders 2022: "The Past, Present, and Future of Cloud Native API Gateways"
 
KubeCon EU 2022: From Kubernetes to PaaS to Err What's Next
KubeCon EU 2022: From Kubernetes to PaaS to Err What's NextKubeCon EU 2022: From Kubernetes to PaaS to Err What's Next
KubeCon EU 2022: From Kubernetes to PaaS to Err What's Next
 
Devoxx UK 22: Debugging Java Microservices "Remocally" in Kubernetes with Tel...
Devoxx UK 22: Debugging Java Microservices "Remocally" in Kubernetes with Tel...Devoxx UK 22: Debugging Java Microservices "Remocally" in Kubernetes with Tel...
Devoxx UK 22: Debugging Java Microservices "Remocally" in Kubernetes with Tel...
 
DevXDay KubeCon NA 2021: "From Kubernetes to PaaS to Developer Control Planes"
DevXDay KubeCon NA 2021: "From Kubernetes to PaaS to Developer Control Planes"DevXDay KubeCon NA 2021: "From Kubernetes to PaaS to Developer Control Planes"
DevXDay KubeCon NA 2021: "From Kubernetes to PaaS to Developer Control Planes"
 
JAX London 2021: Jumpstart Your Cloud Native Development: An Overview of Prac...
JAX London 2021: Jumpstart Your Cloud Native Development: An Overview of Prac...JAX London 2021: Jumpstart Your Cloud Native Development: An Overview of Prac...
JAX London 2021: Jumpstart Your Cloud Native Development: An Overview of Prac...
 
Container Days: Easy Debugging of Microservices Running on Kubernetes with Te...
Container Days: Easy Debugging of Microservices Running on Kubernetes with Te...Container Days: Easy Debugging of Microservices Running on Kubernetes with Te...
Container Days: Easy Debugging of Microservices Running on Kubernetes with Te...
 
Canadian CNCF: "Emissary-ingress 101: An introduction to the CNCF incubation-...
Canadian CNCF: "Emissary-ingress 101: An introduction to the CNCF incubation-...Canadian CNCF: "Emissary-ingress 101: An introduction to the CNCF incubation-...
Canadian CNCF: "Emissary-ingress 101: An introduction to the CNCF incubation-...
 
MJC 2021: "Debugging Java Microservices Running on Kubernetes with Telepresence"
MJC 2021: "Debugging Java Microservices Running on Kubernetes with Telepresence"MJC 2021: "Debugging Java Microservices Running on Kubernetes with Telepresence"
MJC 2021: "Debugging Java Microservices Running on Kubernetes with Telepresence"
 
LJC 4/21"Easy Debugging of Java Microservices Running on Kubernetes with Tele...
LJC 4/21"Easy Debugging of Java Microservices Running on Kubernetes with Tele...LJC 4/21"Easy Debugging of Java Microservices Running on Kubernetes with Tele...
LJC 4/21"Easy Debugging of Java Microservices Running on Kubernetes with Tele...
 
GOTOpia 2/2021 "Cloud Native Development Without the Toil: An Overview of Pra...
GOTOpia 2/2021 "Cloud Native Development Without the Toil: An Overview of Pra...GOTOpia 2/2021 "Cloud Native Development Without the Toil: An Overview of Pra...
GOTOpia 2/2021 "Cloud Native Development Without the Toil: An Overview of Pra...
 
HashiCorp Webinar: "Getting started with Ambassador and Consul on Kubernetes ...
HashiCorp Webinar: "Getting started with Ambassador and Consul on Kubernetes ...HashiCorp Webinar: "Getting started with Ambassador and Consul on Kubernetes ...
HashiCorp Webinar: "Getting started with Ambassador and Consul on Kubernetes ...
 

MSc Enterprise Systems Development Guest Lecture at UniS (2/12/09)

  • 1. Enterprise Systems Development Direct Web Remoting (DWR): Ajax made easy… Daniel Bryant Department of Computing, FEPS (d.bryant@surrey.ac.uk) Tai-Dev Ltd, (daniel.bryant@tai-dev.co.uk)
  • 2. Today’s roadmap... • My life story (in under 3 minutes)… • Quick review - so, what is Ajax? (Old school vs new school) • DWR Introduction Looking deeper into DWR (client-side/server-side) Design Patterns Implementation Demo (and debugging) • Quick case study – TriOpsis Ltd • DWR is awesome!! But are there any disadvantages? • Review
  • 3. My life story (abridged)… • Studying at Surrey for 8 years BSc Computing and IT - Placement at DTI (now called BERR, DBIS etc. etc...) MSc Internet Computing • PhD Student within the Department of Computing Argumentation “how humans reason” Software Agents “mobile and/or intelligent code” • JEE, Web 2.0, J2ME & RDBMS Consultant Working freelance for the past 5 years Started Tai-Dev Ltd 1 year ago (http://tai-dev.blog.co.uk/) J2EE, JEE 5, JSE, J2ME Spring, Hibernate, MySQL, GlassFish v2 HTML, CSS, Javascript Prototype, Script.aculo.us, JQuery Direct Web Remoting (DWR)…
  • 4. So, just what is Ajax? • “Asynchronous JavaScript and XML” “…group of interrelated web development techniques used for creating interactive web applications or rich Internet applications.” (Wikipedia, 2008) • Building block for “Web 2.0” applications Facebook, Google Mail and many more (auto-complete forms) • Applications can retrieve data from the server asynchronously in the background without interfering with the display and behaviour of the existing page No browser plugins (a’la Flash, Flex, SilverLight) • The use of JavaScript, XML, or its asynchronous use is not required…
  • 5. Ajax - the old school way… Server Client http://java.sun.com/developer/technicalArticles/J2EE/AJAX
  • 6. Old school, not so cool… • Client-side Browser incompatibilities (Microsoft, and then the rest of the world...) Long-winded Error prone Responsible for parsing return data, often XML-based (not OO) Responsible for handling application errors (response codes?) Large amount of repeated “boiler plate” code • Server-side Create Servlets (no abstraction, and limited chance to allow design patterns) Construct XML document of data Responsible for “flattening” Objects and Collections Set content-type of return data manually Manual error handing (convert Exceptions into response codes?)
  • 7. Introducing the alternatives… • JavaScript Libraries/Frameworks dojo, JQuery, Prototype Greatly simplify client-side code Not so helpful on server-side… • JSP Taglibs/JSF Components jMaki, Ajax4jsf Very easy to utilise Limited server-side configuration (majority of focus on existing widgets and services) • Proxy-based Frameworks Direct Web Remoting (DWR), Rajax Best of both worlds Language specific on backend (Java) • Tip: Always new stuff coming out – check blogs and news sites...
  • 8. Direct Web Remoting (DWR) Overview • DWR allows easy implementation of Ajax functionality Homepage @ http://directwebremoting.org/ Open source JavaScript “client-side” Java “server-side” • Proxy-based framework Client-side code can call Java server-side methods as if they were local JavaScript functions. Converts or “marshalls” parameters and return variable to/from Java/JavaScript • DWR generates the intermediate code (“piping” or boilerplate code) • Also provides Utility classes
  • 9. DWR in pictures Image from http://directwebremoting.org/dwr/overview/dwr
  • 10. Client-side • Core components DWR JavaScript engine (‘engine.js’) JavaScript “interface” definitions of remote methods JavaScript Object Notation (JSON) used instead of XML • Call Java methods as if local JavaScript functions Albeit with callbacks… • Hides browser incompatibilities (via “engine.js”) XMLHttpRequest Object Maps function calls to URLs • Converts or “marshalls” data Java ArrayLists into JavaScript arrays Java Objects into JavaScript object (eg we can say user.firstname) • Simplifies error-handling Maps Java Exceptions to JavaScript errors
  • 11. Server-side • Core components DWR JAR Library Proxy generator DWRServlets • Easy framework configuration XML or Annotations (Java 5+) Care needed… • Not tied to writing Servlets or Spring Controllers Promotes good OO coding and design patterns • Simply expose (existing) Application Services Specify order and types of parameter Can return any type of Collection or Object Can utilise Spring, Struts, JSF…
  • 12. Design Patterns • “A design pattern in architecture and computer science is a formal way of documenting a solution to a design problem in a particular field of expertise.” (Wikipedia, http://en.wikipedia.org/wiki/Design_patterns, accessed 30/11/2009) • Already covered Model, View, Controller (MVC) – utilised within Spring “MVC” • Difficult to use MVC with Ajax/DWR - Sacrificing some benefits MVC isolates business logic from input and presentation, MVC permits independent development, testing and maintenance of each With MVC we can have multiple views... Spring Dispatcher-Servlet Your Business Objects (User, Address Location) and Business Logic (Application Services?) JSP
  • 13. Design Patterns (continued...) • DWR based on other Design Patterns - We gain simplicity of implementation Business Objects – basic POJOs, beans Application Service - our business logic classes. Note, these can/should be Unit Tested View is determined by calling HTML/JSP and JavaScript Front Controller taken care of – the DWRServlet • When combining Spring MVC and DWR we have to be careful when managing state shared between the two (such as security info). We can overcome this using other patterns, such as the Intercepting Filter Could be implemented using Aspect Oriented Programming e.g. Spring AOP? • Images taken from http://www.corej2eepatterns.com/ (accessed 30/11/2009) DWRServlet Javascript in browser (engine.js) Your Application Services and Business Objects Intercepting Filter Would be implemented here
  • 14. Implementation in 5 (easy) steps… 1. Copy DWR Library files into project 2. Configure your existing framework to handle DWR requests 3. Create your Data Model (Business Objects) and Application Services 4. Inform DWR of these classes and their required exposure client-side 1. dwr.xml configuration file 2. Annotations (Java 5+) 5. Create your client-side functions
  • 15. Handling http requests (web.xml)…. … <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet- class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> …
  • 16. Cooking the Spring Beans… <!-- DWR configuration (wrapping Spring ServletWrappingController around standard DWR Servlet, and specifying init-params (including the location of annotated classes --> <bean id="dwrController" class="org.springframework.web.servlet.mvc.ServletWrappingController"> <property name="servletClass" value="org.directwebremoting.servlet.DwrServlet"> </property> <property name="initParameters"> <props> <!-- remember to disable in production use --> <prop key="debug"> true </prop> <!—Location of annotated classes that DWR should scan for use --> <prop key="classes"> esd.model.Location, esd.service.LocService </prop> </props> </property> </bean>
  • 17. Create the Model (Business Objects) package esd.model; import org.directwebremoting.annotations.DataTransferObject; import org.directwebremoting.annotations.RemoteProperty; @DataTransferObject public class Location { @RemoteProperty private String address1; @RemoteProperty private String address2; @RemoteProperty private String city; @RemoteProperty private String county; @RemoteProperty private String country; @RemoteProperty private String postcode; public Location(String address1, String address2, String city, String county, String country, String postcode) { …
  • 18. Create your Application Services… import … @RemoteProxy public class LocService { private List<Location> initialLocs = new ArrayList<Location>(); // // -------------- Constructors ----------------- // public LocService() { … } @RemoteMethod public List<Location> findLocs(String postcode) { List<Location> results = new ArrayList<Location>(); if (postcode == null || postcode.equals("")) { results = initialLocs; } else { //perform search //TODO } return results; } }
  • 19. Create your client-side functions… import … @RemoteProxy public class LocService { <script src='dwr/interface/LocService.js'></script> private List<Location> initialLocs = new <script src='dwr/engine.js'></script> ArrayList<Location>(); // // -------------- Constructors ----------------- <script> // public LocService() { function searchForLocs() { … } LocService.findLocs("", { @RemoteMethod callback:function(dataFromServer) { public List<Location> findLocs(String postcode) { List<Location> results = new ArrayList<Location>(); updateResults(dataFromServer); if (postcode == null || postcode.equals("")) { results = initialLocs; }, } else { errorHandler:function(errorString, exception) { //perform search //TODO alert("Error: " + errorString); } return results; } } }); } } function updateResults(locList) { for (var i = 0, l = locList.length; i < l; i++) { var txt = document.createTextNode(locList[i].address1 + "," + locList[i].postcode); document.getElementById("results").appendChild(txt); } var br = document.createElement("br"); document.getElementById("results").appendChild(br); } </script>
  • 20. Lights, camera, action... (oh yes, and debugging) • Quick demo of slide material • Quick look at debugging Client-side – Firefox’s Firebug Server-side – Netbeans’ debugger • Tip: If you want to be a professional software developer debugging efficiently should become as natural as breathing… Not emphasized enough in teaching (but this is just my opinion) Probably a worthwhile skill for those MSc Dissertations as well…
  • 21. Real world case study... TriOpsis Ltd • Highly innovative start-up company based at the Research Park (STC) • Check out www.triopsis.co.uk for more information • Experts in the emerging field of Visual Business Information • Specialising on ‘in the field’ data capture via mobile devices • Images and associated metadata reporting relevant to target customer
  • 22. Real world case study... TriOpsis Ltd Screenshot of TriOpsis Flagship product – the ‘Asset Manager’ (implemented by yours truly!)
  • 23. And finally… There are some disadvantages with DWR… • As with any framework that generates (blackbox) “piping” Sometimes difficult to know what is happening “in the pipe” • Potentially difficult to debug Spans across client and server domain Can use Netbeans debugger and FireFox’s Firebug • Maintaining http session information Hybrid of POSTed forms and Ajax • Can cause unexpectedly large amounts of http traffic Passing of complete object graphs (typically developer error ☺ ) • Potential security implications Exposing incorrect methods etc. Easy to pass sensitive data in plaintext (passwords etc.) without knowing
  • 24. Conclusions • We know what Ajax is… • We examined old school/new school approaches to implementation • We learned that DWR is a “proxy-based” framework Providing (JavaScript) client and (Java) server-side Ajax support Allows exposure of Java model (BOs) and services DWR “handles the details”.. • We’ve seen how to implement DWR • We’ve had a look at an often undervalued skill – debugging • Seen real case study using this technology, TriOpsis, which is actively used within Industry • And we are always aware of potential disadvantages Beware of “black box” implementations… Security, session and http traffic
  • 25. Thanks for your attention… • I’m happy to answer questions now or later... • We will learn more about DWR in the lab session Sorry, but I can’t promise to answer individual emails... • Feedback, comments, constructive criticism...