Cross Site Scripting (XSS) Attack Remediation

XSS

For more details on XSS Attack refer OWASP, and OWASP Prevention cheat sheet

Preventing XSS

Various factors should be considered while Acting on XSS Attacks, for example

  • input type in the HTTP request
  • Locations of the HTML document where data would be included 

Note

  • A defense that works in one context (such as an HTML attribute) might not work in another context (such as a JavaScript variable assignment)
  • A defense that works with one kind of input (such as input validation and output encoding for a username) will not work with other kinds of input (such as sanitization for untrusted HTML).

We need to use a different output encoding function based on where you are inserting untrusted data into the webpage!

OWASP Java Encoder Project

<dependency>
    <groupId>org.owasp.encoder</groupId>
    <artifactId>encoder</artifactId>
    <version>1.2.1</version>
</dependency>
<dependency>
    <groupId>org.owasp.encoder</groupId>
    <artifactId>encoder-jsp</artifactId>
    <version>1.2.1</version>
</dependency>

Here are a few examples of different contexts in an HTML page in a JSP:

Encoding

HTML

The following encoding functions are used to safely place untrusted data into different locations of an HTML document.

APIComents
Encode.forHtml(UNTRUSTED) If you are unsure, which one to use, you can use this in HTML context
Encode.forHtmlAttribute(UNTRUSTED)
Encode.forHtmlContent(UNTRUSTED)
Encode.forHtmlUnquotedAttribute(UNTRUSTED)

JavaScript

The following encoding functions are used to safely place untrusted data into different locations of JavaScript code.

APIComments
Encode.forJavaScript(UNTRUSTED)If you are unsure, which one to use, you can use this in JavaScript context
Encode.forJavaScriptAttribute(UNTRUSTED)
Encode.forJavaScriptBlock(UNTRUSTED)
Encode.forJavaScriptSource(UNTRUSTED)

CSS


The following encoding functions are used to safely place untrusted data into different locations of dynamic CSS code.

APIComments
Encode.forCssString(UNTRUSTED)<div style=”width:<= Encode.forCssString(UNTRUSTED) %>”>
Encode.forCssUrl(UNTRUSTED)<div style=”background:<= Encode.forCssUrl(UNTRUSTED) %>”>

XML

APIComments
Encode.forXML(UNTRUSTED)
Encode.forXMLContent(UNTRUSTED)
Encode.forXMLAttribute(UNTRUSTED)
Encode.forXMLComment(UNTRUSTED)
Encode.forCDATA(UNTRUSTED)

Tag lib

Prefer tag libs while working with jsps

 
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@taglib prefix="e" uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project" %>
<html>
<head>
<title><e:forHtml value="${param.title}" /></title>
</head>
<body>
<h1>${e:forHtml(param.data)}</h1>
</body> P

For more details on this refer the OWASP Java Encoder Project Docs

Wrapper Class

import javax.servlet.http.HttpServletRequest;
 
import org.owasp.encoder.Encode;
 
public class SafeDataBuilder {
 
    private String paramVal = null;
 
    private SafeDataBuilder(HttpServletRequest request, String paramName) {
        String val = getValue(request, paramName);
        this.paramVal = cleanValue(val);
    }
 
    private String cleanValue(String val) {
        String result = val;
        if (val != null && val.length() > SecurityConstants.MAX_HTTP_PARAM_LENGTH) {
            result = val.substring(0, SecurityConstants.MAX_HTTP_PARAM_LENGTH);
        }
        return result;
    }
 
    private String getValue(HttpServletRequest request, String paramName) {
        String val = request.getParameter(paramName);
 
        if (val == null) {
            Object attr = request.getAttribute(paramName);
            if (attr instanceof String) {
                val = (String) attr;
            }
            if (attr instanceof Boolean) {
                val = attr.toString();
            }
        }
        return val;
    }
 
    public static SafeDataBuilder requestParam(HttpServletRequest request, String paramName) {
        return new SafeDataBuilder(request, paramName);
    }
 
    public SafeDataBuilder defaultValue(String val) {
        if (this.paramVal == null) {
            this.paramVal = val;
        }
        return this;
    }
     
    public SafeDataBuilder trim() {
        if (this.paramVal != null) {
            this.paramVal = paramVal.trim();
        }
        return this;
    }
 
    public SafeDataBuilder forHtml() {
        if (this.paramVal != null) {
            this.paramVal = Encode.forHtml(this.paramVal);
        }
        return this;
    }
 
