05
  • Web Applications (2)

    Web Server is a software that can process the client request and send the response back to the client.
    Static pages
    Dynamic web content, compiled by the web application (server) in order to provide a response to an http request
    Some of the data may come from a persistent data source, such as a database
    After the response has been put together it is passed to the server to be sent to the client, which sent the request

    Typical programming languages for dynamic content generation: PHP, Python, Ruby on Rails, Java Servlets and JSPs.

    Java Servlet and JSPs are Java-based server side technologies to extend the capability of web servers by providing support for dynamic response and data persistence.

    Important Classes and Interfaces of the javax.servlet API

    Interface Diagram

    The Problem

    Application functionality has been developed as individual (http) servlets, e.g.
    ShopServlet
    ProductServlet
    CartServlet

    A servlet provides a response to a request, often in the doGet(...), doPost(...) etc. methods

    It might create other objects and run methods on these in the process.

    📷 Example - ShopServlet

    📷 Example - LoginServlet

    Redirecting – Generating a Request from the Server

    1. http request http://localhost:9000/login
    2. Runner
    3. LoginServlet.java

    private static final String LOGIN_TEMPLATE = "login.mustache";
    
       doPost() {
       ...
       } else if ("login".equals(action)) {
            if (!doLogin(request, userName, password)) {                		
                 response.sendRedirect(response.encodeRedirectURL("/login?rejected=true"));                	
                 return;
            } ....}
    

    Producing the Response - login.mustache

    <form method="POST" action="/login">
     <div class="mdl-textfield mdl-js-textfield">
         <input class="mdl-textfield__input" type="text" name="userName" id="userName"/>
         <label class="mdl-textfield__label" for="userName">Username</label>
     </div>
     <div class="mdl-textfield mdl-js-textfield">
         <input class="mdl-textfield__input" type="password" name="password" id="password"/>
         <label class="mdl-textfield__label" for="password">Password</label>
     </div>
     <div>
        <button class="mdl-button mdl-button--colored mdl-js-button mdl-js-ripple-effect" type="submit" name="act" value="login">Log in</button>
        <button class="mdl-button mdl-button--colored mdl-js-button mdl-js-ripple-effect" type="submit" name="act" value="register">Register</button>
     </div>
            {#rejected}}   <p>Try Again</p>  {{/rejected}}
     </form>...
    

    Re-directing on the Server

    in response method doX(...){...}, i.e. doGet(){...}

    send response.sendRedirect(response.encodeRedirectURL("/logout"));

    This creates another request for URL:

    localhost:9000/logout

    Which will then be passed to Runner

    Depending on which Servlet has been set up for the request for "/logout" using ContextHandler, that servlet will provide the response.

    📷 Redirecting on the Client - Example

    📷 Redirecting on the Client - Example

    📷 Redirecting on the Client - Example

    X
    ShopServlet Example
    X
    LoginServlet Example

    doPost():
    doLogin():
    doRegister():
    X
    Redirecting on the Client Example
    http://localhost:9000/shop/sku/0300096747
    X
    Redirecting on the Client Example
    http://localhost:9000/shop/
    X
    Redirecting on the Client Example
  • Example - Generating the new Request

    The "botton" is a link <a>

    That is styled as a button using CSS

    Its href attribute is the address of the next page

    Example:

    <a class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect store-cart__button" data-role="button" href="/shop" data-upgraded=",MaterialButton,MaterialRipple">Back to Store<a>
    

    Defining which Servlet handles the Response

    In class Runner.java set up a Context Handler

    Example:

    ServletContextHandler handler = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS);
    handler.setInitParameter("org.eclipse.jetty.servlet.Default." + "resourceBase", "src/main/resources/webapp");
    SkuServlet skuServlet = new SkuServlet();
    handler.addServlet(new ServletHolder(skuServlet), "/sku.mustache");
    

    If in Doubt, look up the API

    import 🔗 org.eclipse.jetty.servlet.ServletContextHandler;

    Allows for simple construction of a context and optionally session and security handlers.

    The Jetty Web Server

    The Jetty Web Server provides an HTTP server and Servlet container

    Is capable of serving static and dynamic content

    either from a standalone or embedded instantiations.

    Benefit: easy to configure

    Alternative: configuration file web.xml

    Using Jetty - Runner.java

    //import the libraries - pom.xml
    //the Jetty HTTP Servlet Server
    import org.eclipse.jetty.server.Server;
    ...
    //define the port to listen to
    private static final int PORT = 9000;
    ...
    private void start() throws Exception {
    	//instantiate the server
        Server server = new Server(PORT);
    	...
    }
    

    Dependency Injection

    By using the Java Dependency Injection design pattern we can remove the hard-coded dependencies and make our application loosely coupled, extendable and maintainable.

    We move the dependency resolution from compile-time to runtime.

    DI Example (1)

    package com.journaldev.java.legacy; 
    public class EmailService { 
    public void sendEmail(String message, String receiver){ 
       //logic to send email 
       System.out.println("Email sent to " +receiver+ " with Message="+message); 
       } 
    }
    

    DI Example (2)

    package com.journaldev.java.legacy; 
    public class MyApplication { 
       private EmailService email = new EmailService(); 
       public void processMessages(String msg, String rec){ 
          //do some msg validation, manipulation logic etc 
          this.email.sendEmail(msg, rec); 
      } 
    }
    

    DI Example (3) Alternative

    package com.journaldev.java.legacy; 
    public class MyApplication { 
       private EmailService email = null; 
       public MyApplication(EmailService svc){ 
          this.email=svc; 
       } 
       public void processMessages(String msg, String rec){ 
       //do some msg validation, manipulation logic etc 
          this.email.sendEmail(msg, rec); 
       } 
    }
    
  • Limitations

    MyApplication class is responsible to initialize the email service and then use it. This leads to hard-coded dependency. If we want to switch to some other advanced email service in future, it will require code changes in MyApplication class.

    If we want to extend our application to provide additional messaging feature, such as SMS or Facebook message then we would need to write another application for that. This will involve code changes in application classes and in client classes too.

    our application is directly creating the email service instance. Testing is difficult. There is no way we can mock these objects in our test classes.

    DI Requirements

    Service components should be designed with base class or interface. It’s better to prefer interfaces or abstract classes that would define contract for the services.

    Consumer classes should be written in terms of service interface.

    Injector classes that will initialize the services and then the consumer classes.

    DI - Service Components as interface

    package com.journaldev.java.dependencyinjection.service; 
    public interface MessageService { 
       void sendMessage(String msg, String rec); 
    }
    

    Implementation - Guice

    Google Guice is the framework to automate the dependency injection in applications.
    Guice sets up one filter,
    in Runner:
    Guice.createInjector(new BindingModule(), new RouteModule());

    Constructor Injection

    Constructor injection combines instantiation with injection.
    Annotate the constructor with the @Inject annotation.
    This constructor should accept class dependencies as parameters.
    Most constructors will then assign the parameters to final fields.
    Explicit annotation is preferable because it documents that the type participates in dependency injection.
    If there is no @Inject annotation on constructor, Guice will use a public, no-arguments constructor if it exists.

    Constructor Injection Example

    public class RealBillingService implements BillingService {
       private final CreditCardProcesor processorProvider;
       private final TransactionLog transactionLogProvider;
       
       @Inject
       public RealBillingService(CreditCardProcessor processorProvider, TransactionLog transactionLogProvider){
          this.processorProvider = processorProvider;
          this.transactionLogProvider = transactionLogProvider;
       }
    }
    

    Method Injection

    Guice can inject methods that have the @Inject annotation.

    Dependencies take the form of parameters,

    which the injector resolves before invoking the method.

    Injected methods may have any number of parameters, and the method name does not impact injection.

    Method Injection Example

    public class PayPalCreditCardProcessor implements CredtCardProcessor {
    
      private static final String DEFAULT_API_KEY = "development-use-only";
      
      private String apiKey = DEFAULT_API_KEY;
      
      @Inject
      public void setApiKey(@Named9"PayPal API key") String apiKey){
         this.apiKey = apiKey;
      }
    }
    

    Field Injection Example

    Annotate fields with the @Inject annotation.

    This is the most concise injection,

    but the least testable.

    Field Injection Example

    public class DatabaseTransactionLogProvider implements Provider<TransactionLog>{
      @Inject Connection connection;
      
      public TransactionLog get() {
         return new DatabaseTransactionLog(connection);
      }
    }
    
  • Google Guice

    Google Guice is one of the leading frameworks whose main work is to provide automatic implementation of dependency injection.

    Google Guice support both setter-based and constructor-based dependency injection. Our application class that consumes the service looks like below.

    Guice in Context

    sub package guice, e.g.

    package uk.ac.wpd2.group2.shop.guice;

    sub sub package annotations

    package uk.ac.wpd2.group2.shop.guice.annotations;

    @BindingAnnotation
    @Target({FIELD, PARAMETER, METHOD})
    @Retention(RUNTIME)
    public @interface DefaultShop {
    }
    
    public class BindingModule extends AbstractModule {
        @SuppressWarnings({"unused"})
        static final Logger LOG = LoggerFactory.getLogger(BindingModule.class);
        public BindingModule() {}
        @Override
        protected void configure() {
            bind(Shop.class).annotatedWith(DefaultShop.class).toInstance(new ShopLoader().load());
            bind(String.class).annotatedWith(CsrfParamName.class).toInstance("csrf");
            bind(IUserLogin.class).toInstance(new H2User(H2User.DB.MEMORY));
        }
    }
    
    public class RouteModule extends ServletModule {
        @SuppressWarnings({"unused"})
        static final Logger LOG = LoggerFactory.getLogger(RouteModule.class.getName());
        
        public RouteModule() {
        
        }
        
        @Override
        protected void configureServlets() {
             filter("/*").through(CsrfFilter.class, ImmutableMap.of("guardedPaths", "/cart.+"));
             serve("/login").with(LoginServlet.class);
             serve("/logout").with(LogoutServlet.class);
             serve("/shop").with(ShopServlet.class);
             serve("/shop/sku/*").with(SkuServlet.class);
             serve("/shop/cart").with(CartServlet.class);
             serve("/shop/cart/pay").with(CartServlet.class);
             serve("/shop/cart/deleteSku").with(DeleteSkuServlet.class);
             serve("*.html").with(MustacheServlet.class);
             
             // Needed for Jetty, and serves static content
             bind(DefaultServlet.class).in(Scopes.SINGLETON);
             serve("/*").with(DefaultServlet.class, configuredDefault());
             }
    

    RouteModule (2)

    private Map<String,String> configuredDefault() {
       Map<String, String> params = new HashMap<>();
       params.put("resourceBase", "src/main/resources/webapp");
       params.put("dirAllowed", "true");
       return params;
    }
    
  • In Runner - Guice Filter

    import com.google.inject.Guice;
    import com.google.inject.servlet.GuiceFilter;
    

    In Runner.java

    private void start() throws Exception {
       Guice.createInjector(new BindingModule(), new RouteModule());
       Server server = new Server(PORT);
       ...
    }
    

    Adding a Guice Filter

    handler.addFilter(GuiceFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
    

    Guice API (1)

    The entry point to the Guice framework. Creates Injectors from Modules.

    Guice supports a model of development that draws clear boundaries between APIs, Implementations of these APIs, Modules which configure these implementations, and finally Applications which consist of a collection of Modules. It is the Application, which typically defines your main() method, that bootstraps the Guice Injector using the Guice class, as in this example:

    Guice API Screenshot

    Guice Annotations

    From com.google.inject or javax.inject packages

    Construct an instance of ... servlet

    @Inject
    Use this constructor when you use the injector to create an instance of a class
    Either default or @Inject one (@Inject is preference if there is default constructor)

    @Annotation

    @BindingAnnotation - Guice

    @Target({FIELD, PARAMETER, METHOD}) - java.lang

    where can it be put

    Parameter used now, parameter in servlet constructor

    @Retention(RUNTIME) - java.lang

    when do you use it, here at runtime

    Guice Maven Dependency

    Include in the pom file
    <dependency>
    	<groupId>com.google.inject</groupId>
    	<artifactId>guice</artifactId>
    	<version>3.0</version>
    </dependency>
    
  • Further Reading

    https://www.w3.org/TR/webarch/

    http://www.journaldev.com/1854/java-web-application-tutorial-for-beginners

    http://www.journaldev.com/1877/servlet-tutorial-java#servlet-api-hierarchy

    http://www.eclipse.org/jetty/documentation/

    https://github.com/google/guice/wiki/GettingStarted

    http://www.journaldev.com/2394/java-dependency-injection-design-pattern-example-tutorial

    http://www.journaldev.com/2403/google-guice-dependency-injection-example-tutorial