Merge pull request #194 from apache/dependabot/maven/slf4j.version-1.7.32

Bump slf4j.version from 1.7.31 to 1.7.32
diff --git a/modules/json/src/org/apache/axis2/json/gson/JsonFormatter.java b/modules/json/src/org/apache/axis2/json/gson/JsonFormatter.java
index 776674f..6c42c44 100644
--- a/modules/json/src/org/apache/axis2/json/gson/JsonFormatter.java
+++ b/modules/json/src/org/apache/axis2/json/gson/JsonFormatter.java
@@ -101,7 +101,7 @@
                 try {
                     GsonBuilder gsonBuilder = new GsonBuilder(); 
                     // XSS protection, encode JSON Strings as HTML
-                    gsonBuilder.registerTypeAdapter(String.class, new JsonHtmlXssSerializer());
+                    gsonBuilder.registerTypeAdapter(String.class, new JsonHtmlEncoder());
                     Gson gson = gsonBuilder.create();
                     jsonWriter.beginObject();
                     jsonWriter.name(JsonConstant.RESPONSE);
diff --git a/modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java b/modules/json/src/org/apache/axis2/json/gson/JsonHtmlEncoder.java
similarity index 94%
rename from modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java
rename to modules/json/src/org/apache/axis2/json/gson/JsonHtmlEncoder.java
index 619c1ae..0b76443 100644
--- a/modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java
+++ b/modules/json/src/org/apache/axis2/json/gson/JsonHtmlEncoder.java
@@ -27,7 +27,7 @@
 import com.google.gson.JsonSerializer;
 import java.lang.reflect.Type;
 
-public class JsonHtmlXssSerializer implements JsonSerializer<String> {
+public class JsonHtmlEncoder implements JsonSerializer<String> {
 
 	@Override
 	public JsonElement serialize(String src, Type typeOfSrc,
diff --git a/modules/json/src/org/apache/axis2/json/moshi/JsonFormatter.java b/modules/json/src/org/apache/axis2/json/moshi/JsonFormatter.java
index 941451e..1936873 100644
--- a/modules/json/src/org/apache/axis2/json/moshi/JsonFormatter.java
+++ b/modules/json/src/org/apache/axis2/json/moshi/JsonFormatter.java
@@ -60,7 +60,7 @@
         String msg;
 
         try {
-            Moshi moshi = new Moshi.Builder().add(String.class, new JsonHtmlXssSerializer()).add(Date.class, new Rfc3339DateJsonAdapter()).build();
+            Moshi moshi = new Moshi.Builder().add(String.class, new JsonHtmlEncoder()).add(Date.class, new Rfc3339DateJsonAdapter()).build();
             JsonAdapter<Object> adapter = moshi.adapter(Object.class);
             BufferedSink sink = Okio.buffer(Okio.sink(outputStream));
             jsonWriter = JsonWriter.of(sink);
diff --git a/modules/json/src/org/apache/axis2/json/moshi/JsonHtmlXssSerializer.java b/modules/json/src/org/apache/axis2/json/moshi/JsonHtmlEncoder.java
similarity index 95%
rename from modules/json/src/org/apache/axis2/json/moshi/JsonHtmlXssSerializer.java
rename to modules/json/src/org/apache/axis2/json/moshi/JsonHtmlEncoder.java
index 241a96e..3a7c906 100644
--- a/modules/json/src/org/apache/axis2/json/moshi/JsonHtmlXssSerializer.java
+++ b/modules/json/src/org/apache/axis2/json/moshi/JsonHtmlEncoder.java
@@ -26,7 +26,7 @@
 
 import org.owasp.encoder.Encode;
 
-public final class JsonHtmlXssSerializer extends JsonAdapter<String> {
+public final class JsonHtmlEncoder extends JsonAdapter<String> {
 
     @Override
     public synchronized String fromJson(JsonReader reader) throws IOException {
diff --git a/modules/samples/userguide/README.txt b/modules/samples/userguide/README.txt
index 0a38736..cf4d8d1 100644
--- a/modules/samples/userguide/README.txt
+++ b/modules/samples/userguide/README.txt
@@ -8,6 +8,9 @@
 The sample explains how to write a Web service and Web service client with 

 Apache Axis2 using XML based client APIs (Axis2's Primary APIs).

 

+For new applications, json-springboot-userguide.html brings Axis2 into 

+modern API's and contemporary servers. 

+

 Introduction

 ============

 

@@ -41,7 +44,7 @@
 Pre-Requisites

 ==============

 

-Apache Ant 1.6.2 or later

+Apache Ant 1.8.0 or later

 

 Building the Service

 ====================

diff --git a/modules/samples/userguide/src/userguide/springbootdemo/pom.xml b/modules/samples/userguide/src/userguide/springbootdemo/pom.xml
new file mode 100644
index 0000000..731fdec
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/pom.xml
@@ -0,0 +1,405 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements. See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership. The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License. You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied. See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>userguide.springboot</groupId>
+    <artifactId>axis2-json-api</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <packaging>war</packaging>
+    <name>axis2-json-api</name>
+    <description>Spring Boot with Axis2 demo</description>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.5.2</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+        <spring-boot.version>2.5.2</spring-boot.version>
+        <forceHttps>false</forceHttps>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <!-- Required in this userguide for 
+                 org.springframework.dao.DataAccessException 
+            -->
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.zaxxer</groupId>
+                    <artifactId>HikariCP</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.12.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.mail</groupId>
+            <artifactId>jakarta.mail</artifactId>
+            <version>1.6.7</version>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.activation</groupId>
+            <artifactId>jakarta.activation-api</artifactId>
+            <version>1.2.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jaxb</groupId>
+            <artifactId>jaxb-runtime</artifactId>
+            <version>2.3.4</version>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.xml.bind</groupId>
+            <artifactId>jakarta.xml.bind-api</artifactId>
+            <version>2.3.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-log4j2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-jul</artifactId>
+            <version>2.14.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+	<dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-collections4</artifactId>
+            <version>4.4</version>
+	</dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+	<dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <version>3.1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+            <version>2.5.2</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.11.0</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>1.15</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.6</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-validator</groupId>
+            <artifactId>commons-validator</artifactId>
+            <version>1.7</version>
+        </dependency>
+        <!-- axis2 -->
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+            <version>1.4</version>
+        </dependency>
+        <dependency>
+                <groupId>org.apache.geronimo.specs</groupId>
+                <artifactId>geronimo-ws-metadata_2.0_spec</artifactId>
+                <version>1.1.3</version>
+        </dependency>
+        <dependency>
+                <groupId>org.apache.geronimo.specs</groupId>
+                <artifactId>geronimo-jaxws_2.2_spec</artifactId>
+                <version>1.2</version>
+        </dependency>
+	<dependency>
+		<groupId>org.apache.axis2</groupId>
+		<artifactId>axis2-kernel</artifactId>
+		<version>1.8.0</version>
+	</dependency>
+	<dependency>
+		<groupId>org.apache.axis2</groupId>
+		<artifactId>axis2-transport-http</artifactId>
+		<version>1.8.0</version>
+	</dependency>
+	<dependency>
+		<groupId>org.apache.axis2</groupId>
+		<artifactId>axis2-transport-local</artifactId>
+		<version>1.8.0</version>
+	</dependency>
+	<dependency>
+		<groupId>org.apache.axis2</groupId>
+		<artifactId>axis2-json</artifactId>
+		<version>1.8.0</version>
+	</dependency>
+        <dependency>
+            <groupId>org.apache.axis2</groupId>
+            <artifactId>axis2-ant-plugin</artifactId>
+	    <version>1.8.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.axis2</groupId>
+            <artifactId>axis2-adb</artifactId>
+	    <version>1.8.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.axis2</groupId>
+            <artifactId>axis2-java2wsdl</artifactId>
+	    <version>1.8.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.axis2</groupId>
+            <artifactId>axis2-metadata</artifactId>
+	    <version>1.8.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.axis2</groupId>
+            <artifactId>axis2-spring</artifactId>
+	    <version>1.8.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.axis2</groupId>
+            <artifactId>axis2-jaxws</artifactId>
+	    <version>1.8.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.neethi</groupId>
+            <artifactId>neethi</artifactId>
+	    <version>3.1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>wsdl4j</groupId>
+            <artifactId>wsdl4j</artifactId>
+	    <version>1.6.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.woodstox</groupId>
+            <artifactId>woodstox-core-asl</artifactId>
+            <version>4.4.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.ws.xmlschema</groupId>
+            <artifactId>xmlschema-core</artifactId>
+            <version>2.2.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.woodstox</groupId>
+            <artifactId>stax2-api</artifactId>
+            <version>4.2.1</version>
+        </dependency>
+        <dependency>
+            <groupId>jaxen</groupId>
+            <artifactId>jaxen</artifactId>
+            <version>1.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.woden</groupId>
+            <artifactId>woden-core</artifactId>
+            <version>1.0M10</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.ws.commons.axiom</groupId>
+            <artifactId>axiom-api</artifactId>
+            <version>1.3.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.ws.commons.axiom</groupId>
+            <artifactId>axiom-dom</artifactId>
+            <version>1.3.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.ws.commons.axiom</groupId>
+            <artifactId>axiom-impl</artifactId>
+            <version>1.3.0</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>jsr311-api</artifactId>
+            <version>1.1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.owasp.esapi</groupId>
+            <artifactId>esapi</artifactId>
+            <version>2.2.3.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.13</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore</artifactId>
+            <version>4.4.13</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <version>3.2.0</version>
+                <executions>
+                    <execution>
+                        <id>unpack</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>userguide.springboot</groupId>
+                                    <artifactId>axis2-json-api</artifactId>
+                                    <version>0.0.1-SNAPSHOT</version>
+                                    <type>war</type>
+                                    <overWrite>false</overWrite>
+                                    <outputDirectory>${project.build.directory}/deploy/axis2-json-api.war</outputDirectory>
+                                    <includes>**/*.class,**/*.xml</includes>
+                                    <excludes>**/*test.class</excludes>
+                                </artifactItem>
+                            </artifactItems>
+                            <includes>**/*.java</includes>
+                            <excludes>**/*.properties</excludes>
+                            <overWriteReleases>true</overWriteReleases>
+                            <overWriteSnapshots>true</overWriteSnapshots>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>install</id>
+                        <phase>install</phase>
+                        <configuration>
+                            <tasks>
+                                <!--  used for local deploys, ignored otherwise -->
+                                <touch file="target/deploy/axis2-json-api.war.dodeploy">
+                                </touch>
+                                <jar jarfile="${project.build.directory}/deploy/axis2-json-api.war/WEB-INF/services/Login.aar">
+                                    <metainf file="resources-axis2/login_resources/services.xml"/>
+                                </jar>
+                                <jar jarfile="${project.build.directory}/deploy/axis2-json-api.war/WEB-INF/services/testws.aar">
+                                    <metainf file="resources-axis2/test_service_resources/services.xml"/>
+                                </jar>
+                                <copy todir="${project.build.directory}/deploy/axis2-json-api.war/WEB-INF/conf">
+                                    <fileset dir="resources-axis2/conf">
+                                        <include name="axis2.xml"/>
+                                    </fileset>
+                                </copy>
+                                <unzip src="${project.build.directory}/axis2-json-api-0.0.1-SNAPSHOT.war" dest="${project.build.directory}/exploded"/>
+                                <jar jarfile="${project.build.directory}/exploded/WEB-INF/services/Login.aar">
+                                    <metainf file="resources-axis2/login_resources/services.xml"/>
+                                </jar>
+                                <jar jarfile="${project.build.directory}/exploded/WEB-INF/services/testws.aar">
+                                    <metainf file="resources-axis2/test_service_resources/services.xml"/>
+                                </jar>
+                                <copy todir="${project.build.directory}/exploded/WEB-INF/conf">
+                                    <fileset dir="resources-axis2/conf">
+                                        <include name="axis2.xml"/>
+                                    </fileset>
+                                </copy>
+                            </tasks>
+                        </configuration>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-war-plugin</artifactId>
+                <version>3.3.1</version>
+                <configuration>
+                    <webResources>
+                        <resource>
+                            <directory>src/main/resources</directory>
+                            <includes>
+                                <include>**/*.xml</include>
+                                <include>**/application.properties</include>
+                            </includes>
+                            <targetPath>WEB-INF/classes</targetPath>
+                            <filtering>true</filtering>
+                        </resource>
+                    </webResources>
+                    <webappDirectory>${project.build.directory}/deploy/axis2-json-api.war</webappDirectory>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>enforce-java</id>
+                        <goals>
+                            <goal>exploded</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+
+    </build>
+
+</project>
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/conf/axis2.xml b/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/conf/axis2.xml
new file mode 100644
index 0000000..dd06722
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/conf/axis2.xml
@@ -0,0 +1,539 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements. See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership. The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License. You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied. See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+
+<axisconfig name="AxisJava2.0">
+    <!-- ================================================= -->
+    <!-- Parameters -->
+    <!-- ================================================= -->
+    <parameter name="hotdeployment">true</parameter>
+    <parameter name="hotupdate">false</parameter>
+    <parameter name="enableMTOM">false</parameter>
+    <parameter name="enableSwA">false</parameter>
+
+    <!--Uncomment if you want to enable file caching for attachments -->
+    <!--parameter name="cacheAttachments">true</parameter>
+    <parameter name="attachmentDIR"></parameter>
+    <parameter name="sizeThreshold">4000</parameter-->
+
+    <parameter name="EnableChildFirstClassLoading">false</parameter>
+
+    <!--
+    The exposeServiceMetadata parameter decides whether the metadata (WSDL, schema, policy) of
+    the services deployed on Axis2 should be visible when ?wsdl, ?wsdl2, ?xsd, ?policy requests
+    are received.
+    This parameter can be defined in the axi2.xml file, in which case this will be applicable
+    globally, or in the services.xml files, in which case, it will be applicable to the
+    Service groups and/or services, depending on the level at which the parameter is declared.
+    This value of this parameter defaults to true.
+    -->
+    <parameter name="exposeServiceMetadata">true</parameter>
+
+
+    <!--Uncomment if you want to plugin your own attachments lifecycle implementation -->
+    <!--<attachmentsLifecycleManager class="org.apache.axiom.attachments.lifecycle.impl.LifecycleManagerImpl"/>-->
+
+
+    <!--Uncomment if you want to enable the reduction of the in-memory cache of WSDL definitions -->
+    <!--In some server environments, the available memory heap is limited and can fill up under load -->
+    <!--Since in-memory copies of WSDL definitions can be large, some steps can be taken-->
+    <!--to reduce the memory needed for the cached WSDL definitions. -->
+    <!--parameter name="reduceWSDLMemoryCache">true</parameter-->
+
+    <!--This will give out the timout of the configuration contexts, in milliseconds-->
+    <parameter name="ConfigContextTimeoutInterval">30000</parameter>
+
+    <!--During a fault, stack trace can be sent with the fault message. The following flag will control -->
+    <!--that behavior.-->
+    <parameter name="sendStacktraceDetailsWithFaults">false</parameter>
+
+    <!--If there aren't any information available to find out the fault reason, we set the message of the exception-->
+    <!--as the faultreason/Reason. But when a fault is thrown from a service or some where, it will be -->
+    <!--wrapped by different levels. Due to this the initial exception message can be lost. If this flag-->
+    <!--is set, then Axis2 tries to get the first exception and set its message as the faultreason/Reason.-->
+    <parameter name="DrillDownToRootCauseForFaultReason">false</parameter>
+
+    <parameter name="userName">admin</parameter>
+    <parameter name="password">axis2</parameter>
+
+    <!--To override repository/services you need to uncomment following parameter and value SHOULD be absolute file path.-->
+    <!--ServicesDirectory only works on the following cases-->
+    <!---File based configurator and in that case the value should be a file URL (http:// not allowed)-->
+    <!---When creating URL Based configurator with URL file:// -->
+    <!--- War based configurator with expanded case , -->
+
+    <!--All the other scenarios it will be ignored.-->
+    <!--<parameter name="ServicesDirectory">service</parameter>-->
+    <!--To override repository/modules you need to uncomment following parameter and value SHOULD be absolute file path-->
+    <!--<parameter name="ModulesDirectory">modules</parameter>-->
+
+
+    <!--Following params will set the proper context paths for invocations. All the endpoints will have a commons context-->
+    <!--root which can configured using the following contextRoot parameter-->
+    <!--<parameter name="contextRoot">axis2</parameter>-->
+
+    <!--Our HTTP endpoints can handle both REST and SOAP. Following parameters can be used to distinguiush those endpoints-->
+    <!--In case of a servlet, if you change this you have to manually change the settings of your servlet container to map this -->
+    <!--context path to proper Axis2 servlets-->
+    <!--<parameter name="servicePath">services</parameter>-->
+    <!--<parameter name="restPath">rest</parameter>-->
+
+    <!-- Following parameter will completely disable REST handling in Axis2-->
+    <parameter name="disableREST" locked="false">false</parameter>
+
+    <!-- Following parameter will suppress generation of SOAP 1.2 bindings in auto-generated WSDL files -->
+    <parameter name="disableSOAP12" locked="true">false</parameter>
+
+    <!-- ================================================= -->
+    <!-- Deployers -->
+    <!-- ================================================= -->
+
+    <!--Service deployer , this will alow users to deploy AAR or exploded AAR as axis2 services-->
+    <deployer extension=".aar" directory="services" class="org.apache.axis2.deployment.ServiceDeployer">
+        <serviceBuilderExtension name ="jwsbuilderExt" class="org.apache.axis2.jaxws.framework.JAXWSServiceBuilderExtension"/>
+        <serviceBuilderExtension name ="wsdlbuilderExt" class="org.apache.axis2.deployment.WSDLServiceBuilderExtension"/>
+    </deployer>
+    
+    <!--POJO deployer , this will alow users to drop .class file and make that into a service-->
+    <deployer extension=".class" directory="pojo" class="org.apache.axis2.deployment.POJODeployer"/>
+    <deployer extension=".jar" directory="servicejars"
+              class="org.apache.axis2.jaxws.framework.JAXWSDeployer"/>
+    <deployer extension=".jar" directory="transports"
+              class="org.apache.axis2.deployment.TransportDeployer"/>
+
+    <!--CORBA deployer , this will alow users to invoke remote CORBA services through Axis2-->
+    <!--<deployer extension=".xml" directory="corba" class="org.apache.axis2.corba.deployer.CorbaDeployer"/>-->
+
+    <!--<deployer extension=".jsa" directory="rmiservices" class="org.apache.axis2.rmi.deploy.RMIServiceDeployer"/>-->
+
+
+    <!-- Following parameter will set the host name for the epr-->
+    <!--<parameter name="hostname" locked="true">myhost.com</parameter>-->
+
+    <!-- If you have a front end host which exposes this webservice using a different public URL  -->
+    <!-- use this parameter to override autodetected url -->
+    <!--<parameter name="httpFrontendHostUrl">https://someotherhost/context</parameter>-->
+
+    <!--By default, JAXWS services are created by reading annotations. WSDL and schema are generated-->
+    <!--using a separate WSDL generator only when ?wsdl is called. Therefore, even if you engage-->
+    <!--policies etc.. to AxisService, it doesn't appear in the WSDL. By setting the following property-->
+    <!--to true, you can create the AxisService using the generated WSDL and remove the need for a-->
+    <!--WSDL generator. When ?wsdl is called, WSDL is generated in the normal way.-->
+    <parameter name="useGeneratedWSDLinJAXWS">false</parameter>
+
+    <!--    The way of adding listener to the system-->
+    <!--    <listener class="org.apache.axis2.ObserverIMPL">-->
+    <!--        <parameter name="RSS_URL">http://127.0.0.1/rss</parameter>-->
+    <!--    </listener>-->
+
+    <threadContextMigrators>
+        <threadContextMigrator listId="JAXWS-ThreadContextMigrator-List"
+                               class="org.apache.axis2.jaxws.addressing.migrator.EndpointContextMapMigrator"/>
+    </threadContextMigrators>
+
+    <!-- ================================================= -->
+    <!-- Message Receivers -->
+    <!-- ================================================= -->
+    <!--This is the default MessageReceiver for the system , if you want to have MessageReceivers for -->
+    <!--all the other MEP implement it and add the correct entry to here , so that you can refer from-->
+    <!--any operation -->
+    <!--Note : You can override this for a particular service by adding the same element with your requirement-->
+    <messageReceivers>        
+        <messageReceiver mep="http://www.w3.org/ns/wsdl/in-out"
+               class="org.apache.axis2.json.moshi.rpc.JsonRpcMessageReceiver"  />
+        <messageReceiver mep="http://www.w3.org/ns/wsdl/in-only"
+               class="org.apache.axis2.json.moshi.rpc.JsonInOnlyRPCMessageReceiver"/>
+    </messageReceivers>
+
+    <!-- ================================================= -->
+    <!-- Message Formatter -->
+    <!-- ================================================= -->
+    <!--Following content type to message formatter mapping can be used to implement support for different message -->
+    <!--format  serialization in Axis2. These message formats are expected to be resolved based on the content type. -->
+    <messageFormatters>
+        <messageFormatter contentType="application/x-www-form-urlencoded"
+                          class="org.apache.axis2.transport.http.XFormURLEncodedFormatter"/>
+        <messageFormatter contentType="multipart/form-data"
+                          class="org.apache.axis2.transport.http.MultipartFormDataFormatter"/>
+        <messageFormatter contentType="application/xml"
+                          class="org.apache.axis2.transport.http.ApplicationXMLFormatter"/>
+        <messageFormatter contentType="text/xml"
+                          class="org.apache.axis2.transport.http.SOAPMessageFormatter"/>
+        <messageFormatter contentType="application/soap+xml"
+                          class="org.apache.axis2.transport.http.SOAPMessageFormatter"/>
+        <messageFormatter contentType="application/json"
+                          class="org.apache.axis2.json.moshi.JsonFormatter"/>
+    </messageFormatters>
+
+    <!-- ================================================= -->
+    <!-- Message Builders -->
+    <!-- ================================================= -->
+    <!--Following content type to builder mapping can be used to implement support for different message -->
+    <!--formats in Axis2. These message formats are expected to be resolved based on the content type. -->
+    <messageBuilders>
+        <messageBuilder contentType="application/xml"
+                        class="org.apache.axis2.builder.ApplicationXMLBuilder"/>
+        <messageBuilder contentType="application/x-www-form-urlencoded"
+                        class="org.apache.axis2.builder.XFormURLEncodedBuilder"/>
+        <messageBuilder contentType="multipart/form-data"
+                        class="org.apache.axis2.builder.MultipartFormDataBuilder"/>
+        <messageBuilder contentType="application/json"
+                        class="org.apache.axis2.json.moshi.JsonBuilder"/>
+    </messageBuilders>
+
+    <!-- ================================================= -->
+    <!-- Transport Ins -->
+    <!-- ================================================= -->
+    <transportReceiver name="http"
+                       class="org.apache.axis2.transport.http.SimpleHTTPServer">
+        <parameter name="port">8080</parameter>
+        <!-- Here is the complete list of supported parameters (see example settings further below):
+            port: the port to listen on (default 6060)
+            hostname:  if non-null, url prefix used in reply-to endpoint references                                 (default null)
+            originServer:  value of http Server header in outgoing messages                                         (default "Simple-Server/1.1")
+            requestTimeout:  value in millis of time that requests can wait for data                                (default 20000)
+            requestTcpNoDelay:  true to maximize performance and minimize latency                                   (default true)
+                                false to minimize bandwidth consumption by combining segments
+            requestCoreThreadPoolSize:  number of threads available for request processing (unless queue fills up)  (default 25)
+            requestMaxThreadPoolSize:  number of threads available for request processing if queue fills up         (default 150)
+                                       note that default queue never fills up:  see HttpFactory
+            threadKeepAliveTime:  time to keep threads in excess of core size alive while inactive                  (default 180)
+                                  note that no such threads can exist with default unbounded request queue
+            threadKeepAliveTimeUnit:  TimeUnit of value in threadKeepAliveTime (default SECONDS)                    (default SECONDS)
+        -->
+        <!-- <parameter name="hostname">http://www.myApp.com/ws</parameter> -->
+        <!-- <parameter name="originServer">My-Server/1.1</parameter>           -->
+        <!-- <parameter name="requestTimeout">10000</parameter>                   -->
+        <!-- <parameter name="requestTcpNoDelay">false</parameter>                   -->
+        <!-- <parameter name="requestCoreThreadPoolSize">50</parameter>                      -->
+        <!-- <parameter name="requestMaxThreadPoolSize">100</parameter>                     -->
+        <!-- <parameter name="threadKeepAliveTime">240000</parameter>                  -->
+        <!-- <parameter name="threadKeepAliveTimeUnit">MILLISECONDS</parameter>            -->
+    </transportReceiver>
+
+    <!-- This is where you'd put custom transports.  See the transports project -->
+    <!-- for more.  http://ws.apache.org/commons/transport                      -->
+
+    <!-- ================================================= -->
+    <!-- Transport Outs -->
+    <!-- ================================================= -->
+
+    <transportSender name="local"
+                     class="org.apache.axis2.transport.local.LocalTransportSender"/>
+    <transportSender name="http"
+                     class="org.apache.axis2.transport.http.impl.httpclient4.HTTPClient4TransportSender">
+        <parameter name="PROTOCOL">HTTP/1.1</parameter>
+        <parameter name="Transfer-Encoding">chunked</parameter>
+
+        <!-- If following is set to 'true', optional action part of the Content-Type will not be added to the SOAP 1.2 messages -->
+        <!--  <parameter name="OmitSOAP12Action">true</parameter>  -->
+    </transportSender>
+
+    <transportSender name="https"
+                     class="org.apache.axis2.transport.http.impl.httpclient4.HTTPClient4TransportSender">
+        <parameter name="PROTOCOL">HTTP/1.1</parameter>
+        <parameter name="Transfer-Encoding">chunked</parameter>
+    </transportSender>
+
+    <!-- Please enable this if you need the java transport -->
+    <!-- <transportSender name="java"
+                     class="org.apache.axis2.transport.java.JavaTransportSender"/> -->
+
+    <!-- ================================================= -->
+    <!-- Global Modules  -->
+    <!-- ================================================= -->
+    <!-- Comment this to disable Addressing -->
+    <!-- commented out for the Axis2 spring boot demo that uses JSON -->
+    <!-- <module ref="addressing"/> -->
+
+    <!--Configuring module , providing parameters for modules whether they refer or not-->
+    <!--<moduleConfig name="addressing">-->
+    <!--<parameter name="addressingPara">N/A</parameter>-->
+    <!--</moduleConfig>-->
+
+    <!-- ================================================= -->
+    <!-- Clustering  -->
+    <!-- ================================================= -->
+    <!--
+     To enable clustering for this node, set the value of "enable" attribute of the "clustering"
+     element to "true". The initialization of a node in the cluster is handled by the class
+     corresponding to the "class" attribute of the "clustering" element. It is also responsible for
+     getting this node to join the cluster.
+     -->
+    <clustering class="org.apache.axis2.clustering.tribes.TribesClusteringAgent" enable="false">
+
+        <!--
+           This parameter indicates whether the cluster has to be automatically initalized
+           when the AxisConfiguration is built. If set to "true" the initialization will not be
+           done at that stage, and some other party will have to explictly initialize the cluster.
+        -->
+        <parameter name="AvoidInitiation">true</parameter>
+
+        <!--
+           The membership scheme used in this setup. The only values supported at the moment are
+           "multicast" and "wka"
+
+           1. multicast - membership is automatically discovered using multicasting
+           2. wka - Well-Known Address based multicasting. Membership is discovered with the help
+                    of one or more nodes running at a Well-Known Address. New members joining a
+                    cluster will first connect to a well-known node, register with the well-known node
+                    and get the membership list from it. When new members join, one of the well-known
+                    nodes will notify the others in the group. When a member leaves the cluster or
+                    is deemed to have left the cluster, it will be detected by the Group Membership
+                    Service (GMS) using a TCP ping mechanism.
+        -->
+        <parameter name="membershipScheme">multicast</parameter>
+
+        <!--
+         The clustering domain/group. Nodes in the same group will belong to the same multicast
+         domain. There will not be interference between nodes in different groups.
+        -->
+        <parameter name="domain">wso2.carbon.domain</parameter>
+
+        <!--
+           When a Web service request is received, and processed, before the response is sent to the
+           client, should we update the states of all members in the cluster? If the value of
+           this parameter is set to "true", the response to the client will be sent only after
+           all the members have been updated. Obviously, this can be time consuming. In some cases,
+           such this overhead may not be acceptable, in which case the value of this parameter
+           should be set to "false"
+        -->
+        <parameter name="synchronizeAll">true</parameter>
+
+        <!--
+          The maximum number of times we need to retry to send a message to a particular node
+          before giving up and considering that node to be faulty
+        -->
+        <parameter name="maxRetries">10</parameter>
+
+        <!-- The multicast address to be used -->
+        <parameter name="mcastAddress">228.0.0.4</parameter>
+
+        <!-- The multicast port to be used -->
+        <parameter name="mcastPort">45564</parameter>
+
+        <!-- The frequency of sending membership multicast messages (in ms) -->
+        <parameter name="mcastFrequency">500</parameter>
+
+        <!-- The time interval within which if a member does not respond, the member will be
+         deemed to have left the group (in ms)
+         -->
+        <parameter name="memberDropTime">3000</parameter>
+
+        <!--
+           The IP address of the network interface to which the multicasting has to be bound to.
+           Multicasting would be done using this interface.
+        -->
+        <parameter name="mcastBindAddress">127.0.0.1</parameter>
+
+        <!-- The host name or IP address of this member -->
+        <parameter name="localMemberHost">127.0.0.1</parameter>
+
+        <!--
+        The TCP port used by this member. This is the port through which other nodes will
+        contact this member
+         -->
+        <parameter name="localMemberPort">4000</parameter>
+
+        <!--
+        Preserve message ordering. This will be done according to sender order.
+        -->
+        <parameter name="preserveMessageOrder">true</parameter>
+
+        <!--
+        Maintain atmost-once message processing semantics
+        -->
+        <parameter name="atmostOnceMessageSemantics">true</parameter>
+
+        <!--
+        Properties specific to this member
+        -->
+        <parameter name="properties">
+            <property name="backendServerURL" value="https://${hostName}:${httpsPort}/services/"/>
+            <property name="mgtConsoleURL" value="https://${hostName}:${httpsPort}/"/>
+        </parameter>
+
+        <!--
+           The list of static or well-known members. These entries will only be valid if the
+           "membershipScheme" above is set to "wka"
+        -->
+        <members>
+            <member>
+                <hostName>127.0.0.1</hostName>
+                <port>4000</port>
+            </member>
+            <member>
+                <hostName>127.0.0.1</hostName>
+                <port>4001</port>
+            </member>
+        </members>
+
+        <!--
+        Enable the groupManagement entry if you need to run this node as a cluster manager.
+        Multiple application domains with different GroupManagementAgent implementations
+        can be defined in this section.
+        -->
+        <groupManagement enable="false">
+            <applicationDomain name="apache.axis2.application.domain"
+                               description="Axis2 group"
+                               agent="org.apache.axis2.clustering.management.DefaultGroupManagementAgent"/>
+        </groupManagement>
+
+        <!--
+           This interface is responsible for handling management of a specific node in the cluster
+           The "enable" attribute indicates whether Node management has been enabled
+        -->
+        <nodeManager class="org.apache.axis2.clustering.management.DefaultNodeManager"
+                         enable="true"/>
+
+        <!--
+           This interface is responsible for handling state replication. The property changes in
+           the Axis2 context hierarchy in this node, are propagated to all other nodes in the cluster.
+
+           The "excludes" patterns can be used to specify the prefixes (e.g. local_*) or
+           suffixes (e.g. *_local) of the properties to be excluded from replication. The pattern
+           "*" indicates that all properties in a particular context should not be replicated.
+
+            The "enable" attribute indicates whether context replication has been enabled
+        -->
+        <stateManager class="org.apache.axis2.clustering.state.DefaultStateManager"
+                      enable="true">
+            <replication>
+                <defaults>
+                    <exclude name="local_*"/>
+                    <exclude name="LOCAL_*"/>
+                </defaults>
+                <context class="org.apache.axis2.context.ConfigurationContext">
+                    <exclude name="local_*"/>
+                </context>
+                <context class="org.apache.axis2.context.ServiceGroupContext">
+                    <exclude name="local_*"/>
+                </context>
+                <context class="org.apache.axis2.context.ServiceContext">
+                    <exclude name="local_*"/>
+                </context>
+            </replication>
+        </stateManager>
+    </clustering>
+
+    <!-- ================================================= -->
+    <!-- Phases  -->
+    <!-- ================================================= -->
+    <phaseOrder type="InFlow">
+        <!--  System predefined phases       -->
+        <phase name="Transport">
+            <handler name="RequestURIBasedDispatcher"
+                     class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher">
+                <order phase="Transport"/>
+            </handler>
+            <handler name="SOAPActionBasedDispatcher"
+                     class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher">
+                <order phase="Transport"/>
+            </handler>
+            <handler name="JSONMessageHandler"
+                     class="org.apache.axis2.json.moshi.JSONMessageHandler">
+                <order phase="Transport"/>
+            </handler>
+        </phase>
+        <phase name="Addressing">
+            <handler name="AddressingBasedDispatcher"
+                     class="org.apache.axis2.dispatchers.AddressingBasedDispatcher">
+                <order phase="Addressing"/>
+            </handler>
+        </phase>
+        <phase name="Security"/>
+        <phase name="PreDispatch"/>
+        <phase name="Dispatch" class="org.apache.axis2.engine.DispatchPhase">
+            <handler name="RequestURIBasedDispatcher"
+                     class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher"/>
+            <handler name="SOAPActionBasedDispatcher"
+                     class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher"/>
+            <handler name="RequestURIOperationDispatcher"
+                     class="org.apache.axis2.dispatchers.RequestURIOperationDispatcher"/>
+            <handler name="SOAPMessageBodyBasedDispatcher"
+                     class="org.apache.axis2.dispatchers.SOAPMessageBodyBasedDispatcher"/>
+            <handler name="HTTPLocationBasedDispatcher"
+                     class="org.apache.axis2.dispatchers.HTTPLocationBasedDispatcher"/>
+            <handler name="GenericProviderDispatcher"
+                     class="org.apache.axis2.jaxws.dispatchers.GenericProviderDispatcher"/>
+            <handler name="MustUnderstandValidationDispatcher"
+                     class="org.apache.axis2.jaxws.dispatchers.MustUnderstandValidationDispatcher"/>
+        </phase>
+        <phase name="RMPhase"/>
+        <!--  System predefined phases       -->
+        <!--   After Postdispatch phase module author or service author can add any phase he want      -->
+        <phase name="OperationInPhase">
+            <handler name="MustUnderstandChecker"
+                     class="org.apache.axis2.jaxws.dispatchers.MustUnderstandChecker">
+                <order phase="OperationInPhase"/>
+            </handler>
+        </phase>
+        <phase name="soapmonitorPhase"/>
+    </phaseOrder>
+    <phaseOrder type="OutFlow">
+        <!--      user can add his own phases to this area  -->
+        <phase name="soapmonitorPhase"/>
+        <phase name="OperationOutPhase"/>
+        <!--system predefined phase-->
+        <!--these phase will run irrespective of the service-->
+        <phase name="RMPhase"/>
+        <phase name="PolicyDetermination"/>
+        <phase name="MessageOut"/>
+        <phase name="Security"/>
+    </phaseOrder>
+    <phaseOrder type="InFaultFlow">
+        <phase name="Addressing">
+            <handler name="AddressingBasedDispatcher"
+                     class="org.apache.axis2.dispatchers.AddressingBasedDispatcher">
+                <order phase="Addressing"/>
+            </handler>
+        </phase>
+        <phase name="Security"/>
+        <phase name="PreDispatch"/>
+        <phase name="Dispatch" class="org.apache.axis2.engine.DispatchPhase">
+            <handler name="RequestURIBasedDispatcher"
+                     class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher"/>
+            <handler name="SOAPActionBasedDispatcher"
+                     class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher"/>
+            <handler name="RequestURIOperationDispatcher"
+                     class="org.apache.axis2.dispatchers.RequestURIOperationDispatcher"/>
+            <handler name="SOAPMessageBodyBasedDispatcher"
+                     class="org.apache.axis2.dispatchers.SOAPMessageBodyBasedDispatcher"/>
+            <handler name="HTTPLocationBasedDispatcher"
+                     class="org.apache.axis2.dispatchers.HTTPLocationBasedDispatcher"/>
+            <handler name="GenericProviderDispatcher"
+                     class="org.apache.axis2.jaxws.dispatchers.GenericProviderDispatcher"/>
+            <handler name="MustUnderstandValidationDispatcher"
+                     class="org.apache.axis2.jaxws.dispatchers.MustUnderstandValidationDispatcher"/>
+        </phase>
+        <phase name="RMPhase"/>
+        <!--      user can add his own phases to this area  -->
+        <phase name="OperationInFaultPhase"/>
+        <phase name="soapmonitorPhase"/>
+    </phaseOrder>
+    <phaseOrder type="OutFaultFlow">
+        <!--      user can add his own phases to this area  -->
+        <phase name="soapmonitorPhase"/>
+        <phase name="OperationOutFaultPhase"/>
+        <phase name="RMPhase"/>
+        <phase name="PolicyDetermination"/>
+        <phase name="MessageOut"/>
+        <phase name="Security"/>
+    </phaseOrder>
+</axisconfig>
+
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/login_resources/services.xml b/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/login_resources/services.xml
new file mode 100755
index 0000000..64812c7
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/login_resources/services.xml
@@ -0,0 +1,33 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements. See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership. The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License. You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied. See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<service name="loginService">
+    <description>
+        Login Resources
+    </description>
+    <parameter name="ServiceObjectSupplier">org.apache.axis2.extensions.spring.receivers.SpringServletContextObjectSupplier</parameter>
+    <parameter name="SpringBeanName">loginService</parameter>
+    <operation name="doLogin">
+        <messageReceivers>
+            <messageReceiver mep="http://www.w3.org/ns/wsdl/in-out"
+                class="org.apache.axis2.json.moshi.rpc.JsonRpcMessageReceiver"  />
+            <messageReceiver mep="http://www.w3.org/ns/wsdl/in-only"
+                class="org.apache.axis2.json.moshi.rpc.JsonInOnlyRPCMessageReceiver"/>
+    </messageReceivers>
+    </operation>
+</service>
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/test_service_resources/services.xml b/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/test_service_resources/services.xml
new file mode 100755
index 0000000..6a202ff
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/test_service_resources/services.xml
@@ -0,0 +1,33 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements. See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership. The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License. You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied. See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<service name="testws">
+    <description>
+        testws Resources
+    </description>
+    <parameter name="ServiceObjectSupplier">org.apache.axis2.extensions.spring.receivers.SpringServletContextObjectSupplier</parameter>
+    <parameter name="SpringBeanName">testwsService</parameter>
+    <operation name="doTestws">
+        <messageReceivers>
+            <messageReceiver mep="http://www.w3.org/ns/wsdl/in-out"
+                class="org.apache.axis2.json.moshi.rpc.JsonRpcMessageReceiver"  />
+            <messageReceiver mep="http://www.w3.org/ns/wsdl/in-only"
+                class="org.apache.axis2.json.moshi.rpc.JsonInOnlyRPCMessageReceiver"/>
+    </messageReceivers>
+    </operation>
+</service>
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/Axis2Application.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/Axis2Application.java
new file mode 100644
index 0000000..7aefd00
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/Axis2Application.java
@@ -0,0 +1,468 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.Filter;
+
+import java.io.PrintWriter;
+import java.io.IOException;
+import java.util.*;
+
+import org.springframework.context.annotation.Bean;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.access.AccessDecisionVoter;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.access.vote.AffirmativeBased;
+import org.springframework.security.access.vote.RoleVoter;
+import org.springframework.security.access.SecurityConfig;
+import org.springframework.security.authentication.InsufficientAuthenticationException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.access.AccessDeniedHandler;
+
+import org.springframework.security.web.access.ExceptionTranslationFilter;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+import org.springframework.security.web.context.HttpRequestResponseHolder;
+import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
+import org.springframework.security.web.firewall.HttpFirewall;
+import org.springframework.security.web.firewall.StrictHttpFirewall;
+import org.springframework.security.web.header.HeaderWriter;
+import org.springframework.security.web.header.HeaderWriterFilter;
+import org.springframework.security.web.session.SessionManagementFilter;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.security.web.FilterChainProxy;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.DefaultSecurityFilterChain;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.HttpStatusEntryPoint;
+import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+import org.springframework.security.authentication.ProviderManager;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.filter.DelegatingFilterProxy;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.password.NoOpPasswordEncoder;
+
+import static org.springframework.http.HttpStatus.FORBIDDEN;
+
+import userguide.springboot.security.webservices.WSLoginFilter;
+import userguide.springboot.security.webservices.JWTAuthenticationFilter;
+import userguide.springboot.security.webservices.JWTAuthenticationProvider;
+import userguide.springboot.security.webservices.HTTPPostOnlyRejectionFilter;
+import userguide.springboot.security.webservices.RequestAndResponseValidatorFilter;
+import userguide.springboot.security.webservices.RestAuthenticationEntryPoint;
+
+@SpringBootApplication
+@EnableAutoConfiguration
+@Configuration
+public class Axis2Application extends SpringBootServletInitializer {
+
+    private static final Logger logger = LogManager.getLogger(Axis2Application.class);
+    public static volatile boolean isRunning = false;
+
+    @Configuration
+    @EnableWebSecurity
+    @Order(1)
+    @PropertySource("classpath:application.properties")
+    public static class SecurityConfigurationTokenWebServices extends WebSecurityConfigurerAdapter {
+        private static final Logger logger = LogManager.getLogger(SecurityConfigurationTokenWebServices.class);
+
+        public SecurityConfigurationTokenWebServices() {
+            super(true);
+            String logPrefix = "SecurityConfigurationTokenWebServices , ";
+            logger.debug(logPrefix + "inside constructor, defaults disabled via super(true) ...");
+        }
+
+        class AnonRequestMatcher implements RequestMatcher {
+            
+            @Override
+            public boolean matches(HttpServletRequest request) {
+                String logPrefix = "AnonRequestMatcher.matches , ";
+                boolean result = request.getRequestURI().contains(
+                        "/services/loginService");
+                logger.debug(logPrefix
+                        + "inside AnonRequestMatcher.matches, will return result: "
+                        + result + " , on request.getRequestURI() : "
+                        + request.getRequestURI() + " , request.getMethod() : "
+                        + request.getMethod());
+                return result;
+            }
+            
+        }
+
+        class AuthorizationFailHandler implements AccessDeniedHandler {
+
+            @Override
+            public void handle(final HttpServletRequest request, final HttpServletResponse response, final AccessDeniedException accessDeniedException)
+                    throws IOException, ServletException {
+                String logPrefix = "AuthorizationFailHandler.handle() , ";
+                response.setContentType("application/json");
+                try (PrintWriter writer = response.getWriter()) {
+                    logger.error(logPrefix + "found error: " + accessDeniedException.getMessage());
+                    writer.write("{\"msg\":\" Access Denied\"}");
+                }
+            }
+        }
+
+	// this is about where Spring SEC HTTPInterceptor would go however it was too flaky and inflexible for this use case
+        class SecureResouceMetadataSource implements FilterInvocationSecurityMetadataSource {
+
+            @Override
+            public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
+                String logPrefix = "SecureResouceMetadataSource.getAttributes , ";
+
+                final HttpServletRequest request = ((FilterInvocation) object).getRequest();
+                final String url = request.getRequestURI();
+                final String method = request.getMethod();
+                    
+                String[] roles = new String[] { String.format("%s|%s", url, method) };
+                logger.debug(logPrefix + "found roles: " + Arrays.toString(roles));
+                return SecurityConfig.createList(roles);
+            }
+
+            @Override
+            public Collection<ConfigAttribute> getAllConfigAttributes() {
+                String logPrefix = "SecureResouceMetadataSource.getAllConfigAttributes , ";
+                logger.debug(logPrefix + "returning ROLE_USER ...");
+                List<ConfigAttribute> attrs = SecurityConfig.createList("ROLE_USER");
+                return attrs;
+            }
+
+            /**
+             * true if the implementation can process the indicated class
+             */
+            @Override
+            public boolean supports(final Class<?> clazz) {
+                return true;
+            }
+
+        }
+        
+        class StatelessSecurityContextRepository extends HttpSessionSecurityContextRepository {
+
+            @Override
+            public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
+                String logPrefix = "StatelessSecurityContextRepository.loadContext , ";
+                logger.debug(logPrefix + "inside loadContext() ... invoking createEmptyContext()");
+                return SecurityContextHolder.createEmptyContext();
+            }
+
+            @Override
+            public void saveContext(SecurityContext context,
+                HttpServletRequest request, HttpServletResponse response) {
+                String logPrefix = "StatelessSecurityContextRepository.saveContext , ";
+                logger.debug(logPrefix + "inside saveContext() ... no action taken");
+            }
+
+            @Override
+            public boolean containsContext(final HttpServletRequest request) {
+                String logPrefix = "StatelessSecurityContextRepository.containsContext , ";
+                logger.debug(logPrefix + "inside containsContext() ... returning false");
+                return false;
+            }
+
+        }
+
+        class GenericAccessDecisionManager implements AccessDecisionManager {
+
+            @Override
+            public void decide(final Authentication authentication, final Object object, final Collection<ConfigAttribute> configAttributes)
+                    throws AccessDeniedException, InsufficientAuthenticationException {
+        
+                /* TODO role based auth can go here 
+                boolean allowAccess = false;
+        
+                for (final GrantedAuthority grantedAuthority : authentication.getAuthorities()) {
+        
+                    for (final ConfigAttribute attribute : configAttributes) {
+                        allowAccess = attribute.getAttribute().equals(grantedAuthority.getAuthority());
+                        if (allowAccess) {
+                            break;// this loop
+                        }
+                    }
+        
+                }
+        
+                if (!allowAccess) {
+                    logger.warn("Throwing access denied exception");
+                    throw new AccessDeniedException("Access is denied");
+                }
+                */
+            }
+
+            @Override
+            public boolean supports(final ConfigAttribute attribute) {
+                return true;
+            }
+        
+            @Override
+            public boolean supports(final Class<?> clazz) {
+                return true;
+            }
+        }
+
+        @Autowired
+        private JWTAuthenticationProvider jwtAuthenticationProvider;
+
+        @Autowired
+        private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
+
+        @Autowired
+        public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
+            auth.authenticationProvider(jwtAuthenticationProvider);
+        }
+        
+        @Override
+        protected void configure(final HttpSecurity http) throws Exception {
+            String logPrefix = "StatelessSecurityContextRepository.configure(final HttpSecurity http) , ";
+            logger.debug(logPrefix + "inside Spring Boot filter config ...");
+        }
+        
+        @Bean
+        WSLoginFilter wsLoginFilter() throws Exception {
+          final WSLoginFilter filter = new WSLoginFilter();
+          return filter;
+        }
+
+        @Bean
+        JWTAuthenticationFilter jwtAuthenticationFilter() throws Exception {
+          final JWTAuthenticationFilter filter = new JWTAuthenticationFilter();
+          return filter;
+        }
+      
+        @Bean
+        HTTPPostOnlyRejectionFilter httpPostOnlyRejectionFilter() throws Exception {
+          final HTTPPostOnlyRejectionFilter filter = new HTTPPostOnlyRejectionFilter();
+          return filter;
+        }
+
+        @Bean
+        public ProviderManager authenticationManager() {
+            return new ProviderManager(Arrays.asList(jwtAuthenticationProvider));
+        }
+
+        public ExceptionTranslationFilter exceptionTranslationFilter() {
+            final ExceptionTranslationFilter exceptionTranslationFilter = new ExceptionTranslationFilter(restAuthenticationEntryPoint);
+            exceptionTranslationFilter.setAccessDeniedHandler(new AuthorizationFailHandler());
+            return exceptionTranslationFilter;
+        }
+    
+        @Bean
+        public SecureResouceMetadataSource secureResouceMetadataSource() {
+            return new SecureResouceMetadataSource();// gives allowed roles
+        }
+
+        @Bean
+        AffirmativeBased accessDecisionManager() {
+            List<AccessDecisionVoter<? extends Object>> voters = new ArrayList<>();
+            voters.add(new RoleVoter());
+            AffirmativeBased decisionManager = new AffirmativeBased(voters);
+            decisionManager.setAllowIfAllAbstainDecisions(false);
+            return decisionManager;
+        }
+
+        @Bean
+        public GenericAccessDecisionManager genericAccessDecisionManager() {
+            return new GenericAccessDecisionManager();
+        }
+    
+        public FilterSecurityInterceptor filterSecurityInterceptor() throws Exception {
+            final FilterSecurityInterceptor filterSecurityInterceptor = new FilterSecurityInterceptor();
+            filterSecurityInterceptor.setAuthenticationManager(authenticationManager());
+            filterSecurityInterceptor.setAccessDecisionManager(genericAccessDecisionManager());
+            filterSecurityInterceptor.setSecurityMetadataSource(secureResouceMetadataSource());
+            return filterSecurityInterceptor;
+        }
+
+        @Bean
+        public StatelessSecurityContextRepository statelessSecurityContextRepository() {
+            return new StatelessSecurityContextRepository();
+        }
+
+        @Bean
+        public Filter sessionManagementFilter() {
+            StatelessSecurityContextRepository repo = statelessSecurityContextRepository();
+            repo.setAllowSessionCreation(false); 
+            SessionManagementFilter filter = new SessionManagementFilter(repo);
+            return filter;
+        }
+
+        @Bean
+        public HeaderWriterFilter headerWriterFilter() {
+            HeaderWriter headerWriter = new HeaderWriter() {
+                public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
+                    response.setHeader("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate");
+                    response.setHeader("Expires", "0");
+                    response.setHeader("Pragma", "no-cache");
+                    response.setHeader("X-Frame-Options", "SAMEORIGIN");
+                    response.setHeader("X-XSS-Protection", "1; mode=block");
+                    response.setHeader("x-content-type-options", "nosniff");
+                }
+            };
+            List<HeaderWriter> headerWriterFilterList = new ArrayList<HeaderWriter>();
+            headerWriterFilterList.add(headerWriter);
+            HeaderWriterFilter headerFilter = new HeaderWriterFilter(headerWriterFilterList);
+            return headerFilter;
+        }
+      
+        @Bean(name = "springSecurityFilterChain")
+        public FilterChainProxy springSecurityFilterChain() throws ServletException, Exception {
+            String logPrefix = "GenericAccessDecisionManager.springSecurityFilterChain , ";
+            logger.debug(logPrefix + "inside main filter config ...");
+
+            final List<SecurityFilterChain> listOfFilterChains = new ArrayList<SecurityFilterChain>();
+
+	    // these two chains are a binary choice. 
+	    // A login url will match, otherwise invoke jwtAuthenticationFilter
+            listOfFilterChains.add(new DefaultSecurityFilterChain(new AnonRequestMatcher(), headerWriterFilter(), httpPostOnlyRejectionFilter(), requestAndResponseValidatorFilter(), wsLoginFilter(), sessionManagementFilter()));
+
+            listOfFilterChains.add(new DefaultSecurityFilterChain(new NegatedRequestMatcher(new AnonRequestMatcher()), headerWriterFilter(), httpPostOnlyRejectionFilter(), requestAndResponseValidatorFilter(), jwtAuthenticationFilter(), sessionManagementFilter(), exceptionTranslationFilter(), filterSecurityInterceptor()));
+
+            final FilterChainProxy filterChainProxy = new FilterChainProxy(listOfFilterChains);
+
+            return filterChainProxy;
+        }
+
+        /**
+         * Disable Spring boot automatic filter registration since we are using FilterChainProxy.
+         */
+        @Bean
+        FilterRegistrationBean disableWSLoginFilterAutoRegistration(final WSLoginFilter wsLoginFilter) {
+            String logPrefix = "GenericAccessDecisionManager.disableWSLoginFilterAutoRegistration , ";
+            logger.debug(logPrefix + "executing registration.setEnabled(false) on wsLoginFilter ...");
+            final FilterRegistrationBean registration = new FilterRegistrationBean(wsLoginFilter);
+            registration.setEnabled(false);
+            return registration;
+        }
+
+        /**
+         * Disable Spring boot automatic filter registration since we are using FilterChainProxy.
+         */
+        @Bean
+        FilterRegistrationBean disableJWTAuthenticationFilterAutoRegistration(final JWTAuthenticationFilter filter) {
+            String logPrefix = "GenericAccessDecisionManager.disableJWTAuthenticationFilterAutoRegistration , ";
+            logger.debug(logPrefix + "executing registration.setEnabled(false) on JWTAuthenticationFilter ...");
+            final FilterRegistrationBean registration = new FilterRegistrationBean(filter);
+            registration.setEnabled(false);
+            return registration;
+        }
+      
+        /**
+         * Disable Spring boot automatic filter registration since we are using FilterChainProxy.
+         */
+        @Bean
+        FilterRegistrationBean disableHTTPPostOnlyRejectionFilterAutoRegistration(final HTTPPostOnlyRejectionFilter filter) {
+            String logPrefix = "GenericAccessDecisionManager.disableHTTPPostOnlyRejectionFilterAutoRegistration , ";
+            logger.debug(logPrefix + "executing registration.setEnabled(false) on HTTPPostOnlyRejectionFilter ...");
+            final FilterRegistrationBean registration = new FilterRegistrationBean(filter);
+            registration.setEnabled(false);
+            return registration;
+        }
+
+        /**
+         * Disable Spring boot automatic filter registration since we are using FilterChainProxy.
+         */
+        @Bean
+        FilterRegistrationBean disableRequestAndResponseValidatorFilterAutoRegistration(final RequestAndResponseValidatorFilter filter) {
+            String logPrefix = "GenericAccessDecisionManager.disableRequestAndResponseValidatorFilterAutoRegistration , ";
+            logger.debug(logPrefix + "executing registration.setEnabled(false) on RequestLoggingFilter ...");
+            final FilterRegistrationBean registration = new FilterRegistrationBean(filter);
+            registration.setEnabled(false);
+            return registration;
+        }
+        
+        @Bean
+        public RequestAndResponseValidatorFilter requestAndResponseValidatorFilter() {
+            RequestAndResponseValidatorFilter filter = new RequestAndResponseValidatorFilter();
+            return filter;
+        }
+        
+        @Bean()
+        FilterRegistrationBean FilterRegistrationBean() {
+            final FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
+            filterRegistrationBean.setFilter(new DelegatingFilterProxy("springSecurityFilterChain"));
+            filterRegistrationBean.setOrder(Ordered.LOWEST_PRECEDENCE);
+            filterRegistrationBean.setName("springSecurityFilterChain");
+            filterRegistrationBean.addUrlPatterns("/*");
+            return filterRegistrationBean;
+        }
+
+        @Bean
+        AuthenticationEntryPoint forbiddenEntryPoint() {
+           return new HttpStatusEntryPoint(FORBIDDEN);
+        }
+
+        // demo purposes only
+        @SuppressWarnings("deprecation")
+        @Bean
+        public static NoOpPasswordEncoder passwordEncoder() {
+            return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
+        }
+
+    }
+
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+        setRegisterErrorPageFilter(false);
+        return application.sources(Axis2Application.class);
+    }
+
+    public static void main(String[] args) throws Exception {
+        String logPrefix = "Axis2Application.main , ";
+        if (!isRunning) {
+            SpringApplication ctx = new SpringApplication(Axis2Application.class);
+            ApplicationContext applicationContext = ctx.run(args);
+            String[] activeProfiles = applicationContext.getEnvironment().getActiveProfiles();
+            for (String profile : activeProfiles) {
+                logger.debug(logPrefix + "Spring Boot profile: " + profile);
+            }
+        }
+        isRunning = true;
+    }
+
+
+
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/configuration/Axis2WebAppInitializer.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/configuration/Axis2WebAppInitializer.java
new file mode 100644
index 0000000..0d3acce
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/configuration/Axis2WebAppInitializer.java
@@ -0,0 +1,72 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.configuration;
+ 
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.axis2.transport.http.AxisServlet;
+import org.springframework.boot.web.servlet.ServletContextInitializer;
+import org.springframework.context.annotation.Configuration; 
+import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;   
+import org.springframework.core.annotation.Order;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
+
+import javax.servlet.ServletContext; 
+import javax.servlet.ServletRegistration; 
+
+import java.util.Set; 
+ 
+@Configuration
+@Order(4)
+public class Axis2WebAppInitializer implements ServletContextInitializer { 
+ 
+    private static final Logger logger = LogManager.getLogger(Axis2WebAppInitializer.class); 
+    private static final String SERVICES_MAPPING = "/services/*"; 
+ 
+    @Override 
+    public void onStartup(ServletContext container) { 
+        logger.warn("inside onStartup() ...");
+        // Create the 'root' Spring application context 
+        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); 
+ 
+        addAxis2Servlet(container, ctx); 
+        logger.warn("onStartup() completed ...");
+    }
+ 
+    private void addAxis2Servlet(ServletContext container, AnnotationConfigWebApplicationContext ctx) { 
+
+        ServletRegistration.Dynamic dispatcher = container.addServlet(
+          "AxisServlet", new AxisServlet());
+        dispatcher.setLoadOnStartup(1);
+        Set<String> mappingConflicts = dispatcher.addMapping(SERVICES_MAPPING);
+        if (!mappingConflicts.isEmpty()) { 
+            for (String s : mappingConflicts) { 
+                logger.error("Mapping conflict: " + s); 
+            } 
+            throw new IllegalStateException("'AxisServlet' could not be mapped to '" + SERVICES_MAPPING + "'"); 
+        }
+    }
+
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/hibernate/dao/SpringSecurityDAOImpl.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/hibernate/dao/SpringSecurityDAOImpl.java
new file mode 100755
index 0000000..37d9545
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/hibernate/dao/SpringSecurityDAOImpl.java
@@ -0,0 +1,115 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.hibernate.dao;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.dao.DataAccessException;
+
+import userguide.springboot.requestactivity.Axis2UserDetails;
+import userguide.springboot.security.webservices.WSSecUtils;
+import userguide.springboot.security.webservices.LoginDTO;
+
+@Service
+public class SpringSecurityDAOImpl implements UserDetailsService {
+
+    private static final Logger logger = LogManager.getLogger(SpringSecurityDAOImpl.class);
+    
+    @Autowired
+    private WSSecUtils wssecutils;
+
+    /** Everyone needs this role. **/
+    public static final String ROLE_USER = "ROLE_USER";
+
+    /**
+     * Spring Security invokes this method to get the credentials from the DB.
+     */
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
+
+        String logPrefix = "SpringSecurityDAOImpl.loadUserByUsername() , ";
+        Axis2UserDetails userDetails = null;
+        
+        logger.debug("user attempting Spring Security login: " + username);
+        if (username == null || username.equals("")) {
+            throw new BadCredentialsException("user login FAILED: username empty or null.");
+        }    
+        LoginDTO persistedUser = null;
+        try {
+            persistedUser = wssecutils.findUserByEmail(username);
+        } catch (Exception ex) {
+            logger.error(logPrefix + "cannot create LoginDTO from email: " + username + " , " + ex.getMessage(), ex);
+        }
+        if (persistedUser == null) {
+            throw new BadCredentialsException("Can't find username: " + username);
+        }    
+
+        Set<String> roles = new HashSet<String>();
+        // adding permissions - put Roles here
+        // Every user must have the ROLE_USER to navigate the application:
+        if (!roles.contains(ROLE_USER)) {
+            roles.add(ROLE_USER);
+        }
+        Iterator<String> it = roles.iterator();
+
+        Collection<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
+
+        int xx = 0;
+        while (it.hasNext()) {
+            String role = it.next();
+            GrantedAuthority authority = new SimpleGrantedAuthority(role);
+            authorities.add(authority);
+            if (logger.isDebugEnabled()) {
+                logger.debug("user: " + username + ", "
+                             + "authorities : " + (xx - 1) + ", value:"
+                             + authority.toString());
+            }
+        }
+
+        // Give these fields to Spring Security so it can compare with credentials passed in via the login page
+        userDetails = new Axis2UserDetails(persistedUser,
+                // username == email 
+                persistedUser.getEmail().toLowerCase(),
+                persistedUser.getPassword(),
+                persistedUser.getEnabled(),
+                persistedUser.getAccountNonExpired(),
+                persistedUser.getCredentialsNonExpired(),
+                persistedUser.getAccountNonLocked(),
+                authorities);
+            
+    
+        return userDetails;
+
+    }
+    
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/requestactivity/Axis2UserDetails.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/requestactivity/Axis2UserDetails.java
new file mode 100644
index 0000000..cc5db11
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/requestactivity/Axis2UserDetails.java
@@ -0,0 +1,64 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.requestactivity;
+
+import java.util.Collection;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+
+public class Axis2UserDetails extends User {
+
+    private static final long serialVersionUID = 2041888514077783198L;
+    /**  User entity which is Stored by Spring's SecurityContext per every login. */
+    private Object userDomain;
+    
+    /**
+     * @return Returns the userDomain.
+     */
+    public Object getUserDomain() {
+        return userDomain;
+    }
+    
+    /** 
+     * Override SPRING SECURITY Constructor to inform it about the  User entity.
+     * 
+     * @param userDomain Authenticated  User entity
+     * @param username from DB
+     * @param password from DB
+     * @param enabled Indicates whether the user is enabled or disabled
+     * @param accountNonExpired Indicates whether the user's account has expired
+     * @param credentialsNonExpired Indicates whether the user's credentials 
+     *   (password) has expired.
+     * @param accountNonLocked Indicates whether the user is locked or unlocked.
+     * @param authorities the authorities granted to the user
+     * @throws IllegalArgumentException Invalid argument was found 
+     */
+    public Axis2UserDetails(Object userDomain, 
+            String username, String password, boolean enabled, 
+            boolean accountNonExpired, boolean credentialsNonExpired, 
+            boolean accountNonLocked,
+            Collection<? extends GrantedAuthority> authorities)
+        throws IllegalArgumentException  {
+         
+        super(username, password, enabled, accountNonExpired, 
+                credentialsNonExpired, accountNonLocked, authorities);
+        this.userDomain = userDomain;
+    }
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/BadRequestMatcher.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/BadRequestMatcher.java
new file mode 100644
index 0000000..8adb2a1
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/BadRequestMatcher.java
@@ -0,0 +1,258 @@
+

+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements. See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership. The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License. You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied. See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package userguide.springboot.security.webservices;

+

+import org.apache.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.springframework.security.web.util.matcher.RequestMatcher;

+

+import java.util.Arrays;

+import java.util.Enumeration;

+import java.util.HashSet;

+import java.util.List;

+import java.util.Collection;

+import java.util.Collections;

+import java.util.Set;

+

+public class BadRequestMatcher implements RequestMatcher {

+

+    /** commons logging declaration. **/

+    private static Log logger = LogFactory.getLog(BadRequestMatcher.class);

+          

+    private Set<String> encodedUrlBlacklist = new HashSet<String>();

+

+    private Set<String> decodedUrlBlacklist = new HashSet<String>();

+    

+    private static final String ENCODED_PERCENT = "%25";

+

+    private static final String PERCENT = "%";

+

+    private List<String> FORBIDDEN_ENCODED_PERIOD = Collections.unmodifiableList(Arrays.asList("%2e", "%2E"));

+

+    private List<String> FORBIDDEN_SEMICOLON = Collections.unmodifiableList(Arrays.asList(";", "%3b", "%3B"));

+

+    private List<String> FORBIDDEN_FORWARDSLASH = Collections.unmodifiableList(Arrays.asList("%2f", "%2F"));

+

+    private List<String> FORBIDDEN_BACKSLASH = Collections.unmodifiableList(Arrays.asList("\\", "%5c", "%5C"));

+

+    private int requestDebuggingActivated;

+

+    public BadRequestMatcher(int requestDebuggingActivated) {

+        

+	this.requestDebuggingActivated = requestDebuggingActivated;

+        // this is a 'defense in depth' strategy as Cloudflare or another load balancer should reject this stuff

+        urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);

+        urlBlacklistsAddAll(FORBIDDEN_FORWARDSLASH);

+        urlBlacklistsAddAll(FORBIDDEN_BACKSLASH);

+

+        this.encodedUrlBlacklist.add(ENCODED_PERCENT);

+        this.encodedUrlBlacklist.addAll(FORBIDDEN_ENCODED_PERIOD);

+        this.decodedUrlBlacklist.add(PERCENT);

+    }

+    

+    private void urlBlacklistsAddAll(Collection<String> values) {

+        this.encodedUrlBlacklist.addAll(values);

+        this.decodedUrlBlacklist.addAll(values);

+    }

+

+    public boolean validate(HttpServletRequest request) {

+        return matches(request);	    

+    }        

+    @Override

+    public boolean matches(HttpServletRequest request) {

+        String logPrefix = "BadRequestMatcher.matches , ";

+	boolean foundElements = false;

+        for (Enumeration en = request.getParameterNames(); en

+                .hasMoreElements();) {

+

+            foundElements = true;

+

+            Object obj = en.nextElement();

+            String value = request.getParameterValues((String) obj)[0];

+            if (!isNormalized(value)) {

+                logger.error(logPrefix + 

+		    "found illegal String: " +value+ " , returning false because the request has parameters that are not 'normalized i.e. paths contain dir traversal or illegal chars'");

+		return false;

+                

+            }

+            if (!rejectedBlacklistedValues(value)) {

+                logger.error(logPrefix + 

+		    "found illegal String: " +value+ " , returning false because the request has rejected black list values");

+		return false;

+                

+            }

+            if (requestDebuggingActivated == 1) {

+                logger.error(logPrefix + 

+		    "on requestDebuggingActivated=1 found String: " +value);

+                

+            }

+        }

+        if (!foundElements) {

+            logger.warn(logPrefix + "on requestDebuggingActivated=1 , no HTTP elements found!");

+        }

+        rejectedBlacklistedUrls(request);

+        if (!isNormalized(request)) {

+            logger.error(logPrefix + 

+	        "inside BadRequestMatcher.matches, returning false because the request was not 'normalized i.e. paths contain dir traversal or illegal chars'");

+            return false;

+        }

+        String requestUri = request.getRequestURI();

+        if (!containsOnlyPrintableAsciiCharacters(requestUri)) {

+            logger.error(logPrefix +

+                "The requestURI was rejected because it can only contain printable ASCII characters.");

+            return false;

+

+        }

+        return true;

+    }

+    

+    private boolean containsOnlyPrintableAsciiCharacters(String uri) {

+        int length = uri.length();

+        for (int i = 0; i < length; i++) {

+            char c = uri.charAt(i);

+            if (c < '\u0020' || c > '\u007e') {

+                return false;

+            }

+        }

+

+        return true;

+    }

+    

+    private boolean rejectedBlacklistedUrls(HttpServletRequest request) {

+        String logPrefix = "BadRequestMatcher.rejectedBlacklistedUrls , ";

+        for (String forbidden : this.encodedUrlBlacklist) {

+            if (encodedUrlContains(request, forbidden)) {

+                logger.error(logPrefix + 

+	            "returning false, The request was rejected because the URL contained a potentially malicious String \"" + forbidden + "\"");

+		return false;

+            }

+        }

+        for (String forbidden : this.decodedUrlBlacklist) {

+            if (decodedUrlContains(request, forbidden)) {

+                logger.error(logPrefix + 

+                    "The request was rejected because the URL contained a potentially malicious String \"" + forbidden + "\"");

+		return false;

+            }

+        }

+        return true;

+    }

+    

+    private boolean rejectedBlacklistedValues(String value) {

+        String logPrefix = "BadRequestMatcher.matches , ";

+        for (String forbidden : this.encodedUrlBlacklist) {

+            if (valueContains(value, forbidden)) {

+                logger.error(logPrefix + "found illegal String: " +value+ " , returning false because the request has parameters that are not 'normalized i.e. paths contain dir traversal or illegal chars'");

+		return false;

+            }

+        }    

+        return true;

+    }

+    

+    private boolean valueContains(String value, String contains) {

+        return value != null && value.contains(contains);

+    }

+

+    private boolean encodedUrlContains(HttpServletRequest request, String value) {

+        if (valueContains(request.getContextPath(), value)) {

+            return true;

+        }

+        return valueContains(request.getRequestURI(), value);

+    }

+

+    private boolean decodedUrlContains(HttpServletRequest request, String value) {

+        if (valueContains(request.getServletPath(), value)) {

+            return true;

+        }

+        if (valueContains(request.getPathInfo(), value)) {

+            return true;

+        }

+        return false;

+    }

+    

+    /**

+     * This should be done by Spring Security StrictHttpFirewall but isn't working as expected, 

+     * turns out its not as detailed as we need. 

+     * Instead of sub-classing it to add logging - there is none - and features, just do the important parts here

+     *  

+     * Checks whether a path is normalized (doesn't contain path traversal

+     * sequences like "./", "/../" or "/.")

+     *

+     * @param path

+     *            the path to test

+     * @return true if the path doesn't contain any path-traversal character

+     *         sequences.

+     */

+    private boolean isNormalized(HttpServletRequest request) {

+        String logPrefix = "BadRequestMatcher.isNormalized , ";

+        if (!isNormalized(request.getRequestURI())) {

+            logger.error(logPrefix + "returning false on request.getRequestURI() : " + request.getRequestURI());

+            return false;

+        }

+        if (!isNormalized(request.getContextPath())) {

+            logger.error(logPrefix + "returning false on request.getContextPath() : " + request.getContextPath());

+            return false;

+        }

+        if (!isNormalized(request.getServletPath())) {

+            logger.error(logPrefix + "returning false on request.getServletPath() : " + request.getServletPath());

+            return false;

+        }

+        if (!isNormalized(request.getPathInfo())) {

+            logger.error(logPrefix + "returning false on request.getPathInfo() : " + request.getPathInfo());

+            return false;

+        }

+        return true;

+    }

+    

+    private boolean isNormalized(String path) {

+        

+        String logPrefix = "BadRequestMatcher.isNormalized(String path) , ";

+        

+        logger.warn(logPrefix + "evaluating path : " + path);

+        

+        if (path == null) {

+            return true;

+        }

+

+        if (path.indexOf("//") > -1) {

+            return false;

+        }

+

+        for (int j = path.length(); j > 0;) {

+            int i = path.lastIndexOf('/', j - 1);

+            int gap = j - i;

+

+            if (gap == 2 && path.charAt(i + 1) == '.') {

+                // ".", "/./" or "/."

+                return false;

+            } else if (gap == 3 && path.charAt(i + 1) == '.' && path.charAt(i + 2) == '.') {

+                return false;

+            }

+

+            j = i;

+        }

+

+          return true;

+      }

+

+}

diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/HTTPPostOnlyRejectionFilter.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/HTTPPostOnlyRejectionFilter.java
new file mode 100644
index 0000000..9b9dd58
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/HTTPPostOnlyRejectionFilter.java
@@ -0,0 +1,89 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.security.webservices;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.http.server.ServletServerHttpRequest;
+import org.springframework.web.filter.OncePerRequestFilter;
+import org.springframework.web.util.ContentCachingRequestWrapper;
+import org.springframework.web.util.ContentCachingResponseWrapper;
+import org.springframework.web.util.WebUtils;
+import org.springframework.security.web.RedirectStrategy;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.UUID;
+
+public class HTTPPostOnlyRejectionFilter extends OncePerRequestFilter {
+ 
+    private static Log logger = LogFactory.getLog(HTTPPostOnlyRejectionFilter.class);
+    
+    private final RedirectStrategy redirectStrategy = new NoRedirectStrategy();
+
+    public HTTPPostOnlyRejectionFilter() {
+        super();
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
+
+        String uuid = UUID.randomUUID().toString();
+        String logPrefix = "HTTPPostOnlyRejectionFilter.doFilterInternal , uuid: " + uuid + " , ";
+        
+        logger.trace(logPrefix + "starting ... ");
+        
+        if (!request.getMethod().equals("POST")) {
+
+	    String ip = "unknown";
+            if (request.getHeader("X-Forwarded-For") != null) { 
+	        ip = request.getHeader("X-Forwarded-For");
+            }
+            logger.trace(logPrefix +
+                "this is not a POST request, ignoring with an HTTP 200 response, " +
+                " , on IP from X-Forwarded-For: " + request.getRequestURI() + 
+                " , request.getRequestURI() : " + request.getRequestURI() + 
+		" , request.getMethod() : " + request.getMethod());
+
+            response.setContentType("application/json;charset=UTF-8");
+            response.getWriter().print("HTTP requests that are not POST are ignored");
+            response.getWriter().flush();
+            this.redirectStrategy.sendRedirect((HttpServletRequest) request, (HttpServletResponse) response, "/");
+
+        } else {
+            filterChain.doFilter(request, response);
+        }
+    }
+
+    protected class NoRedirectStrategy implements RedirectStrategy {
+
+        @Override
+        public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url)
+                throws IOException {
+            // do nothing
+        }
+
+    }
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTAuthenticationFilter.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTAuthenticationFilter.java
new file mode 100644
index 0000000..e46c9c7
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTAuthenticationFilter.java
@@ -0,0 +1,136 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.security.webservices;
+
+import java.io.IOException;
+import java.util.UUID;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
+import org.owasp.esapi.ESAPI;
+import org.owasp.esapi.Validator;
+
+public class JWTAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
+    
+    @Autowired
+    private WSSecUtils wssecutils;
+
+    public JWTAuthenticationFilter() {
+        super("/**");
+    }
+
+    @Override
+    @Autowired
+    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
+        super.setAuthenticationManager(authenticationManager);
+    }
+
+    @Override
+    protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
+        return true;
+    }
+
+    @Override
+    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
+        String logPrefix = "JWTAuthenticationFilter.attemptAuthentication() , ";
+
+        // if this fails it will throw a fatal error, don't catch it since it could be evil data
+        String authToken = getBearerToken(request);
+
+        JWTAuthenticationToken authRequest = new JWTAuthenticationToken(authToken);
+
+        return getAuthenticationManager().authenticate(authRequest);
+    }
+
+    public String getBearerToken(HttpServletRequest request) throws AuthenticationException {
+        String logPrefix = "JWTAuthenticationFilter.getBearerToken() , ";
+        String header = request.getHeader("Authorization");
+
+        if (header == null || !header.startsWith("Bearer ")) {
+            throw new JWTTokenMissingException("No JWT token found in request headers");
+        }
+        Validator validator = ESAPI.validator();
+        boolean headerstatus = validator.isValidInput("userInput", header, "HTTPHeaderValue", 1000 , false);
+        if (!headerstatus) {
+            logger.error(logPrefix + "returning with failure status on invalid header: " + header);
+            throw new JWTTokenMissingException("invalid header");
+        }
+
+        String authToken = header.substring(7);
+
+        return authToken;
+    }
+
+    @Override
+    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
+            
+        String logPrefix = "JWTAuthenticationFilter.successfulAuthentication() , ";
+
+        String authToken = getBearerToken(request);
+        JWTUserDTO parsedUser = null; 
+        try{
+            parsedUser = wssecutils.getParsedUser(authToken);
+        } catch (Exception ex) {
+            logger.error(logPrefix +  ex.getMessage(), ex );
+        }
+
+        if (parsedUser == null) {
+            throw new ServletException("JWT token is not valid, cannot find user");
+        }
+        String uuid = parsedUser.getUuid();
+        if (uuid == null) {
+            throw new ServletException("JWT token is not valid, cannot find uuid");
+        }
+        logger.warn(logPrefix + "found uuid from token: " + uuid);
+        String usernameFromToken = parsedUser.getUsername();
+        if (usernameFromToken == null) {
+            throw new ServletException("JWT token is not valid, cannot find username");
+        }
+        usernameFromToken = usernameFromToken.trim();
+
+        String currentUserIPAddress = null;
+
+	String newuuid = UUID.randomUUID().toString();
+
+        // As this authentication is in the HTTP header, after success we need to continue 
+        // the request normally and return the response as if the resource was not secured at all
+
+        // set some vars that may be helpful to the webservices
+        request.setAttribute("email", usernameFromToken);
+        request.setAttribute("uuid", newuuid);
+        request.setAttribute("currentUserIPAddress", currentUserIPAddress);
+
+        SecurityContextHolder.getContext().setAuthentication(authResult);
+   
+        chain.doFilter(request, response);
+    }
+ 
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTAuthenticationProvider.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTAuthenticationProvider.java
new file mode 100644
index 0000000..7137858
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTAuthenticationProvider.java
@@ -0,0 +1,108 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.security.webservices;
+
+import java.util.List;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+
+import userguide.springboot.requestactivity.Axis2UserDetails;
+
+@Component
+public class JWTAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
+
+    private static final Logger log = LogManager.getLogger(JWTAuthenticationProvider.class);
+    
+    @Autowired
+    private WSSecUtils wssecutils;
+
+    @Override
+    public boolean supports(Class<?> authentication) {
+        return (JWTAuthenticationToken.class.isAssignableFrom(authentication));
+    }
+
+    @Override
+    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
+    }
+
+    @Override
+    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
+        String logPrefix = "JWTAuthenticationProvider.retrieveUser() , username: " +username+ " , ";
+        JWTAuthenticationToken jwtAuthenticationToken = (JWTAuthenticationToken) authentication;
+        String token = jwtAuthenticationToken.getToken();
+
+        try {
+            JWTUserDTO parsedUser = wssecutils.getParsedUser(token);
+    
+            if (parsedUser == null) {
+                throw new JWTTokenMalformedException("JWT token is not valid, cannot find user");
+            }
+            logger.warn(logPrefix + "found parsedUser: " + parsedUser.toString());
+            String uuid = parsedUser.getUuid();
+            if (uuid == null) {
+                throw new JWTTokenMalformedException("JWT token is not valid, cannot find uuid");
+            }
+            if (parsedUser.getUsername() == null) {
+                throw new JWTTokenMalformedException("JWT token is not valid, cannot find email");
+            }
+            logger.warn(logPrefix + "found uuid from token: " + uuid);
+
+            LoginDTO persistedUser = null;
+            try {
+                persistedUser = wssecutils.findUserByEmail(parsedUser.getUsername());
+            } catch (Exception ex) {
+                logger.error(logPrefix + "cannot create LoginDTO from email: " + parsedUser.getUsername() + " , " + ex.getMessage(), ex);
+                throw new JWTTokenMalformedException("JWT token is not valid, cannot create LoginDTO from email: " + parsedUser.getUsername());
+            }
+            if (persistedUser == null) {
+                logger.error(logPrefix + "returning with failure status on failed creation of LoginDTO from email: " + parsedUser.getUsername());
+                throw new JWTTokenMalformedException("JWT token is not valid, LoginDTO is null from email: " + parsedUser.getUsername());
+            }
+            List<GrantedAuthority> authorityList = AuthorityUtils.commaSeparatedStringToAuthorityList(parsedUser.getRole());
+
+            Boolean isNonLocked;
+
+            if (persistedUser.getAccountNonLocked()) {
+                isNonLocked = true;
+            } else {
+                isNonLocked = false;
+            }
+
+            Axis2UserDetails userDetails = new Axis2UserDetails(persistedUser, parsedUser.getUsername(), token, persistedUser.getEnabled(), persistedUser.getAccountNonExpired(), persistedUser.getCredentialsNonExpired(), isNonLocked, authorityList);
+
+            return userDetails;
+        
+        } catch (Exception ex) {
+            logger.error(logPrefix + "failed: " + ex.getMessage(), ex);
+            throw new JWTTokenMalformedException("unexpected error parsing token");
+        }
+            
+    }
+
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTAuthenticationSuccessHandler.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTAuthenticationSuccessHandler.java
new file mode 100644
index 0000000..ae0a6cd
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTAuthenticationSuccessHandler.java
@@ -0,0 +1,35 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.security.webservices;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
+
+public class JWTAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
+	
+	@Override
+    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
+        // We do not need to do anything extra on REST authentication success, because there is no page to redirect to
+    }
+
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTAuthenticationToken.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTAuthenticationToken.java
new file mode 100644
index 0000000..60f654f
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTAuthenticationToken.java
@@ -0,0 +1,48 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.security.webservices;
+
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+
+public class JWTAuthenticationToken extends UsernamePasswordAuthenticationToken {
+    
+    private static final long serialVersionUID = -5031102661066770894L;
+
+    private String token;
+
+    public JWTAuthenticationToken(String token) {
+        super(null, null);
+        this.token = token;
+    }
+
+    public String getToken() {
+        return token;
+    }
+
+    @Override
+    public Object getCredentials() {
+        return null;
+    }
+
+    @Override
+    public Object getPrincipal() {
+        return null;
+    }
+}
diff --git a/modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTTokenAuthenticationException.java
similarity index 61%
copy from modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java
copy to modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTTokenAuthenticationException.java
index 619c1ae..ea35763 100644
--- a/modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTTokenAuthenticationException.java
@@ -1,3 +1,4 @@
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -16,24 +17,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package userguide.springboot.security.webservices;
 
