AXIS2-6006, json-springboot-userguide completed first pass
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/pom.xml b/modules/samples/userguide/src/userguide/springbootdemo/pom.xml
index 85b9037..731fdec 100644
--- a/modules/samples/userguide/src/userguide/springbootdemo/pom.xml
+++ b/modules/samples/userguide/src/userguide/springbootdemo/pom.xml
@@ -340,8 +340,8 @@
<!-- 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/LoginTokenizer.aar">
- <metainf file="resources-axis2/login_tokenizer_resources/services.xml"/>
+ <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"/>
@@ -352,8 +352,8 @@
</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/LoginTokenizer.aar">
- <metainf file="resources-axis2/login_tokenizer_resources/services.xml"/>
+ <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"/>
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/login_tokenizer_resources/services.xml b/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/login_resources/services.xml
similarity index 89%
rename from modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/login_tokenizer_resources/services.xml
rename to modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/login_resources/services.xml
index 952ac49..64812c7 100755
--- a/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/login_tokenizer_resources/services.xml
+++ b/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/login_resources/services.xml
@@ -16,12 +16,12 @@
~ specific language governing permissions and limitations
~ under the License.
-->
-<service name="loginTokenizerService">
+<service name="loginService">
<description>
- Alpha Theory Login Tokenizer Resources
+ Login Resources
</description>
<parameter name="ServiceObjectSupplier">org.apache.axis2.extensions.spring.receivers.SpringServletContextObjectSupplier</parameter>
- <parameter name="SpringBeanName">loginTokenizerService</parameter>
+ <parameter name="SpringBeanName">loginService</parameter>
<operation name="doLogin">
<messageReceivers>
<messageReceiver mep="http://www.w3.org/ns/wsdl/in-out"
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
index 055789d..6a202ff 100755
--- 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
@@ -18,7 +18,7 @@
-->
<service name="testws">
<description>
- Alpha Theory testws Resources
+ testws Resources
</description>
<parameter name="ServiceObjectSupplier">org.apache.axis2.extensions.spring.receivers.SpringServletContextObjectSupplier</parameter>
<parameter name="SpringBeanName">testwsService</parameter>
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
index 38b19d9..7aefd00 100644
--- 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
@@ -122,7 +122,7 @@
public boolean matches(HttpServletRequest request) {
String logPrefix = "AnonRequestMatcher.matches , ";
boolean result = request.getRequestURI().contains(
- "/services/loginTokenizerService");
+ "/services/loginService");
logger.debug(logPrefix
+ "inside AnonRequestMatcher.matches, will return result: "
+ result + " , on request.getRequestURI() : "
@@ -165,7 +165,7 @@
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
- String logPrefix = "SecurityConfigurationTokenWebServices.getAllConfigAttributes , ";
+ String logPrefix = "SecureResouceMetadataSource.getAllConfigAttributes , ";
logger.debug(logPrefix + "returning ROLE_USER ...");
List<ConfigAttribute> attrs = SecurityConfig.createList("ROLE_USER");
return attrs;
@@ -257,7 +257,7 @@
@Override
protected void configure(final HttpSecurity http) throws Exception {
- String logPrefix = "SecurityConfigurationTokenWebServices.configure(final HttpSecurity http) , ";
+ String logPrefix = "StatelessSecurityContextRepository.configure(final HttpSecurity http) , ";
logger.debug(logPrefix + "inside Spring Boot filter config ...");
}
@@ -350,7 +350,7 @@
@Bean(name = "springSecurityFilterChain")
public FilterChainProxy springSecurityFilterChain() throws ServletException, Exception {
- String logPrefix = "SecurityConfigurationTokenWebServices.springSecurityFilterChain , ";
+ String logPrefix = "GenericAccessDecisionManager.springSecurityFilterChain , ";
logger.debug(logPrefix + "inside main filter config ...");
final List<SecurityFilterChain> listOfFilterChains = new ArrayList<SecurityFilterChain>();
@@ -371,7 +371,7 @@
*/
@Bean
FilterRegistrationBean disableWSLoginFilterAutoRegistration(final WSLoginFilter wsLoginFilter) {
- String logPrefix = "SecurityConfigurationLogin.disableWSLoginFilterAutoRegistration , ";
+ String logPrefix = "GenericAccessDecisionManager.disableWSLoginFilterAutoRegistration , ";
logger.debug(logPrefix + "executing registration.setEnabled(false) on wsLoginFilter ...");
final FilterRegistrationBean registration = new FilterRegistrationBean(wsLoginFilter);
registration.setEnabled(false);
@@ -383,7 +383,7 @@
*/
@Bean
FilterRegistrationBean disableJWTAuthenticationFilterAutoRegistration(final JWTAuthenticationFilter filter) {
- String logPrefix = "SecurityConfigurationTokenWebServices.disableJWTAuthenticationFilterAutoRegistration , ";
+ String logPrefix = "GenericAccessDecisionManager.disableJWTAuthenticationFilterAutoRegistration , ";
logger.debug(logPrefix + "executing registration.setEnabled(false) on JWTAuthenticationFilter ...");
final FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
@@ -395,7 +395,7 @@
*/
@Bean
FilterRegistrationBean disableHTTPPostOnlyRejectionFilterAutoRegistration(final HTTPPostOnlyRejectionFilter filter) {
- String logPrefix = "SecurityConfigurationTokenWebServices.disableHTTPPostOnlyRejectionFilterAutoRegistration , ";
+ String logPrefix = "GenericAccessDecisionManager.disableHTTPPostOnlyRejectionFilterAutoRegistration , ";
logger.debug(logPrefix + "executing registration.setEnabled(false) on HTTPPostOnlyRejectionFilter ...");
final FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
@@ -407,7 +407,7 @@
*/
@Bean
FilterRegistrationBean disableRequestAndResponseValidatorFilterAutoRegistration(final RequestAndResponseValidatorFilter filter) {
- String logPrefix = "SecurityConfigurationTokenWebServices.disableRequestAndResponseValidatorFilterAutoRegistration , ";
+ String logPrefix = "GenericAccessDecisionManager.disableRequestAndResponseValidatorFilterAutoRegistration , ";
logger.debug(logPrefix + "executing registration.setEnabled(false) on RequestLoggingFilter ...");
final FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginTokenizerRequest.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginRequest.java
similarity index 88%
rename from modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginTokenizerRequest.java
rename to modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginRequest.java
index deb0097..1e6d5bb 100644
--- a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginTokenizerRequest.java
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginRequest.java
@@ -19,7 +19,7 @@
*/
package userguide.springboot.webservices.secure;
-public class LoginTokenizerRequest {
+public class LoginRequest {
String email;
@@ -42,7 +42,7 @@
}
- public LoginTokenizerRequest(String email, String credentials) {
+ public LoginRequest(String email, String credentials) {
this.email = email;
this.credentials = credentials;
}
@@ -50,6 +50,6 @@
@Override
public String toString() {
// implement toString() for debugging in trace mode of axis2
- return "LoginTokenizerRequest [email=" + email + ", credentials=not_shown ]";
+ return "LoginRequest [email=" + email + ", credentials=not_shown ]";
}
}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginTokenizerResponse.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginResponse.java
similarity index 90%
rename from modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginTokenizerResponse.java
rename to modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginResponse.java
index 936a0df..c140b5d 100644
--- a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginTokenizerResponse.java
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginResponse.java
@@ -19,7 +19,7 @@
*/
package userguide.springboot.webservices.secure;
-public class LoginTokenizerResponse {
+public class LoginResponse {
String status;
@@ -51,12 +51,12 @@
this.token = token;
}
- public LoginTokenizerResponse(String status, String token) {
+ public LoginResponse(String status, String token) {
this.status = status;
this.token = token;
}
- public LoginTokenizerResponse() {
+ public LoginResponse() {
}
diff --git a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginTokenizerService.java b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginService.java
similarity index 94%
rename from modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginTokenizerService.java
rename to modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginService.java
index 33a87b1..7bddf44 100644
--- a/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginTokenizerService.java
+++ b/modules/samples/userguide/src/userguide/springbootdemo/src/main/java/userguide/springboot/webservices/secure/LoginService.java
@@ -49,9 +49,9 @@
import org.springframework.stereotype.Component;
@Component
-public class LoginTokenizerService {
+public class LoginService {
- private static final Logger logger = LogManager.getLogger(LoginTokenizerService.class);
+ private static final Logger logger = LogManager.getLogger(LoginService.class);
@Autowired
SpringSecurityDAOImpl springSecurityDAOImpl;
@@ -63,21 +63,21 @@
private WSSecUtils wssecutils;
@SuppressWarnings({ "unchecked", "rawtypes" })
- public LoginTokenizerResponse doLogin(LoginTokenizerRequest request) {
+ public LoginResponse doLogin(LoginRequest request) {
Long startTime = System.currentTimeMillis();
String uuid = UUID.randomUUID().toString();
- String logPrefix = "LoginTokenizerService.doLogin() , "
+ String logPrefix = "LoginService.doLogin() , "
+ " , uuid: " + uuid + " , request: " + request.toString() + " , ";
logger.warn(logPrefix + "starting ... ");
- LoginTokenizerResponse response = new LoginTokenizerResponse();
+ LoginResponse response = new LoginResponse();
try {
if (request == null) {
- logger.error(logPrefix + "returning with failure status on null LoginTokenizerRequest");
+ logger.error(logPrefix + "returning with failure status on null LoginRequest");
response.setStatus("FAILED");
return response;
}
@@ -201,9 +201,9 @@
}
@SuppressWarnings({ "unchecked", "rawtypes" })
- private boolean generateTokenForReturn(HttpServletRequest httpServletRequest, LoginTokenizerRequest request, LoginTokenizerResponse response, String currentUserIPAddress, String email, String uuid) {
+ private boolean generateTokenForReturn(HttpServletRequest httpServletRequest, LoginRequest request, LoginResponse response, String currentUserIPAddress, String email, String uuid) {
- String logPrefix = "LoginTokenizerService.generateTokenForReturn() , "
+ String logPrefix = "LoginService.generateTokenForReturn() , "
+ " , uuid: " + uuid + " , ";
try {
diff --git a/src/site/xdoc/docs/json-springboot-userguide.html b/src/site/xdoc/docs/json-springboot-userguide.html
index 76c5917..527aa2b 100644
--- a/src/site/xdoc/docs/json-springboot-userguide.html
+++ b/src/site/xdoc/docs/json-springboot-userguide.html
@@ -22,19 +22,19 @@
<html>
<head>
<meta http-equiv="content-type" content=""/>
- <title>Axis2 Advanced User's Guide</title>
+ <title>Apache Axis2 JSON and REST with Spring Boot User's Guide</title>
</head>
<body dir="ltr" lang="en-US">
<a name="_Toc96697849" id="_Toc96697849"></a>
-<h1 align="center">Apache Axis2 JSON with Spring Boot User's Guide</h1>
+<h1 align="center">Apache Axis2 JSON and REST with Spring Boot User's Guide</h1>
-<p>This guide will help you get started with Axis2 and JSON, using Spring Boot!
-It gives a detailed description on how to write Web services and also
-Web service clients via JSON and Curl, how to write a custom login,
-and how to use them in a token based Web service that also helps prevent cross site
-scripting (XSS).
+<p>This guide will help you get started with Axis2 and JSON via REST, using
+Spring Security with Spring Boot! It gives a detailed description on how to write
+JSON based REST Web services and also Web service clients via JSON and Curl, how to
+write a custom login, and how to use them in a token based Web service that also helps
+prevent cross site scripting (XSS).
</p>
<a name="Introduction"></a>
@@ -62,43 +62,164 @@
<h2>Getting Started</h2>
-<p>The first two sections of the user guide explain how to write and deploy a
-new Web Service using Axis2, and how to write a Web Service client using
-Axis2. The next section - <a href="#config"> Configuring Axis2</a> - provides
-an introduction to important configuration options in Axis2.
+<p>This user guide explains how to write and deploy a
+new JSON and REST based Web Service using Axis2, and how to write a Web Service client
+using JSON with Curl.
+</p>
-<p>In this (first) section, we will learn how to write and deploy Web
-JSON based services using Axis2. All the samples mentioned in this guide are located in
+<p>All the sample code mentioned in this guide is located in
the <b>"samples/userguide/src/springbootdemo"</b> directory of <a
href="../download.cgi">Axis2 standard binary
distribution</a>.</p>
-
+<p>
+This quide supplies a pom.xml for building an exploded WAR with Spring Boot -
+however this WAR does not have an embedded web server such as Tomcat.
+</p>
+<p>
+The testing was carried out on Wildfly, by installing the WAR in its app server.
+</p>
<p>Please deploy the result of the maven build via 'mvn clean install', axis2-json-api.war, into your servlet container and ensure that it installs without any errors.</p>
-<a name="ws_codegen"></a><a name="Web_Services_Using_Axis2"></a>
<h2>Creating a New Web Service</h2>
<p>
-Areas out of scope for this guide are the JWT and JWE, since they require
-elliptic curve cryptography.
-
+Areas out of scope for this guide are JWT and JWE for token generation and validation,
+since they require elliptic curve cryptography. A sample token that is not meant for
+production is generated in this demo - with the intent that the following standards
+should be used in its place. This demo merely shows a place to implement these
+standards.
+</p>
+<p>
https://datatracker.ietf.org/doc/html/rfc7519
https://datatracker.ietf.org/doc/html/rfc7516
-
-DB operations are also out of scope. Very limited credential validation is done.
+</p>
+<p>
+Tip: com.nimbusds is recommended as an open-source Java implementation of these
+standards, for both token generation and validation.
+</p>
+<p>
+DB operations are also out of scope. There is a minimal DAO layer for authentication.
+Very limited credential validation is done.
+</p>
+<p>
The NoOpPasswordEncoder Spring class included in this guide is meant for demos
-and testing only.
-
-This guide provides two JSON based web services, LoginTokenizerService and TestwsService.
-
+and testing only. Do not use this code as is in production.
+</p>
+<p>
+This guide provides two JSON based web services, LoginService and TestwsService.
+</p>
+<p>
The login, if successful, will return a simple token not meant for anything beyond demos.
-
-Axis2 JSON support is via POJO Objects. LoginTokenizerRequest and LoginTokenizerResponse are coded in the LoginTokenizerService as the names would indicate.
-
+The intent of this guide is to show a place that the JWT and JWE standards can be
+implemented.
+</p>
+<p>
+Axis2 JSON support is via POJO Objects. LoginRequest and LoginResponse are coded in the LoginService as the names would indicate.
+</p>
+<p>
Also provided is a test service, TestwsService. It includes two POJO Objects as would
be expected, TestwsRequest and TestwsResponse. This service attempts to return
a String with some Javascript, that is HTML encoded by Axis2 and thereby
-eliminating the possibility of Javascript running the response.
-</ol>
+eliminating the possibility of a Javascript engine executing the response i.e. a
+reflected XSS attack.
+</p>
+<p>
+Concerning Spring Security and Spring Boot, the Axis2Application class that
+extends SpringBootServletInitializer as typically done utilizes
+List<SecurityFilterChain> as a binary choice; A login url will match, otherwise invoke
+JWTAuthenticationFilter. All URL's to other services besides the login, will proceed
+after JWTAuthenticationFilter verifies the token.
+</p>
+<p>
+The JWTAuthenticationFilter class expects a token from the web services JSON client in
+the form of "Authorization: Bearer mytoken".
+</p>
+<p>
+The Axis2WebAppInitializer class supplied in this guide, is the config class
+that registers AxisServlet with spring boot.
+</p>
+<p>
+Axis2 web services are installed via a WEB-INF/services directory that contains
+files with an .aar extention for each service. These aar files are similar to
+jar files, and contain a services.xml that defines the web service behavior.
+The pom.xml supplied in this guide generates these files.
+</p>
+<p>
+Tip: don't expose methods in your web services that are not meant to be exposed,
+such as getters and setters. Axis2 determines the avaliable methods by reflection.
+For JSON, the message name at the start of the JSON received by the Axis2 server
+defines the Axis2 operation to invoke. It is recommended that only one method per
+class be exposed as a starting point. The place to add method exclusion is the
+services.xml file:
+</p>
+<p>
+ <excludeOperations>
+ <operation>setMyVar</operation>
+ </excludeOperations>
+</p>
+<p>
+The axis2.xml file can define Moshi or GSON as the JSON engine. GSON was the original
+however development has largely ceased. Moshi is very similar and is widely considered
+to be the superior implementation in terms of performance. GSON will likely continue to
+be supported in Axis2 because it is helpful to have two JSON implementations to compare
+with for debugging.
+</p>
+<p>
+JSON based web services in the binary distribution of axis2.xml are not enabled by
+default. See the supplied axis2.xml of this guide, and note the places were it has
+"moshi". Just replace "moshi" with "gson" as a global search and replace to switch to
+GSON.
+</p>
+<p>
+Axis2 web services that are JSON based must be invoked from a client that sets an
+HTTP header as "Content-Type: application/json". In order for axis2 to properly
+handle JSON requests, this header behavior needs to be defined in the file
+WEB-INF/conf/axis2.xml.
+</p>
+<p>
+ <messageFormatter contentType="application/json"
+ class="org.apache.axis2.json.moshi.JsonFormatter"/>
+</p>
+<p>
+Other required classes for JSON in the axis2.xml file include JsonRpcMessageReceiver,
+JsonInOnlyRPCMessageReceiver, JsonBuilder, and JSONMessageHandler.
+</p>
+<p>
+Invoking the client for a login that returns a token can be done as follows:
+</p>
+<p>
+curl -v -H "Content-Type: application/json" -X POST --data @/home/myuser/login.dat http://localhost:8080/axis2-json-api/services/loginService
+</p>
+<p>
+Where the contents of /home/myuser/login.dat are:
+</p>
+<p>
+{"doLogin":[{"arg0":{"email":java-dev@axis.apache.org,"credentials":userguide}}]}
+</p>
+<p>
+Response:
+</p>
+<p>
+{"response":{"status":"OK","token":"95104Rn2I2oEATfuI90N","uuid":"99b92d7a-2799-4b20-b029-9fbd6108798a"}}
+</p>
+<p>
+Invoking the client for a Test Service that validates a sample token can be done as
+follows:
+</p>
+<p>
+curl -v -H "Authorization: Bearer I2SpAHWrU5gYbGNwNNKg" -H "Content-Type: application/json" -X POST --data @/root/test.dat http://localhost:8080/axis2-json-api/services/testws'
+</p>
+<p>
+Where the contents of /home/myuser/test.dat are:
+</p>
+<p>
+{"doTestws":[{"arg0":{"messagein":hello}}]}
+</p>
+<p>
+Response, HTML encoded to prevent XSS:
+</p>
+<p>
+{"response":{"messageout":"<script xmlns=\"http://www.w3.org/1999/xhtml\">alert('Hello');</script> \">","status":"OK"}}
+</p>
</body>
</html>