    public SafeDataBuilder forHtmlContent() {
        if (this.paramVal != null) {
            this.paramVal = Encode.forHtml(this.paramVal);
        }
        return this;
    }
 
    public SafeDataBuilder forHtmlAttribute() {
        if (this.paramVal != null) {
            this.paramVal = Encode.forHtml(this.paramVal);
        }
        return this;
    }
     
   public SafeDataBuilder forFormActionAttribute() {
        if (this.paramVal != null) {           
            this.paramVal = Encode.forHtmlAttribute(cleanJsAttribute(this.paramVal));
        }
        return this;
    }
 
    private String cleanJsAttribute(String action) {
        String result = action;
        String cleansed = action.trim().toLowerCase();
        if (cleansed.startsWith("javascript")) {
            result = cleansed.substring(10);
        }
        return result;
    }
    public SafeDataBuilder forJavaScript() {
        if (this.paramVal != null) {
            this.paramVal = Encode.forJavaScript(this.paramVal);
        }
        return this;
    }
 
    public SafeDataBuilder forJavaScriptAttribute() {
        if (this.paramVal != null) {
            this.paramVal = Encode.forJavaScriptAttribute(this.paramVal);
        }
        return this;
    }
 
    public SafeDataBuilder forJavaScriptBlock() {
        if (this.paramVal != null) {
            this.paramVal = Encode.forJavaScriptBlock(this.paramVal);
        }
        return this;
    }
 
    public SafeDataBuilder forJavaScriptSource() {
        if (this.paramVal != null) {
            this.paramVal = Encode.forJavaScriptSource(this.paramVal);
        }
        return this;
    }
 
    public SafeDataBuilder forCssString() {
        if (this.paramVal != null) {
            this.paramVal = Encode.forCssString(this.paramVal);
        }
        return this;
    }
 
    public SafeDataBuilder forCssUrl() {
        if (this.paramVal != null) {
            this.paramVal = Encode.forCssUrl(this.paramVal);
        }
        return this;
    }
 
    public SafeDataBuilder forUriComponent() {
        if (this.paramVal != null) {
            this.paramVal = Encode.forUriComponent(this.paramVal);
        }
        return this;
    }
 
    public String get() {
        return this.paramVal;
    }
 
 
    public String getQuoted() {
        return "'" + this.paramVal + "'";
    }
}

Usage

String paramVal = SafeDataBuilder.requestParam(request, "paramName").forHtml().get();
String paramVal = SafeDataBuilder.requestParam(request, "paramName").defaultValue("def").forHtml().get();
String paramVal = SafeDataBuilder.requestParam(request, "paramName").defaultValue("def").trim().forHtml().get();

Solution

Refer the project for more details

  • Define a config for each page.
  • The config describes what are all parameters (and xss type) used by the page
  • Configure a XSS filter (XSSFilter) for every request, which wraps httpservelet request (XSSRequestWrapper ).
  • Eventually every page has XSSRequestWrapper as HTTPServletRequst, whenever getParameter happens, config is read to the determine the XSS type, and data is stripped accordingly.
  • Further we may have to define one more method in XSSRequestWrapper getParameter (name, type) In case if need arise
  • Further we may have to define one more method in XSSRequestWrapper getOriginalParameter (name) In case if need arise
  • Further by default, for each parameter p, there should other for example p_xss_s_xss_type (for each xss_type)

References

Advertisements

A Stateless Approach To CSRF Protection

CSRF

  • A CSRF attack can occur when an authenticated user moves to a malicious website while still logged into the target web application. Malicious HTTP requests can then be routed to the target site via the victim’s browser. The application will perform the task as requested because it stems from the browser of an authenticated user.
  • Essentially, CSRF is an exploitation of the trust a browser has in an authenticated user.

For CSRF To Happen

  • User should be Authenticated
  • Malicious act happens on authenticated user browser

CSRF Prevention Techniques

OWASP describes various prevention techniques

Introduction

Double submit is a variation of the token scheme where the client is required to submit the token (cookie can be generated by the client and never saved by the server) both as a request parameter and as a cookie.

A malicious page on another domain cannot read the anti-CSRF cookie before its request and thus cannot include it as a request parameter.

Implementation

Approach #1 : Generating Cookie In Client Side

We have got two things to do for this to implement.

Using this approach all your server has to do is check if both values are equal, on a stateless per request basis!

Client Side