-package org.apache.axis2.json.gson;
+import org.springframework.security.core.AuthenticationException;
 
-import org.owasp.encoder.Encode;
+public class JWTTokenAuthenticationException extends AuthenticationException {
 
-import com.google.gson.JsonElement;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import java.lang.reflect.Type;
+    private static final long serialVersionUID = -659063016840102545L;
 
-public class JsonHtmlXssSerializer implements JsonSerializer<String> {
+        public JWTTokenAuthenticationException(String msg) {
+        super(msg);
+    }
 
-	@Override
-	public JsonElement serialize(String src, Type typeOfSrc,
-			JsonSerializationContext context) {
-
-		return new JsonPrimitive(Encode.forHtmlContent(src));
-
-	}
 }
diff --git a/modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTTokenMalformedException.java
similarity index 61%
copy from modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java
copy to modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTTokenMalformedException.java
index 619c1ae..df9a3c3 100644
--- a/modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTTokenMalformedException.java
@@ -1,3 +1,4 @@
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -16,24 +17,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package userguide.springboot.security.webservices;
 
-package org.apache.axis2.json.gson;
+import org.springframework.security.core.AuthenticationException;
 
-import org.owasp.encoder.Encode;
+public class JWTTokenMalformedException extends AuthenticationException {
+	
+	private static final long serialVersionUID = 4207020475526562507L;
 
-import com.google.gson.JsonElement;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import java.lang.reflect.Type;
+	public JWTTokenMalformedException(String msg) {
+        super(msg);
+    }
 
-public class JsonHtmlXssSerializer implements JsonSerializer<String> {
-
-	@Override
-	public JsonElement serialize(String src, Type typeOfSrc,
-			JsonSerializationContext context) {
-
-		return new JsonPrimitive(Encode.forHtmlContent(src));
-
-	}
 }
diff --git a/modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTTokenMissingException.java
similarity index 61%
copy from modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java
copy to modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTTokenMissingException.java
index 619c1ae..3acd5af 100644
--- a/modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTTokenMissingException.java
@@ -1,3 +1,4 @@
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -16,24 +17,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package userguide.springboot.security.webservices;
 
-package org.apache.axis2.json.gson;
+import org.springframework.security.core.AuthenticationException;
 
-import org.owasp.encoder.Encode;
+public class JWTTokenMissingException extends AuthenticationException {
 
-import com.google.gson.JsonElement;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import java.lang.reflect.Type;
+	private static final long serialVersionUID = -659063016840102545L;
 
-public class JsonHtmlXssSerializer implements JsonSerializer<String> {
-
-	@Override
-	public JsonElement serialize(String src, Type typeOfSrc,
-			JsonSerializationContext context) {
-
-		return new JsonPrimitive(Encode.forHtmlContent(src));
-
+	public JWTTokenMissingException(String msg) {
+		super(msg);
 	}
+
 }
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTUserDTO.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTUserDTO.java
new file mode 100644
index 0000000..dae5d35
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/JWTUserDTO.java
@@ -0,0 +1,55 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.security.webservices;
+
+public class JWTUserDTO {
+    
+    private String uuid;
+
+    private String username;
+
+    private String role;
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getRole() {
+        return role;
+    }
+
+    public void setRole(String role) {
+        this.role = role;
+    }
+
+    public void setUuid(String uuid) {
+             
+    this.uuid = uuid;
+    }
+
+    public String getUuid() {
+        return uuid;
+    }
+
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/LoginDTO.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/LoginDTO.java
new file mode 100644
index 0000000..04614e8
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/LoginDTO.java
@@ -0,0 +1,105 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.security.webservices;
+
+public class LoginDTO {
+    
+    private String email;
+
+    private String password;
+
+    private Boolean enabled;
+
+    private Boolean accountNonExpired;
+
+    private Boolean credentialsNonExpired;
+    
+    private Boolean accountNonLocked;
+    
+
+    public Boolean getAccountNonLocked() {
+        return accountNonLocked;
+    }
+
+    public void setAccountNonLocked(Boolean accountNonLocked) {
+        this.accountNonLocked = accountNonLocked;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public Boolean getEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(Boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public Boolean getAccountNonExpired() {
+        return accountNonExpired;
+    }
+
+    public void setAccountNonExpired(Boolean accountNonExpired) {
+        this.accountNonExpired = accountNonExpired;
+    }
+
+    public Boolean getCredentialsNonExpired() {
+        return credentialsNonExpired;
+    }
+
+    public void setCredentialsNonExpired(Boolean credentialsNonExpired) {
+        this.credentialsNonExpired = credentialsNonExpired;
+    }
+
+    public LoginDTO(String email, String password, Boolean enabled, Boolean accountNonExpired, Boolean credentialsNonExpired, Boolean accountNonLocked) {
+        super();
+        this.email = email;
+        this.password = password;
+        this.enabled = enabled;
+        this.accountNonExpired = accountNonExpired;
+        this.credentialsNonExpired = credentialsNonExpired;
+        this.accountNonLocked = accountNonLocked;
+    }
+
+    @Override
+    public String toString() {
+        return "LoginDTO [email=" + email 
+                + ", enabled=" + enabled + ", accountNonExpired="
+                + accountNonExpired + ", credentialsNonExpired="
+                + credentialsNonExpired + ", accountNonLocked="
+                + accountNonLocked + "]";
+    }
+    
+        
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/RequestAndResponseValidatorFilter.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/RequestAndResponseValidatorFilter.java
new file mode 100644
index 0000000..95a2e47
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/RequestAndResponseValidatorFilter.java
@@ -0,0 +1,200 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.security.webservices;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.http.server.ServletServerHttpRequest;
+import org.springframework.web.filter.OncePerRequestFilter;
+import org.springframework.web.util.ContentCachingRequestWrapper;
+import org.springframework.web.util.ContentCachingResponseWrapper;
+import org.springframework.web.util.WebUtils;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.UUID;
+
+@PropertySource("classpath:application.properties")
+public class RequestAndResponseValidatorFilter extends OncePerRequestFilter {
+ 
+    private static Log logger = LogFactory.getLog(RequestAndResponseValidatorFilter.class);
+    
+    private static ThreadLocal<Long> requestBeginTime = new ThreadLocal<>();
+    private static final int DEFAULT_MAX_PAYLOAD_LENGTH = 16384;
+
+    private int maxPayloadLength = DEFAULT_MAX_PAYLOAD_LENGTH;
+
+    @Value("${requestDebuggingActivated}")
+    private int requestDebuggingActivated;
+
+    public RequestAndResponseValidatorFilter() {
+        super();
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
+
+        String uuid = UUID.randomUUID().toString();
+        String logPrefix = "RequestAndResponseValidatorFilter.doFilterInternal , uuid: " + uuid + " , request.getRequestURI():" + request.getRequestURI() + " , ";
+        
+        logger.debug(logPrefix + "starting ... ");
+        
+        BadRequestMatcher bad = new BadRequestMatcher(requestDebuggingActivated);
+        if (!bad.validate(request)) {
+            throw new ServletException("request is invalid, it contains a potentially malicious String");
+        }
+        
+        boolean isFirstRequest = !isAsyncDispatch(request);
+        HttpServletRequest requestToUse = request;
+
+        if (isFirstRequest && !(request instanceof ContentCachingRequestWrapper)) {
+            requestToUse = new ContentCachingRequestWrapper(request, getMaxPayloadLength());
+        }
+
+        HttpServletResponse responseToUse = response;
+        if (!(response instanceof ContentCachingResponseWrapper)) {
+            responseToUse = new ContentCachingResponseWrapper(response);
+        }
+
+        requestBeginTime.set(System.currentTimeMillis());
+
+        String currentUserIPAddress = null;
+        if (requestToUse.getHeader("X-Forwarded-For") != null) {
+            currentUserIPAddress = requestToUse.getHeader("X-Forwarded-For");
+        } else {
+            logger.warn(logPrefix + "cannot find X-Forwarded-For header, this field is required for proper IP auditing");
+            logger.warn(logPrefix + "Because no X-Forwarded-For header was found, setting 'currentUserIPAddress = requestToUse.getRemoteAddr()' which is typically an internal address");
+            currentUserIPAddress = requestToUse.getRemoteAddr();
+        }
+
+        if (currentUserIPAddress == null || currentUserIPAddress.length() == 0 || "unknown".equalsIgnoreCase(currentUserIPAddress)) {
+            logger.warn(logPrefix + "cannot find valid currentUserIPAddress");
+        } else {
+            logger.warn(logPrefix + "proceeding on currentUserIPAddress: " + currentUserIPAddress);
+            // rate limiting and extra validation can go here
+        }
+        
+        try {
+            filterChain.doFilter(requestToUse, responseToUse);
+        } finally {
+            logRequest(createRequestMessage(requestToUse,uuid));
+            logRequest(createResponseMessage(responseToUse,uuid));
+        }
+    }
+
+    protected String createRequestMessage(HttpServletRequest request, String uuid) throws ServletException {
+        
+        StringBuilder msg = new StringBuilder();
+        msg.append("HTTP request with uuid: " + uuid + " , ");
+        msg.append(request.getMethod());
+        msg.append(" uri=").append(request.getRequestURI());
+
+        String queryString = request.getQueryString();
+        if (queryString != null) {
+            msg.append('?').append(queryString);
+        }
+
+        String user = request.getRemoteUser();
+        if (user != null) {
+            msg.append(";user=").append(user);
+        }
+
+        
+        return msg.toString();
+    }
+
+    protected String createResponseMessage(HttpServletResponse resp, String uuid) throws ServletException{
+
+        StringBuilder msg = new StringBuilder();
+        msg.append("HTTP response with uuid: " + uuid + " , ");
+
+        ContentCachingResponseWrapper responseWrapper = WebUtils.getNativeResponse(resp, ContentCachingResponseWrapper.class);
+        if (responseWrapper != null) {
+            byte[] buf = responseWrapper.getContentAsByteArray();
+            try {
+                responseWrapper.copyBodyToResponse();
+            } catch (IOException e) {
+                logger.error("Fail to write response body back", e);
+            }
+            if (buf.length > 0) {
+                String payload;
+                try {
+                    payload = new String(buf, 0, buf.length, responseWrapper.getCharacterEncoding());
+                } catch (UnsupportedEncodingException ex) {
+                    payload = "[unknown]";
+                }
+                msg.append(";response=").append(payload);
+            }
+        }
+        
+        return msg.toString();
+    }
+
+    public static boolean validate(String msg) {
+        // Input validation is inferior to output sanitation as its impossible to think of 
+        // everything. See JsonHtmlXssSerializer for html encoding of the output
+        
+        if (msg != null && msg.toUpperCase().contains("DOCTYPE")) {
+            logger.error("DOCTYPE keyword is disallowed");
+            return false;
+        }
+	
+        // reflected XSS
+        if (msg != null && msg.toUpperCase().indexOf("SCRIPT") != -1) {
+            logger.error("SCRIPT keyword is disallowed");
+            return false;
+        }
+        // reflected XSS without script tag, sneaky ... <img onerror=alert(1)/>
+        if (msg != null && msg.toUpperCase().indexOf("ALERT") != -1) {
+            logger.error("ALERT keyword is disallowed");
+            return false;
+        }
+                
+        return true;
+        
+    }
+
+    public int getMaxPayloadLength() {
+        return maxPayloadLength;
+    }
+
+    protected void logRequest(String message) {
+
+        String logPrefix = "RequestAndResponseValidatorFilter.logRequest() , ";
+        long begin = requestBeginTime.get();
+        long end = System.currentTimeMillis();
+ 
+        long duration = end - begin;
+        if (message != null && message.toString().toUpperCase().indexOf("CREDENTIALS") != -1) {
+            logger.info(logPrefix + " , not logging credentials ... request time:" + duration);
+        } else {
+            logger.info(logPrefix + message + ", request time:" + duration);
+        }
+    }
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/RestAuthenticationEntryPoint.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/RestAuthenticationEntryPoint.java
new file mode 100644
index 0000000..c7c3e68
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/RestAuthenticationEntryPoint.java
@@ -0,0 +1,39 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.security.webservices;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+@Component
+public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
+	@Override
+    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
+        // This is invoked when user tries to access a secured REST resource without supplying any credentials
+        // We should just send a 401 Unauthorized response because there is no 'login page' to redirect to
+        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
+    }
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/WSLoginFilter.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/WSLoginFilter.java
new file mode 100644
index 0000000..c1df12e
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/WSLoginFilter.java
@@ -0,0 +1,93 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.security.webservices;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.filter.GenericFilterBean;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
+
+@PropertySource("classpath:application.properties")
+public class WSLoginFilter extends GenericFilterBean  {
+    
+    @Value("${requestDebuggingActivated}")
+    private int requestDebuggingActivated;
+
+    @Override
+    public void doFilter(
+        ServletRequest request, 
+        ServletResponse response,
+        FilterChain chain) throws IOException, ServletException {
+              
+        final String logPrefix = "WSLoginFilter.doFilter() , requestDebuggingActivated: " + requestDebuggingActivated + " , ";
+
+        logger.debug(logPrefix + "starting ... ");
+
+        HttpServletRequest requestToUse = (HttpServletRequest) request;
+        HttpServletResponse responseToUse = (HttpServletResponse) response;
+
+        String currentUserIPAddress = null;
+        if (requestToUse.getHeader("X-Forwarded-For") != null) {
+            currentUserIPAddress = requestToUse.getHeader("X-Forwarded-For");
+        } else {
+            logger.warn(logPrefix + "cannot find X-Forwarded-For header, this field is required for proper IP auditing");
+            logger.warn(logPrefix + "Because no X-Forwarded-For header was found, setting 'currentUserIPAddress = requestToUse.getRemoteAddr()' which is typically an internal address");
+            currentUserIPAddress = requestToUse.getRemoteAddr();
+        }
+
+        if (currentUserIPAddress == null || currentUserIPAddress.length() == 0 || "unknown".equalsIgnoreCase(currentUserIPAddress)) {
+            logger.warn(logPrefix + "cannot find valid currentUserIPAddress");
+        } else {
+            logger.warn(logPrefix + "IP validation and rate limiting can go here, on currentUserIPAddress: " + currentUserIPAddress);
+        }
+
+        if (requestDebuggingActivated == 1) {
+	    boolean foundElements = false;
+            for (Enumeration en = requestToUse.getParameterNames(); en
+                    .hasMoreElements();) {
+    
+                foundElements = true;
+
+                Object obj = en.nextElement();
+                String value = request.getParameterValues((String) obj)[0];
+                logger.warn(logPrefix + "on requestDebuggingActivated=1 found String: " +value);
+                    
+            }
+            if (!foundElements) {
+                logger.warn(logPrefix + "on requestDebuggingActivated=1 , no HTTP elements found!");
+            }
+        }
+
+        chain.doFilter(request, response);
+    }
+
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/WSSecUtils.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/WSSecUtils.java
new file mode 100644
index 0000000..2f5c98b
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/security/webservices/WSSecUtils.java
@@ -0,0 +1,83 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.security.webservices;
+
+import java.util.UUID;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+@Component
+public class WSSecUtils {
+
+    private static final Logger logger = LogManager.getLogger(WSSecUtils.class);
+    
+    protected JWTUserDTO getParsedUser(String token) throws Exception {
+        String logPrefix = "WSSecUtils.getParsedUser() , ";
+
+        // JWT and JWE are specifications to generate and validate tokens 
+        // securely, however they require a public / private key pair using
+        // elliptic curve cryptography and that is beyond the scope of this
+        // userguide.
+        // See below:
+        // https://datatracker.ietf.org/doc/html/rfc7516
+        // https://datatracker.ietf.org/doc/html/rfc7519
+
+        // token generated via RandomStringUtils.randomAlphanumeric(20);
+        // Do not use this for production code. 
+        if (token == null || token.length() != 20) {
+            throw new Exception("Invalid Token");
+        }
+        try {
+            // All of this info is available in the JWT spec
+            // however that is beyond the scope of this userguide
+            JWTUserDTO user = new JWTUserDTO();
+            user.setUsername("java-dev@axis.apache.org");
+            user.setRole("ROLE_USER");
+            // JWT ID that could be from the "Claimset" i.e.
+            // jwt.getJWTClaimsSet().getJWTID());
+            user.setUuid(UUID.randomUUID().toString());
+                       
+            return user;
+        
+        } catch (Exception ex) {
+            logger.error(logPrefix + "failed: " + ex.getMessage(), ex);
+            throw new JWTTokenMalformedException("unexpected error parsing token");
+        }
+        
+    }
+
+    public final LoginDTO findUserByEmail(String email) {
+
+        String logPrefix = "WSSecUtils.findUserByEmail() , " ;
+
+        if (email != null && email.equals("java-dev@axis.apache.org")) {
+            LoginDTO persistedUser = new LoginDTO("java-dev@axis.apache.org", "userguide", true, true, true, true);
+            return persistedUser;
+        }
+
+        logger.error(logPrefix + "Unknown email: " + email);
+
+        return null;
+
+    }
+
+}
diff --git a/modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/TestwsRequest.java
similarity index 61%
copy from modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java
copy to modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/TestwsRequest.java
index 619c1ae..fbd1636 100644
--- a/modules/json/src/org/apache/axis2/json/gson/JsonHtmlXssSerializer.java
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/TestwsRequest.java
@@ -1,3 +1,4 @@
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -16,24 +17,28 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package userguide.springboot.webservices;
 
-package org.apache.axis2.json.gson;
+public class TestwsRequest {
+    
+    String messagein;
+    
+    public String getMessagein() {
+        return messagein;
+    }
 
-import org.owasp.encoder.Encode;
+    public void setMessagein(String messagein) {
+        this.messagein = messagein;
+    }
 
-import com.google.gson.JsonElement;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import java.lang.reflect.Type;
+    public TestwsRequest(String messagein) {
+        this.messagein = messagein;
+    }
 
-public class JsonHtmlXssSerializer implements JsonSerializer<String> {
-
-	@Override
-	public JsonElement serialize(String src, Type typeOfSrc,
-			JsonSerializationContext context) {
-
-		return new JsonPrimitive(Encode.forHtmlContent(src));
-
-	}
+    @Override
+    public String toString() {
+        return "TestwsRequest [messagein="
+                + messagein + "]";
+    }
+    
 }
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/TestwsResponse.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/TestwsResponse.java
new file mode 100644
index 0000000..dbd42d9
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/TestwsResponse.java
@@ -0,0 +1,56 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.webservices;
+
+public class TestwsResponse {
+
+    String messageout;
+    String status;
+    
+    public String getMessageout() {
+        return messageout;
+    }
+
+    public void setMessageout(String messageout) {
+        this.messageout = messageout;
+    }
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public TestwsResponse() {
+    }
+
+    public TestwsResponse(String messageout, String status) {
+        this.messageout = messageout;
+        this.status = status;
+    }
+
+    @Override
+    public String toString() {
+        return "TestwsResponse [messageout="
+                + messageout + " , status=" + status + "]";
+    }
+
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/TestwsService.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/TestwsService.java
new file mode 100644
index 0000000..7fd14c5
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/TestwsService.java
@@ -0,0 +1,71 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.webservices;
+
+import java.util.UUID;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import org.owasp.esapi.ESAPI;
+import org.owasp.esapi.Validator;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class TestwsService {
+
+    private static final Logger logger = LogManager.getLogger(TestwsService.class);
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public TestwsResponse doTestws(TestwsRequest request) {
+
+        String uuid = UUID.randomUUID().toString();
+
+        String logPrefix = "TestwsService.doTestws() , uuid: " + uuid + " , ";
+
+        logger.warn(logPrefix + "starting on request: " + request.toString());
+        TestwsResponse response = new TestwsResponse();
+
+        try {
+            // All data is evil!
+            Validator validator = ESAPI.validator();
+            boolean messageinstatus = validator.isValidInput("userInput", request.getMessagein(), "SafeString", 100 , false);
+            if (!messageinstatus) {
+                logger.error(logPrefix + "returning with failure status on invalid messagein: " + request.getMessagein());
+                response.setStatus("FAILED");
+                return response;
+            }
+            response.setStatus("OK");
+            String evil = "<script xmlns=\"http://www.w3.org/1999/xhtml\">alert('Hello');</script> \">";
+            response.setMessageout(evil);
+            
+            logger.warn(logPrefix + "returning response: " + response.toString());
+            return response;
+
+        } catch (Exception ex) {
+            logger.error(logPrefix + "failed: " + ex.getMessage(), ex);
+            response.setStatus("FAILED");
+            return response;
+        }
+
+    }
+
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginRequest.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginRequest.java
new file mode 100644
index 0000000..1e6d5bb
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginRequest.java
@@ -0,0 +1,55 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.webservices.secure;
+
+public class LoginRequest {
+    
+    String email;
+    
+    String credentials;
+
+    public String getEmail() {
+        return  email != null ? email.trim() : null;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getCredentials() {
+        return credentials;
+    }
+
+    public void setCredentials(String credentials) {
+        this.credentials = credentials;
+    }
+
+
+    public LoginRequest(String email, String credentials) {
+        this.email = email;
+        this.credentials = credentials;
+    }
+    
+    @Override
+    public String toString() {
+	// implement toString() for debugging in trace mode of axis2
+        return "LoginRequest [email=" + email + ", credentials=not_shown ]";
+    }
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginResponse.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginResponse.java
new file mode 100644
index 0000000..c140b5d
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginResponse.java
@@ -0,0 +1,63 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.webservices.secure;
+
+public class LoginResponse {
+
+    String status;
+    
+    String token;
+    
+    String uuid;
+    
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getToken() {
+        return token;
+    }
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    public LoginResponse(String status, String token) {
+        this.status = status;
+        this.token = token;
+    }
+    
+    public LoginResponse() {
+        
+    }
+
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginService.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginService.java
new file mode 100644
index 0000000..7bddf44
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginService.java
@@ -0,0 +1,238 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package userguide.springboot.webservices.secure;
+
+import java.util.UUID;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+
+import org.apache.commons.lang3.RandomStringUtils; 
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.crypto.password.NoOpPasswordEncoder;
+
+import userguide.springboot.security.webservices.WSSecUtils;
+import userguide.springboot.security.webservices.LoginDTO;
+import userguide.springboot.security.webservices.RequestAndResponseValidatorFilter;
+import userguide.springboot.hibernate.dao.SpringSecurityDAOImpl;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.axis2.context.MessageContext;
+import org.apache.axis2.transport.http.HTTPConstants;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.owasp.esapi.ESAPI;
+import org.owasp.esapi.Validator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class LoginService {
+
+    private static final Logger logger = LogManager.getLogger(LoginService.class);
+
+    @Autowired
+    SpringSecurityDAOImpl springSecurityDAOImpl;
+
+    @Autowired
+    NoOpPasswordEncoder passwordEncoder;
+
+    @Autowired
+    private WSSecUtils wssecutils;
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public LoginResponse doLogin(LoginRequest request) {
+
+        Long startTime = System.currentTimeMillis();
+
+        String uuid = UUID.randomUUID().toString();
+
+        String logPrefix = "LoginService.doLogin() , "
+                + " , uuid: " + uuid + " , request: " + request.toString() + " , ";
+
+        logger.warn(logPrefix + "starting ... ");
+        LoginResponse response = new LoginResponse();
+
+        try {
+            if (request == null) {
+                logger.error(logPrefix + "returning with failure status on null LoginRequest");
+                response.setStatus("FAILED");
+                return response;
+            }
+            if (request.getEmail() == null) {
+                logger.error(logPrefix + "returning with failure status on null email");
+                response.setStatus("FAILED");
+                return response;
+            }
+            request.email = request.email.trim();
+
+            MessageContext ctx = MessageContext.getCurrentMessageContext();
+            HttpServletRequest httpServletRequest = (HttpServletRequest) ctx.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
+            if (httpServletRequest == null) {
+                logger.error(logPrefix + "returning with failure status on null httpServletRequest");
+                response.setStatus("FAILED");
+                return response;
+            }
+            String currentUserIPAddress = null;
+
+            if (httpServletRequest.getHeader("X-Forwarded-For") != null) {
+                currentUserIPAddress = httpServletRequest.getHeader("X-Forwarded-For");
+            } else {
+                logger.warn(logPrefix + "cannot find X-Forwarded-For header, this field is required for proper IP auditing");
+                currentUserIPAddress = httpServletRequest.getRemoteAddr();
+                logger.warn(logPrefix + "found currentUserIPAddress from httpServletRequest.getRemoteAddr() :" + currentUserIPAddress);
+            }
+            // All data is evil!
+            Validator validator = ESAPI.validator();
+
+            String email = request.getEmail().trim();
+            boolean emailstatus = validator.isValidInput("userInput", email, "Email", 100 , false);
+            if (!emailstatus) {
+                logger.error(logPrefix + "returning with failure status on invalid email (in quotes): '" + email +  "'");
+                response.setStatus("FAILED");
+                return response;
+            }
+
+            String creds = "";
+            // handle unicode escaped chars that were sent that way for '@' etc
+            if (request.getCredentials().contains("u00")) {
+                String uu = request.getCredentials();
+                String uut = uu.replaceAll("u00", "\\\\u00");
+                creds = StringEscapeUtils.unescapeJava(uut); 
+            } else {
+                creds = request.getCredentials(); 
+                if (logger.isTraceEnabled()) { 
+                   logger.trace(logPrefix + "found creds: " +creds); 
+                }
+            }
+            // passwords require special char's ... just do some minimal validation
+            boolean credentialsstatus = RequestAndResponseValidatorFilter.validate(creds);
+            if (!credentialsstatus || creds.length() > 100) {
+                logger.error(logPrefix + "returning with failure status, credentials failed validation, credentialsstatus: " + credentialsstatus + " , length: " + creds.length());
+                response.setStatus("FAILED");
+
+                return response;
+            }
+
+            LoginDTO loginDTO = null;
+            try {
+                loginDTO = wssecutils.findUserByEmail(email);
+            } catch (Exception ex) {
+                logger.error(logPrefix + "cannot create LoginDTO from email: " + email + " , " + ex.getMessage(), ex);
+                response.setStatus("FAILED");
+                return response;
+            }
+
+            if (loginDTO == null) {
+                logger.error(logPrefix + "returning with failure status on failed creation of LoginDTO from email: " + email);
+                response.setStatus("FAILED");
+                return response;
+            }
+
+            logger.warn(logPrefix + "found loginDTO: " + loginDTO.toString());
+
+            response.setUuid(uuid);
+            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(email, creds);
+
+            logger.warn(logPrefix
+                    + "calling authenticate(authRequest) with username: " + email);
+
+            boolean hasFailedLogin = false;
+            String failedStr = "";
+            try {
+                // will throw an Exception if it fails
+                DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
+                daoAuthenticationProvider.setUserDetailsService(springSecurityDAOImpl);
+                daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
+                Authentication authResult = daoAuthenticationProvider.authenticate(authRequest);
+                logger.warn(logPrefix + "authenticate(authRequest) completed successfully with username: " + email);
+            } catch (Exception ex) {
+                if (ex.getMessage() == null) {
+                    failedStr = "Authentication Exception failed state is undefined";
+                } else {
+                    failedStr = ex.getMessage();
+                }
+                logger.error(logPrefix + "failed: " + failedStr, ex);
+                hasFailedLogin = true;
+            }
+
+            if (hasFailedLogin) {
+                logger.error(logPrefix + "returning with failure status on failed login");
+                response.setStatus("LOGIN FAILED");
+                return response;
+            }
+
+
+            if (!generateTokenForReturn(httpServletRequest, request, response, currentUserIPAddress, email, uuid)) {
+                logger.warn(logPrefix + "generateTokenForReturn() failed, goodbye");
+                response.setStatus("TOKEN GENERION FAILED");
+            }
+
+            return response;
+
+        } catch (Exception ex) {
+            logger.error(logPrefix + "failed: " + ex.getMessage(), ex);
+            response.setStatus("FAILED");
+            return response;
+        }
+
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    private boolean generateTokenForReturn(HttpServletRequest httpServletRequest, LoginRequest request, LoginResponse response, String currentUserIPAddress, String email, String uuid) {
+
+        String logPrefix = "LoginService.generateTokenForReturn() , "
+                + " , uuid: " + uuid + " , ";
+
+        try {
+            String token = null;
+            
+            // JWT and JWE are specifications to generate and validate tokens 
+            // securely, however they require a public / private key pair using
+            // elliptic curve cryptography and that is beyond the scope of this
+            // userguide.
+            // See below:
+            // https://datatracker.ietf.org/doc/html/rfc7516
+            // https://datatracker.ietf.org/doc/html/rfc7519
+
+            // this is an example only for demo purposes - do not use this for 
+            // production code
+            token = RandomStringUtils.randomAlphanumeric(20);
+
+            response.setStatus("OK");
+            response.setToken(token);
+            
+            return true;
+
+        } catch (Exception ex) {
+            logger.error(logPrefix + "failed: " + ex.getMessage(), ex);
+            response.setStatus("FAILED");
+            return false;
+        }
+
+    }
+
+
+}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/resources/ESAPI.properties b/modules/samples/userguide/src/userguide/springbootdemo/src/main/resources/ESAPI.properties
new file mode 100644
index 0000000..710a84e
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/resources/ESAPI.properties
@@ -0,0 +1,461 @@
+#
+# OWASP Enterprise Security API (ESAPI) Properties file -- PRODUCTION Version
+# 
+# This file is part of the Open Web Application Security Project (OWASP)
+# Enterprise Security API (ESAPI) project. For details, please see
+# http://www.owasp.org/index.php/ESAPI.
+#
+# Copyright (c) 2008,2009 - The OWASP Foundation
+#
+# DISCUSS: This may cause a major backwards compatibility issue, etc. but
+#		   from a name space perspective, we probably should have prefaced
+#		   all the property names with ESAPI or at least OWASP. Otherwise
+#		   there could be problems is someone loads this properties file into
+#		   the System properties.  We could also put this file into the
+#		   esapi.jar file (perhaps as a ResourceBundle) and then allow an external
+#		   ESAPI properties be defined that would overwrite these defaults.
+#		   That keeps the application's properties relatively simple as usually
+#		   they will only want to override a few properties. If looks like we
+#		   already support multiple override levels of this in the
+#		   DefaultSecurityConfiguration class, but I'm suggesting placing the
+#		   defaults in the esapi.jar itself. That way, if the jar is signed,
+#		   we could detect if those properties had been tampered with. (The
+#		   code to check the jar signatures is pretty simple... maybe 70-90 LOC,
+#		   but off course there is an execution penalty (similar to the way
+#		   that the separate sunjce.jar used to be when a class from it was
+#		   first loaded). Thoughts?
+###############################################################################
+#
+# WARNING: Operating system protection should be used to lock down the .esapi
+# resources directory and all the files inside and all the directories all the
+# way up to the root directory of the file system.  Note that if you are using
+# file-based implementations, that some files may need to be read-write as they
+# get updated dynamically.
+#
+# Before using, be sure to update the MasterKey and MasterSalt as described below.
+# N.B.: If you had stored data that you have previously encrypted with ESAPI 1.4,
+#		you *must* FIRST decrypt it using ESAPI 1.4 and then (if so desired)
+#		re-encrypt it with ESAPI 2.0. If you fail to do this, you will NOT be
+#		able to decrypt your data with ESAPI 2.0.
+#
+#		YOU HAVE BEEN WARNED!!! More details are in the ESAPI 2.0 Release Notes.
+#
+#===========================================================================
+# ESAPI Configuration
+#
+# If true, then print all the ESAPI properties set here when they are loaded.
+# If false, they are not printed. Useful to reduce output when running JUnit tests.
+# If you need to troubleshoot a properties related problem, turning this on may help.
+# This is 'false' in the src/test/resources/.esapi version. It is 'true' by
+# default for reasons of backward compatibility with earlier ESAPI versions.
+ESAPI.printProperties=true
+
+# ESAPI is designed to be easily extensible. You can use the reference implementation
+# or implement your own providers to take advantage of your enterprise's security
+# infrastructure. The functions in ESAPI are referenced using the ESAPI locator, like:
+#
+#    String ciphertext =
+#		ESAPI.encryptor().encrypt("Secret message");   // Deprecated in 2.0
+#    CipherText cipherText =
+#		ESAPI.encryptor().encrypt(new PlainText("Secret message")); // Preferred
+#
+# Below you can specify the classname for the provider that you wish to use in your
+# application. The only requirement is that it implement the appropriate ESAPI interface.
+# This allows you to switch security implementations in the future without rewriting the
+# entire application.
+#
+# ExperimentalAccessController requires ESAPI-AccessControlPolicy.xml in .esapi directory
+ESAPI.AccessControl=org.owasp.esapi.reference.DefaultAccessController
+# FileBasedAuthenticator requires users.txt file in .esapi directory
+ESAPI.Authenticator=org.owasp.esapi.reference.FileBasedAuthenticator
+ESAPI.Encoder=org.owasp.esapi.reference.DefaultEncoder
+ESAPI.Encryptor=org.owasp.esapi.reference.crypto.JavaEncryptor
+
+ESAPI.Executor=org.owasp.esapi.reference.DefaultExecutor
+ESAPI.HTTPUtilities=org.owasp.esapi.reference.DefaultHTTPUtilities
+ESAPI.IntrusionDetector=org.owasp.esapi.reference.DefaultIntrusionDetector
+ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory
+
+ESAPI.Randomizer=org.owasp.esapi.reference.DefaultRandomizer
+ESAPI.Validator=org.owasp.esapi.reference.DefaultValidator
+
+#===========================================================================
+# ESAPI Authenticator
+#
+Authenticator.AllowedLoginAttempts=3
+Authenticator.MaxOldPasswordHashes=13
+Authenticator.UsernameParameterName=username
+Authenticator.PasswordParameterName=password
+# RememberTokenDuration (in days)
+Authenticator.RememberTokenDuration=14
+# Session Timeouts (in minutes)
+Authenticator.IdleTimeoutDuration=20
+Authenticator.AbsoluteTimeoutDuration=120
+
+#===========================================================================
+# ESAPI Encoder
+#
+# ESAPI canonicalizes input before validation to prevent bypassing filters with encoded attacks.
+# Failure to canonicalize input is a very common mistake when implementing validation schemes.
+# Canonicalization is automatic when using the ESAPI Validator, but you can also use the
+# following code to canonicalize data.
+#
+#      ESAPI.Encoder().canonicalize( "%22hello world&#x22;" );
+#  
+# Multiple encoding is when a single encoding format is applied multiple times. Allowing
+# multiple encoding is strongly discouraged.
+Encoder.AllowMultipleEncoding=false
+
+# Mixed encoding is when multiple different encoding formats are applied, or when 
+# multiple formats are nested. Allowing multiple encoding is strongly discouraged.
+Encoder.AllowMixedEncoding=false
+
+# The default list of codecs to apply when canonicalizing untrusted data. The list should include the codecs
+# for all downstream interpreters or decoders. For example, if the data is likely to end up in a URL, HTML, or
+# inside JavaScript, then the list of codecs below is appropriate. The order of the list is not terribly important.
+Encoder.DefaultCodecList=HTMLEntityCodec,PercentCodec,JavaScriptCodec
+
+
+#===========================================================================
+# ESAPI Encryption
+#
+# The ESAPI Encryptor provides basic cryptographic functions with a simplified API.
+# To get started, generate a new key using java -classpath esapi.jar org.owasp.esapi.reference.crypto.JavaEncryptor
+# There is not currently any support for key rotation, so be careful when changing your key and salt as it
+# will invalidate all signed, encrypted, and hashed data.
+#
+# WARNING: Not all combinations of algorithms and key lengths are supported.
+# If you choose to use a key length greater than 128, you MUST download the
+# unlimited strength policy files and install in the lib directory of your JRE/JDK.
+# See http://java.sun.com/javase/downloads/index.jsp for more information.
+#
+# Backward compatibility with ESAPI Java 1.4 is supported by the two deprecated API
+# methods, Encryptor.encrypt(String) and Encryptor.decrypt(String). However, whenever
+# possible, these methods should be avoided as they use ECB cipher mode, which in almost
+# all circumstances a poor choice because of it's weakness. CBC cipher mode is the default
+# for the new Encryptor encrypt / decrypt methods for ESAPI Java 2.0.  In general, you
+# should only use this compatibility setting if you have persistent data encrypted with
+# version 1.4 and even then, you should ONLY set this compatibility mode UNTIL
+# you have decrypted all of your old encrypted data and then re-encrypted it with
+# ESAPI 2.0 using CBC mode. If you have some reason to mix the deprecated 1.4 mode
+# with the new 2.0 methods, make sure that you use the same cipher algorithm for both
+# (256-bit AES was the default for 1.4; 128-bit is the default for 2.0; see below for
+# more details.) Otherwise, you will have to use the new 2.0 encrypt / decrypt methods
+# where you can specify a SecretKey. (Note that if you are using the 256-bit AES,
+# that requires downloading the special jurisdiction policy files mentioned above.)
+#
+#		***** IMPORTANT: Do NOT forget to replace these with your own values! *****
+# To calculate these values, you can run:
+#		java -classpath esapi.jar org.owasp.esapi.reference.crypto.JavaEncryptor
+#
+#Encryptor.MasterKey=
+#Encryptor.MasterSalt=
+
+# Provides the default JCE provider that ESAPI will "prefer" for its symmetric
+# encryption and hashing. (That is it will look to this provider first, but it
+# will defer to other providers if the requested algorithm is not implemented
+# by this provider.) If left unset, ESAPI will just use your Java VM's current
+# preferred JCE provider, which is generally set in the file
+# "$JAVA_HOME/jre/lib/security/java.security".
+#
+# The main intent of this is to allow ESAPI symmetric encryption to be
+# used with a FIPS 140-2 compliant crypto-module. For details, see the section
+# "Using ESAPI Symmetric Encryption with FIPS 140-2 Cryptographic Modules" in
+# the ESAPI 2.0 Symmetric Encryption User Guide, at:
+# http://owasp-esapi-java.googlecode.com/svn/trunk/documentation/esapi4java-core-2.0-symmetric-crypto-user-guide.html
+# However, this property also allows you to easily use an alternate JCE provider
+# such as "Bouncy Castle" without having to make changes to "java.security".
+# See Javadoc for SecurityProviderLoader for further details. If you wish to use
+# a provider that is not known to SecurityProviderLoader, you may specify the
+# fully-qualified class name of the JCE provider class that implements
+# java.security.Provider. If the name contains a '.', this is interpreted as
+# a fully-qualified class name that implements java.security.Provider.
+#
+# NOTE: Setting this property has the side-effect of changing it in your application
+#       as well, so if you are using JCE in your application directly rather than
+#       through ESAPI (you wouldn't do that, would you? ;-), it will change the
+#       preferred JCE provider there as well.
+#
+# Default: Keeps the JCE provider set to whatever JVM sets it to.
+Encryptor.PreferredJCEProvider=
+
+# AES is the most widely used and strongest encryption algorithm. This
+# should agree with your Encryptor.CipherTransformation property.
+# By default, ESAPI Java 1.4 uses "PBEWithMD5AndDES" and which is
+# very weak. It is essentially a password-based encryption key, hashed
+# with MD5 around 1K times and then encrypted with the weak DES algorithm
+# (56-bits) using ECB mode and an unspecified padding (it is
+# JCE provider specific, but most likely "NoPadding"). However, 2.0 uses
+# "AES/CBC/PKCSPadding". If you want to change these, change them here.
+# Warning: This property does not control the default reference implementation for
+#		   ESAPI 2.0 using JavaEncryptor. Also, this property will be dropped
+#		   in the future.
+# @deprecated
+Encryptor.EncryptionAlgorithm=AES
+#		For ESAPI Java 2.0 - New encrypt / decrypt methods use this.
+Encryptor.CipherTransformation=AES/CBC/PKCS5Padding
+
+# Applies to ESAPI 2.0 and later only!
+# Comma-separated list of cipher modes that provide *BOTH*
+# confidentiality *AND* message authenticity. (NIST refers to such cipher
+# modes as "combined modes" so that's what we shall call them.) If any of these
+# cipher modes are used then no MAC is calculated and stored
+# in the CipherText upon encryption. Likewise, if one of these
+# cipher modes is used with decryption, no attempt will be made
+# to validate the MAC contained in the CipherText object regardless
+# of whether it contains one or not. Since the expectation is that
+# these cipher modes support support message authenticity already,
+# injecting a MAC in the CipherText object would be at best redundant.
+#
+# Note that as of JDK 1.5, the SunJCE provider does not support *any*
+# of these cipher modes. Of these listed, only GCM and CCM are currently
+# NIST approved. YMMV for other JCE providers. E.g., Bouncy Castle supports
+# GCM and CCM with "NoPadding" mode, but not with "PKCS5Padding" or other
+# padding modes.
+Encryptor.cipher_modes.combined_modes=GCM,CCM,IAPM,EAX,OCB,CWC
+
+# Applies to ESAPI 2.0 and later only!
+# Additional cipher modes allowed for ESAPI 2.0 encryption. These
+# cipher modes are in _addition_ to those specified by the property
+# 'Encryptor.cipher_modes.combined_modes'.
+# Note: We will add support for streaming modes like CFB & OFB once
+# we add support for 'specified' to the property 'Encryptor.ChooseIVMethod'
+# (probably in ESAPI 2.1).
+# DISCUSS: Better name?
+Encryptor.cipher_modes.additional_allowed=CBC
+
+# 128-bit is almost always sufficient and appears to be more resistant to
+# related key attacks than is 256-bit AES. Use '_' to use default key size
+# for cipher algorithms (where it makes sense because the algorithm supports
+# a variable key size). Key length must agree to what's provided as the
+# cipher transformation, otherwise this will be ignored after logging a
+# warning.
+#
+# NOTE: This is what applies BOTH ESAPI 1.4 and 2.0. See warning above about mixing!
+Encryptor.EncryptionKeyLength=128
+
+# Because 2.0 uses CBC mode by default, it requires an initialization vector (IV).
+# (All cipher modes except ECB require an IV.) There are two choices: we can either
+# use a fixed IV known to both parties or allow ESAPI to choose a random IV. While
+# the IV does not need to be hidden from adversaries, it is important that the
+# adversary not be allowed to choose it. Also, random IVs are generally much more
+# secure than fixed IVs. (In fact, it is essential that feed-back cipher modes
+# such as CFB and OFB use a different IV for each encryption with a given key so
+# in such cases, random IVs are much preferred. By default, ESAPI 2.0 uses random
+# IVs. If you wish to use 'fixed' IVs, set 'Encryptor.ChooseIVMethod=fixed' and
+# uncomment the Encryptor.fixedIV.
+#
+# Valid values:		random|fixed|specified		'specified' not yet implemented; planned for 2.1
+Encryptor.ChooseIVMethod=random
+# If you choose to use a fixed IV, then you must place a fixed IV here that
+# is known to all others who are sharing your secret key. The format should
+# be a hex string that is the same length as the cipher block size for the
+# cipher algorithm that you are using. The following is an *example* for AES
+# from an AES test vector for AES-128/CBC as described in:
+# NIST Special Publication 800-38A (2001 Edition)
+# "Recommendation for Block Cipher Modes of Operation".
+# (Note that the block size for AES is 16 bytes == 128 bits.)
+#
+Encryptor.fixedIV=0x000102030405060708090a0b0c0d0e0f
+
+# Whether or not CipherText should use a message authentication code (MAC) with it.
+# This prevents an adversary from altering the IV as well as allowing a more
+# fool-proof way of determining the decryption failed because of an incorrect
+# key being supplied. This refers to the "separate" MAC calculated and stored
+# in CipherText, not part of any MAC that is calculated as a result of a
+# "combined mode" cipher mode.
+#
+# If you are using ESAPI with a FIPS 140-2 cryptographic module, you *must* also
+# set this property to false.
+Encryptor.CipherText.useMAC=true
+
+# Whether or not the PlainText object may be overwritten and then marked
+# eligible for garbage collection. If not set, this is still treated as 'true'.
+Encryptor.PlainText.overwrite=true
+
+# Do not use DES except in a legacy situations. 56-bit is way too small key size.
+#Encryptor.EncryptionKeyLength=56
+#Encryptor.EncryptionAlgorithm=DES
+
+# TripleDES is considered strong enough for most purposes.
+#	Note:	There is also a 112-bit version of DESede. Using the 168-bit version
+#			requires downloading the special jurisdiction policy from Sun.
+#Encryptor.EncryptionKeyLength=168
+#Encryptor.EncryptionAlgorithm=DESede
+
+Encryptor.HashAlgorithm=SHA-512
+Encryptor.HashIterations=1024
+Encryptor.DigitalSignatureAlgorithm=SHA1withDSA
+Encryptor.DigitalSignatureKeyLength=1024
+Encryptor.RandomAlgorithm=SHA1PRNG
+Encryptor.CharacterEncoding=UTF-8
+
+# This is the Pseudo Random Function (PRF) that ESAPI's Key Derivation Function
+# (KDF) normally uses. Note this is *only* the PRF used for ESAPI's KDF and
+# *not* what is used for ESAPI's MAC. (Currently, HmacSHA1 is always used for
+# the MAC, mostly to keep the overall size at a minimum.)
+#
+# Currently supported choices for JDK 1.5 and 1.6 are:
+#	HmacSHA1 (160 bits), HmacSHA256 (256 bits), HmacSHA384 (384 bits), and
+#	HmacSHA512 (512 bits).
+# Note that HmacMD5 is *not* supported for the PRF used by the KDF even though
+# the JDKs support it.  See the ESAPI 2.0 Symmetric Encryption User Guide
+# further details.
+Encryptor.KDF.PRF=HmacSHA256
+#===========================================================================
+# ESAPI HttpUtilties
+#
+# The HttpUtilities provide basic protections to HTTP requests and responses. Primarily these methods 
+# protect against malicious data from attackers, such as unprintable characters, escaped characters,
+# and other simple attacks. The HttpUtilities also provides utility methods for dealing with cookies,
+# headers, and CSRF tokens.
+#
+# Default file upload location (remember to escape backslashes with \\)
+# HttpUtilities.UploadDir=C:\\ESAPI\\testUpload
+# HttpUtilities.UploadTempDir=C:\\temp
+# Force flags on cookies, if you use HttpUtilities to set cookies
+HttpUtilities.ForceHttpOnlySession=false
+HttpUtilities.ForceSecureSession=false
+HttpUtilities.ForceHttpOnlyCookies=true
+HttpUtilities.ForceSecureCookies=true
+# Maximum size of HTTP headers
+HttpUtilities.MaxHeaderSize=4096
+# File upload configuration
+HttpUtilities.ApprovedUploadExtensions=.zip,.pdf,.doc,.docx,.ppt,.pptx,.tar,.gz,.tgz,.rar,.war,.jar,.ear,.xls,.rtf,.properties,.java,.class,.txt,.xml,.jsp,.jsf,.exe,.dll
+HttpUtilities.MaxUploadFileBytes=500000000
+# Using UTF-8 throughout your stack is highly recommended. That includes your database driver,
+# container, and any other technologies you may be using. Failure to do this may expose you
+# to Unicode transcoding injection attacks. Use of UTF-8 does not hinder internationalization.
+HttpUtilities.ResponseContentType=text/html; charset=UTF-8
+# This is the name of the cookie used to represent the HTTP session
+# Typically this will be the default "JSESSIONID" 
+HttpUtilities.HttpSessionIdName=JSESSIONID
+
+
+
+#===========================================================================
+# ESAPI Executor
+# CHECKME - This should be made OS independent. Don't use unsafe defaults.
+# # Examples only -- do NOT blindly copy!
+#   For Windows:
+#     Executor.WorkingDirectory=C:\\Windows\\Temp
+#     Executor.ApprovedExecutables=C:\\Windows\\System32\\cmd.exe,C:\\Windows\\System32\\runas.exe
+#   For *nux, MacOS:
+#     Executor.WorkingDirectory=/tmp
+#     Executor.ApprovedExecutables=/bin/bash
+Executor.WorkingDirectory=
+Executor.ApprovedExecutables=
+
+
+#===========================================================================
+# ESAPI Logging
+# Set the application name if these logs are combined with other applications
+Logger.ApplicationName=DPT
+# If you use an HTML log viewer that does not properly HTML escape log data, you can set LogEncodingRequired to true
+Logger.LogEncodingRequired=false
+# Determines whether ESAPI should log the application name. This might be clutter in some single-server/single-app environments.
+Logger.LogApplicationName=true
+# Determines whether ESAPI should log the server IP and port. This might be clutter in some single-server environments.
+Logger.LogServerIP=true
+# Determines whether ESAPI should log the user info.
+Logger.UserInfo=true
+# Determines whether ESAPI should log the session id and client IP.
+Logger.ClientInfo=true
+
+
+#===========================================================================
+# ESAPI Intrusion Detection
+#
+# Each event has a base to which .count, .interval, and .action are added
+# The IntrusionException will fire if we receive "count" events within "interval" seconds
+# The IntrusionDetector is configurable to take the following actions: log, logout, and disable
+#  (multiple actions separated by commas are allowed e.g. event.test.actions=log,disable
+#
+# Custom Events
+# Names must start with "event." as the base
+# Use IntrusionDetector.addEvent( "test" ) in your code to trigger "event.test" here
+# You can also disable intrusion detection completely by changing
+# the following parameter to true
+#
+IntrusionDetector.Disable=false
+#
+IntrusionDetector.event.test.count=2
+IntrusionDetector.event.test.interval=10
+IntrusionDetector.event.test.actions=disable,log
+
+# Exception Events
+# All EnterpriseSecurityExceptions are registered automatically
+# Call IntrusionDetector.getInstance().addException(e) for Exceptions that do not extend EnterpriseSecurityException
+# Use the fully qualified classname of the exception as the base
+
+# any intrusion is an attack
+IntrusionDetector.org.owasp.esapi.errors.IntrusionException.count=1
+IntrusionDetector.org.owasp.esapi.errors.IntrusionException.interval=1
+IntrusionDetector.org.owasp.esapi.errors.IntrusionException.actions=log,disable,logout
+
+# for test purposes
+# CHECKME: Shouldn't there be something in the property name itself that designates
+#		   that these are for testing???
+IntrusionDetector.org.owasp.esapi.errors.IntegrityException.count=10
+IntrusionDetector.org.owasp.esapi.errors.IntegrityException.interval=5
+IntrusionDetector.org.owasp.esapi.errors.IntegrityException.actions=log,disable,logout
+
+# rapid validation errors indicate scans or attacks in progress
+# org.owasp.esapi.errors.ValidationException.count=10
+# org.owasp.esapi.errors.ValidationException.interval=10
+# org.owasp.esapi.errors.ValidationException.actions=log,logout
+
+# sessions jumping between hosts indicates session hijacking
+IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.count=2
+IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.interval=10
+IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.actions=log,logout
+
+
+#===========================================================================
+# ESAPI Validation
+#
+# The ESAPI Validator works on regular expressions with defined names. You can define names
+# either here, or you may define application specific patterns in a separate file defined below.
+# This allows enterprises to specify both organizational standards as well as application specific
+# validation rules.
+#
+Validator.ConfigurationFile=validation.properties
+
+# Validators used by ESAPI
+Validator.AccountName=^[a-zA-Z0-9]{3,20}$
+Validator.SystemCommand=^[a-zA-Z\\-\\/]{1,64}$
+Validator.RoleName=^[a-z]{1,20}$
+
+#the word TEST below should be changed to your application 
+#name - only relative URL's are supported
+Validator.Redirect=^\\/test.*$
+
+# Global HTTP Validation Rules
+# Values with Base64 encoded data (e.g. encrypted state) will need at least [a-zA-Z0-9\/+=]
+Validator.HTTPScheme=^(http|https)$
+Validator.HTTPServerName=^[a-zA-Z0-9_.\\-]*$
+Validator.HTTPParameterName=^[a-zA-Z0-9_]{1,32}$
+Validator.HTTPParameterValue=^[a-zA-Z0-9.\\-\\/+=@_,:\\\\ ]*$
+Validator.HTTPParameterTransactionValue=^[a-zA-Z0-9.\\-\\/+=@_<>:\\"\\-, ]*$
+Validator.HTTPCookieName=^[a-zA-Z0-9\\-_]{1,32}$
+Validator.HTTPCookieValue=^[a-zA-Z0-9\\-\\/+=_ ]*$
+Validator.HTTPHeaderName=^[a-zA-Z0-9\\-_]{1,32}$
+Validator.HTTPHeaderValue=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ ]*$
+Validator.HTTPContextPath=^\\/?[a-zA-Z0-9.\\-\\/_]*$
+Validator.HTTPServletPath=^[a-zA-Z0-9.\\-\\/_]*$
+Validator.HTTPPath=^[a-zA-Z0-9.\\-_]*$
+Validator.HTTPQueryString=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ %]*$
+Validator.HTTPURI=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ ]*$
+Validator.HTTPURL=^.*$
+Validator.HTTPJSESSIONID=^[A-Z0-9]{10,30}$
+Validator.SafeString=^[.\\p{Alnum}\\p{Space}]{0,1024}$
+Validator.Email=^[A-Za-z0-9._%'\\-+]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$
+Validator.IPAddress=^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
+
+# Validation of file related input
+Validator.FileName=^[a-zA-Z0-9!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$
+Validator.DirectoryName=^[a-zA-Z0-9:/\\\\!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$
+
+# Validation of dates. Controls whether or not 'lenient' dates are accepted.
+# See DataFormat.setLenient(boolean flag) for further details.
+Validator.AcceptLenientDates=false
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/resources/application.properties b/modules/samples/userguide/src/userguide/springbootdemo/src/main/resources/application.properties
new file mode 100644
index 0000000..b59217d
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/resources/application.properties
@@ -0,0 +1,2 @@
+requestDebuggingActivated=1
+spring.main.allow-bean-definition-overriding=true
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/resources/esapi-java-logging.properties b/modules/samples/userguide/src/userguide/springbootdemo/src/main/resources/esapi-java-logging.properties
new file mode 100644
index 0000000..c5f619b
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/resources/esapi-java-logging.properties
@@ -0,0 +1,6 @@
+handlers= java.util.logging.ConsoleHandler
+.level= INFO
+java.util.logging.ConsoleHandler.level = INFO
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%3$-7s] %5$s %n
+#https://www.logicbig.com/tutorials/core-java-tutorial/logging/customizing-default-format.html
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/resources/log4j2.xml b/modules/samples/userguide/src/userguide/springbootdemo/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..fe37cbd
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/resources/log4j2.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="warn" name="MyApp" packages="">
+    <Appenders>
+        <Console name="Console" target="SYSTEM_OUT">
+            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
+        </Console>
+        <RollingFile name="RollingFile" fileName="axis2-json-api.log"
+                     filePattern="axis2-json-api-%d{MM-dd-yyyy}-%i.log">
+            <PatternLayout>
+                <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
+            </PatternLayout>
+            <Policies>
+                <TimeBasedTriggeringPolicy />
+                <SizeBasedTriggeringPolicy size="20 MB"/>
+            </Policies>
+            <DefaultRolloverStrategy max="20"/>
+        </RollingFile>
+    </Appenders>
+    <Loggers>
+        <Logger name="userguide.springboot" level="debug" additivity="false" >
+            <AppenderRef ref="RollingFile"/>
+            <AppenderRef ref="Console"/>
+        </Logger>
+        <Logger name="org.apache" level="warn" additivity="false" >
+            <AppenderRef ref="RollingFile"/>
+            <AppenderRef ref="Console"/>
+        </Logger>
+        <Logger name="org.apache.axis2" level="warn" additivity="false" >
+            <AppenderRef ref="RollingFile"/>
+            <AppenderRef ref="Console"/>
+        </Logger>
+        <Logger name="org.springframework" level="warn" additivity="false" >
+            <AppenderRef ref="RollingFile"/>
+            <AppenderRef ref="Console"/>
+        </Logger>
+        <Root level="debug">
+            <AppenderRef ref="RollingFile"/>
+        </Root>
+    </Loggers>
+</Configuration>
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/modules/samples/userguide/src/userguide/springbootdemo/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
new file mode 100644
index 0000000..6840eea
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
@@ -0,0 +1,13 @@
+<jboss-deployment-structure>
+    <deployment>
+        <exclude-subsystems>
+            <subsystem name="jaxrs" />
+        </exclude-subsystems>
+        <exclusions>
+            <module name="org.apache.log4j" /> <module name="org.apache.commons.logging" />
+        </exclusions>
+        <dependencies> 
+            <module name="jdk.unsupported" slot="main" export="true" />
+        </dependencies>
+    </deployment>
+</jboss-deployment-structure>
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/webapp/WEB-INF/jboss-web.xml b/modules/samples/userguide/src/userguide/springbootdemo/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100755
index 0000000..4259d75
--- /dev/null
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>                                                                                                                                                               
+<!DOCTYPE jboss-web PUBLIC                                                                                                                                                          
+   "-//JBoss//DTD Web Application 5.0//EN"                                                                                                                                          
+   "http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd">                                                                                                                               
+<!-- force JBoss home page to the one and only war file that has this file defined on each server.
+     There can only be one root context per server.
+-->
+<jboss-web>
+ <!--deleteThisCommentForRootContext <context-root>/</context-root> deleteThisCommentForRootContext-->
+</jboss-web>
diff --git a/modules/webapp/src/main/webapp/WEB-INF/include/footer.inc b/modules/webapp/src/main/webapp/WEB-INF/include/footer.inc
index da9e51d..de42cb3 100644
--- a/modules/webapp/src/main/webapp/WEB-INF/include/footer.inc
+++ b/modules/webapp/src/main/webapp/WEB-INF/include/footer.inc
@@ -31,7 +31,7 @@
 				</tr>
 				<tr>
 					<td align="center">
-					Copyright &#169; 1999-2006, The Apache Software Foundation<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.
+					Copyright &#169; 1999-2021, The Apache Software Foundation<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.
 					</td>
 				</tr>
 			</table>
diff --git a/modules/webapp/src/main/webapp/axis2-web/Error/GenError.html b/modules/webapp/src/main/webapp/axis2-web/Error/GenError.html
index 748fbb2..de5355d 100644
--- a/modules/webapp/src/main/webapp/axis2-web/Error/GenError.html
+++ b/modules/webapp/src/main/webapp/axis2-web/Error/GenError.html
@@ -41,4 +41,4 @@
    </tr>

 </table>

  </body>

-</html>
\ No newline at end of file
+</html>

diff --git a/modules/webapp/src/main/webapp/axis2-web/Error/error404.jsp b/modules/webapp/src/main/webapp/axis2-web/Error/error404.jsp
index b57fc76..c64576b 100644
--- a/modules/webapp/src/main/webapp/axis2-web/Error/error404.jsp
+++ b/modules/webapp/src/main/webapp/axis2-web/Error/error404.jsp
@@ -51,7 +51,7 @@
         <table summary="embedded footer table">
           <tr><td><hr size="1" noshade="noshade"></td></tr>
           <tr>
-            <td align="center">Copyright &#169; 1999-2006, The Apache Software Foundation<br>Licensed under the <a
+            <td align="center">Copyright &#169; 1999-2021, The Apache Software Foundation<br>Licensed under the <a
               href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</td>
           </tr>
         </table>
diff --git a/modules/webapp/src/main/webapp/axis2-web/Error/error500.jsp b/modules/webapp/src/main/webapp/axis2-web/Error/error500.jsp
index 696c95f..886f55d 100644
--- a/modules/webapp/src/main/webapp/axis2-web/Error/error500.jsp
+++ b/modules/webapp/src/main/webapp/axis2-web/Error/error500.jsp
@@ -52,7 +52,7 @@
         <table summary="embedded footer table">
           <tr><td><hr></td></tr>
           <tr>
-            <td style="align: center">Copyright &#169; 1999-2006, The Apache Software Foundation<br>Licensed under the <a
+            <td style="align: center">Copyright &#169; 1999-2021, The Apache Software Foundation<br>Licensed under the <a
               href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</td>
           </tr>
         </table>
diff --git a/src/site/xdoc/docs/userguide.xml b/src/site/xdoc/docs/userguide.xml
index 551d92b..c9a130c 100644
--- a/src/site/xdoc/docs/userguide.xml
+++ b/src/site/xdoc/docs/userguide.xml
@@ -35,8 +35,10 @@
 use Axis2 to create and deploy Web services as well as how to use

 WSDL to generate both clients and services.</p>

 For experienced users of Apache Axis2, we recommend the <a href=

-"adv-userguide.html">Advanced User's Guide.</a> <a name="intro" id=

-"intro"></a>

+"adv-userguide.html">Advanced User's Guide.</a> 

+For users of JSON and Spring Boot, see the sample application in the <a href=

+"json-springboot-userguide.html">JSON and Spring Boot User's Guide.</a> 

+<a name="intro" id= "intro"></a>

 <h1>Introducing Axis2</h1>

 <p>This section introduces Axis2 and its structure, including an

 explanation of various directories/files included in the latest