var CookieReader = (function() {
    var lastCookies = {};
    var lastCookieString = '';
 
    function safeGetCookie() {
        try {
            return document.cookie || '';
        } catch (e) {
            return '';
        }
    }
 
    function safeDecodeURIComponent(str) {
        try {
            return decodeURIComponent(str);
        } catch (e) {
            return str;
        }
    }
 
    function isUndefined(value) {
        return typeof value === 'undefined';
    }
 
    return function () {
        var cookieArray, cookie, i, index, name;
        var currentCookieString = safeGetCookie();
 
        if (currentCookieString !== lastCookieString) {
            lastCookieString = currentCookieString;
            cookieArray = lastCookieString.split('; ');
            lastCookies = {};
 
            for (i = 0; i < cookieArray.length; i++) {
                cookie = cookieArray[i];
                index = cookie.indexOf('=');
                if (index > 0) { //ignore nameless cookies
                    name = safeDecodeURIComponent(cookie.substring(0, index));
 
                    if (isUndefined(lastCookies[name])) {
                        lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
                    }
                }
            }
        }
        return lastCookies;
    };
})();
 
function CsrfForm() {
 
    var csrfTokenName = 'CSRF-TOKEN';
 
    function createHiddenElement($form) {
        var csrfElement = document.createElement("input");
 
        csrfElement.type = "hidden";
        csrfElement.value = CookieReader()[csrfTokenName];
        csrfElement.name = csrfTokenName;
 
        $form.appendChild(csrfElement);
    }
 
    function createCookie() {
        document.cookie = csrfTokenName + '=' + UUID();
    }
 
    function UUID(a) {
        return a ? (a ^ Math.random() * 16 >> a / 4).toString(16) : ([1e16] + 1e16).replace(/[01]/g, UUID);
    }
 
    return {
        submit: function ($form) {
            createCookie();
            createHiddenElement($form);
            $form.submit();
        }
    };
}

Just add the following in each jsp page having the form and everything would be taken care.

new CsrfForm().submit(document.theForm)

Server Side 

CSRFValidationFilter


import org.apache.commons.lang3.StringUtils;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.web.filter.OncePerRequestFilter;
 
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.regex.Pattern;
 
public class CSRFValidationFilter extends OncePerRequestFilter {
 
    private static final String DEFAULT_CSRF_TOKEN_NAME = "CSRF-TOKEN";
    private static final String TOKEN_NAME_INIT_PARAM_NAME = "CSRF_TOKEN_NAME";
 
    private static final String CSRF_REFERER_CHECK_INIT_PARAM_NAME = "CSRF_REFERRER_CHECK";
    private static final String HEADER_NAME_REFERRER = "referer";
 
    private RequestMatcher requireCsrfProtectionMatcher = new DefaultRequiresCsrfMatcher();
 
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
 
        if (isReferrerValid(httpServletRequest) && requireCsrfProtectionMatcher.matches(httpServletRequest)) {
 
            String tokenName = getTokenName();
            final String csrfTokenValue = request.getParameter(tokenName);
            final String csrfCookieValue = csrfCookieValue(httpServletRequest, tokenName);
            if (csrfTokenValue == null || !csrfTokenValue.equals(csrfCookieValue)) {
                throw new RuntimeException("Operation not Allowed");
            }
        }
 
        filterChain.doFilter(request, response);
    }
 
    private boolean isReferrerValid(HttpServletRequest httpServletRequest) {
        return shouldCheckReferrer() && isReferrerAllowed(httpServletRequest);
    }
 
    private boolean isReferrerAllowed(HttpServletRequest httpServletRequest) {
        String referrer = httpServletRequest.getHeader(HEADER_NAME_REFERRER);
        //TODO : Add more detail
        return true;
    }
 
    private boolean shouldCheckReferrer() {
        String configValue = getFilterConfig().getInitParameter(CSRF_REFERER_CHECK_INIT_PARAM_NAME);
        return StringUtils.isBlank(configValue) ? true : Boolean.valueOf(configValue);
    }
 
    private String csrfCookieValue(HttpServletRequest httpServletRequest, String tokenName) {
        String csrfCookieValue = null;
 
        final Cookie[] cookies = httpServletRequest.getCookies();
 
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (tokenName.equals(cookie.getName())) {
                    csrfCookieValue = cookie.getValue();
                }
            }
        }
        return csrfCookieValue;
    }
 
    private String getTokenName() {
        String configValue = getFilterConfig().getInitParameter(TOKEN_NAME_INIT_PARAM_NAME);
        return StringUtils.isBlank(configValue) ? DEFAULT_CSRF_TOKEN_NAME : configValue;
    }
 
    private static final class DefaultRequiresCsrfMatcher implements RequestMatcher {
        private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
 
        public boolean matches(HttpServletRequest request) {
            return !allowedMethods.matcher(request.getMethod()).matches();
        }
    }
}
<filter>
    <filter-name>CSRFValidationFilter</filter-name>
    <filter-class>com.xyz.servlet.CSRFValidationFilter</filter-class>
</filter>
 
<filter-mapping>
    <filter-name>CSRFValidationFilter</filter-name>
    <url-pattern>/administration/Administration.jsp</url-pattern>
</filter-mapping>

Approach #2 : Generating Cookie In Server Side Per Session

Add new filter

public class CsrfTokenGenerationFilter extends OncePerRequestFilter {
 
    private static final String ALREADY_FILTERED_SUFFIX = ".FILTERED";
    private static final String DEFAULT_CSRF_TOKEN_NAME = "CSRF-TOKEN";
 
    private static final String TOKEN_NAME_INIT_PARAM_NAME = "csrf.token.name";
 
    private String tokenName = DEFAULT_CSRF_TOKEN_NAME;
    private String contextPath = null;
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        super.init(filterConfig);
        this.tokenName = tokenName(filterConfig);
        this.contextPath = contextPath(filterConfig);
    }
 
    private String contextPath(FilterConfig filterConfig) {
        ServletContext servletContext = filterConfig.getServletContext();
        return servletContext.getContextPath();
    }
 
    private String tokenName(FilterConfig filterConfig) {
        String configValue = filterConfig.getInitParameter(TOKEN_NAME_INIT_PARAM_NAME);
        return StringUtils.isBlank(configValue) ? DEFAULT_CSRF_TOKEN_NAME : configValue;
    }
 
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        HttpSession session = httpRequest.getSession();
 
        String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
        boolean notFiltered = session.getAttribute(alreadyFilteredAttributeName) == null;
 
        if (notFiltered) {
            session.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
            addCookie(httpResponse);
        }
        filterChain.doFilter(request, response);
    }
 
    private void addCookie(HttpServletResponse httpResponse) {
        httpResponse.addCookie(newCookie());
    }
 
    private Cookie newCookie() {
        final Cookie cookie = new Cookie(tokenName, createNewToken());
        cookie.setPath(contextPath);
        //cookie.setSecure(true); //local this wont work
        return cookie;
    }
 
    protected String getAlreadyFilteredAttributeName() {
        return getClass().getName() + ALREADY_FILTERED_SUFFIX;
    }
 
    private String createNewToken() {
        return UUID.randomUUID().toString();
    }
 
    @Override
    public void destroy() {
 
    }
}
  • This technique is bullet proof and well proven (DWR and AngularJs Uses it)
  • Using the tools like Burp and Fidler you may capture the request on client machine and assume that it is broken (since request parameter is already copied from the cookie), however in real time that is not possible, Even if we assume that this can happen then a lot more can happen than just CSRF, and we would be having very bigger problem to tackle.

Spring Controllers Implementing Interfaces ??

Getting the Following error when Spring Controller implements interfaces


The mapped controller method class 'com.xyz.AbcController' is not an instance of the actual controller bean instance 'com.sun.proxy.$Proxy108'.If the controller requires proxying (e.g. due to @Transactional), please use class-based proxying.

The error is crystal clear, and provides a suggestion how to fix the problem

The solution would be to make sure class-based proxying is used (As shown in line number 2).

@Controller
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class AbcController implements SomeConcerenedInterface {
 
 
}

Why ?

As per spring proxying

Spring AOP uses either JDK dynamic proxies or CGLIB to create the proxy for a given target object. (JDK dynamic proxies are preferred whenever you have a choice).

If the target object to be proxied implements at least one interface then a JDK dynamic proxy  (if ther is a $ProxyXXX, it means there is an interface)  will be used. All of the interfaces implemented by the target type will be proxied. If the target object does not implement any interfaces then a CGLIB proxy will be created.

Now since the com.xyz.AbcController is marked with @Controller (Which is s specialization of @Component) and when it implements interface, A proxy of that interface is created. and since the @RequestMapping method is not present in the interface, error is thrown(As can be seen in InvocableHandlerMethod.assertTargetBean method).

The issue is overcome by switching to class based proxying (using CGLIB, which works by dynamically creating a subclass of the original bean as proxy)

Finally

The best practice is @Controller annotation is on concrete classes, and it is advisable not implement any interface, If we do, then proper measures has to be taken to make sure (a) It is an concerned interface and (b) proper annotations are present in the interface.

Don’t Complicate Spring Controllers With Commotions

@Controller Implementing Interface

You may get into the problem as described below


The mapped controller method class 'com.xyz.ABController' is not an instance of the actual controller bean instance 'com.sun.proxy.$Proxy108'.
If the controller requires proxying (e.g. due to @Transactional), please use class-based proxying.

so better not do the following.

Don’t

@Controller
public class SomeController implements SomeConcerenedInterface {
   
}

@Controller Extending Another @Controller

If the intent is to share the logic, better do it with composition in this case, the reason is you may end up exposing an endpoint unintentionally in ChildController which may be inherited from ParentController

Further that is old way of doing things, before Annotations in Spring

Don’t

@Controller
public class ParentController {
   
}
 
@Controller
public class ChildController extends ParentController {
   
}

Simple Controller 

The best practice is to keep the @Controller class simple as shown below (don’t imlement interface, dont extent another conroller), @Controller should be to expose an endpoint, and the processing logic should be deligated to another abstraction (This way logic can be shared accross multiple @Controllers if required)

Do

@Controller
public class SomeController {
   
}

@Controller Extending another BasClass

This case should be avoided as much as possible, If possible use composition here.

May Do

public class SomeBaseClassWithOutControllerAnnotation {
  //May contain methods Without @RequestMapping
}
 
**//Discouraged**
@Controller
public class SomeController extends SomeBaseClassWithOutControllerAnnotation  {
   
}

The Constant Interface Pattern Is Discouraged

It has been an age old practice to place commonly used constants in an interface, and classes implementing it can directly access those constants, without prefixing the Interface name.

Advantages of this practice

AdvantageRemarks
No need to worry about instantiating a classConstant classes are meant not to be instantiated and hence has a private constructor
Any thing??
Access the constants directly with out prefixing a namespaceJava static import can be used with classes

Disadvantages of this practice

Constant Interface does not define a type

It is being considered a good practice to segregate the contract (Interface defining the type and behavior) from implementation, and brings in lots of benefit. Lets consider some examples.

public class Employee implements Person {  }Employee is a Person and defines specific behavior specific to Person
public class Tiger implements Animal {}
Tiger is a Animal and defines specific behavior specific to Animal

However when we write the following, it really does not make any sense. Hence constant interface by its very nature does not define any type.

public class Tiger implements SessionContants {}What does it convey?Tiger is a SessionConstants?  🙂 🙂

Run-time Issues, because of field shadowing


public interface SessionConstants {
String SESSION_NAME = "XYZ";
}
 
 
public class HttpSession implements SessionConstants {
 
private static final String SESSION_NAME = "ABC";
 
public static void main(String[] args) {
System.out.println(SESSION_NAME);
}
}

What you think the sysout would print?
Is it desirable?


It just works fine with out any warning/error, unlike with Constants class [there would be a warning].
Unless a developer checks any implemented interfaces when adding a constant to a class, or does so but makes a typo in the new constant’s name, the value of a constant can be silently changed.

Namespace pollution

The named constants appear in the namespace of all implementing classes as well as their sub-classes.

Code Compatibility issues 

If binary code compatibility is required in future releases, the constants interface must remain forever an interface (it cannot be converted into a class), even though it has not been used as an interface in the conventional sense.

Constant Class approach

The fact that the interface CAN be implemented by an individual if desired, leaves room for the issues pointed out above. So it’s best to prevent the ability to implement the interface altogether. Hence, it’s more appropriate to have a final class that can’t be instantiated (With private constructor) at all.

Bad Practice

public interface SessionConstants {
    String COOKIE_NAME = "JSESSIONID";
    String WLS_AUTHCOOKIE_PREFIX = "_WL_AUTHCOOKIE_";
    String DEFAULT_WLS_AUTHCOOKIE = "_WL_AUTHCOOKIE_JSESSIONID";
}

Preferred approach

public final class SessionConstants {
    public static final String COOKIE_NAME = "JSESSIONID";
    public static final String WLS_AUTHCOOKIE_PREFIX = "_WL_AUTHCOOKIE_";
    public static final String DEFAULT_WLS_AUTHCOOKIE = "_WL_AUTHCOOKIE_JSESSIONID";
     
    private SessionConstants() {
    }
}

Advantages of this approach

  • Since the required static memebers are imported statically, the class namespace is not polluted.
  • The compiled code has one fewer binary compatibility constraint (that “class implements Constants Interface”).
  • Because static imports apply only to the current file (and not the whole class hierarchy) it is easier to discover where each static member is declared.
  • Run-time and compile-time semantics are more closely aligned when using static imports instead of constants interfaces.
  • If Required static blocks can be declared.

Disadvantages of this approach

TODO : List out

Constant Interface Pattern and the rest of the world

Joshua bloch in his famous book, Effective Java talks about it in great detail

The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class’s exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a non final class implements a constant interface, all of its sub classes will have their namespaces polluted by the constants in the interface.

It is indeed a distasteful use of interfaces, since interfaces should deal with the services provided by an object, not its data. As well, the constants used by a class are typically an implementation detail, but placing them in an interface promotes them to the public API of the class. And hence,

Interfaces should only be used to define contracts and not constants

Running Multiple Instances Of Tomcat In Same Machine

Configuring

Step 1 : Download And Extract

Download

Extract

Step 2 : Instance 1

Create folder instance1, create two folders bin and conf

copy server.xml from tomcat

create startup and shutdown scripts

Startup

@echo off
 
set CATALINA_BASE=D:\softwares\Tomcat\Tomcat8.5\Instance1
set CATALINA_HOME=D:\softwares\Tomcat\Tomcat8.5\apache-tomcat-8.5.34
 
cd "%CATALINA_HOME%\bin"
 
set TITLE=Tomcat Instance 01
 
call startup.bat %TITLE%

Shutdown

@echo off
 
set CATALINA_BASE=D:\softwares\Tomcat\Tomcat8.5\Instance1
set CATALINA_HOME=D:\softwares\Tomcat\Tomcat8.5\apache-tomcat-8.5.34
 
cd "%CATALINA_HOME%\bin"
 
call shutdown.bat

Step 3 : Instance 2

Copy instance1 to instance2

Change the following in instance2

CATALINA_BASE and title in startup and shutdown scripts,

server port, connector http port, connector ajp port, redirect port, 

Starting

Deploying

Paste context.xml files in the following locations

instance1/conf/Catalina/localhost

instance2/conf/Catalina/localhost

for example lets create app.xml as follows, keep a note of docBase.

<?xml version="1.0" encoding="UTF-8"?>

<Context path="/app" debug="0" reloadable="false" docBase="D:\practices\apps\wicket\wicket-app\target\wicket-app-1.0-SNAPSHOT">
    <Environment name="appHome" type="java.lang.String" value="${catalina.home}/webapps/app"/>

</Context>

When To Use Java 8 default methods in interfaces

One of the Oracle’s article describes in great detail, when Default methods should be opted, 

The section Interfaces describes an example that involves manufacturers of computer-controlled cars who publish industry-standard interfaces that describe which methods can be invoked to operate their cars. What if those computer-controlled car manufacturers add new functionality, such as flight, to their cars? These manufacturers would need to specify new methods to enable other companies (such as electronic guidance instrument manufacturers) to adapt their software to flying cars. Where would these car manufacturers declare these new flight-related methods? If they add them to their original interfaces, then programmers who have implemented those interfaces would have to rewrite their implementations. If they add them as static methods, then programmers would regard them as utility methods, not as essential, core methods.

Default methods  enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.

Here is what we can deduct :

  • Default method (Defender methods) should be used for backward compatibility. Whenever you want to add additional functionality in an existing interface you can use default methods without breaking any existing implementing classes (Default methods enable to add new functionality to existing Interfaces without breaking older implementation of these Interfaces).
  • Default methods in interfaces were introduced to the Java language in order to evolve the collections library for the Streams API (As can be seen).
  • The Idea is not you design your solution with default methods in mind, but rather they are an afterthought.

Java has long history of being backward compatible

  • It is because of backward compatibility (In mind) Java generics are Type Erasure instead of reifiable Type
  • It is because of backward compatibility(In mind)  we still find AWT.
  • It is because of backward compatibility (In mind) we still have Vector (event thought we have Arraylist and CopyOnWriteArrayList )
  • It is because of backward compatibility (In mind) Default methods are introduced.

Why Default Methods

It was a smart move to evolve the existing API (collection for example) and to introduce new programming models (Functional for example) without breaking zillion lines of code. For example 

  • java.util.Collection Interface now has methods related to Stream, at the same time being compatible with existing version
  • java.lang.Iterable Interface now supports functional way of programming.