This is an automated email from the ASF dual-hosted git repository.

robertlazarski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/axis-axis2-java-core.git


The following commit(s) were added to refs/heads/master by this push:
     new 408f35a439 AXIS2-6071 Add new class JSONBasedDefaultDispatcher that 
skips legacy SOAP code
408f35a439 is described below

commit 408f35a439671ab147d552b9441ea5505a26c943
Author: Robert Lazarski <rlazar...@alphatheory.com>
AuthorDate: Thu Jul 18 10:49:31 2024 -1000

    AXIS2-6071 Add new class JSONBasedDefaultDispatcher that skips legacy SOAP 
code
---
 .../apache/axis2/json/factory/JsonConstant.java    |   2 +
 .../apache/axis2/json/gson/JSONMessageHandler.java |  34 +++++-
 .../gson/rpc/JsonInOnlyRPCMessageReceiver.java     |   7 +-
 .../json/gson/rpc/JsonRpcMessageReceiver.java      |   8 +-
 .../org/apache/axis2/json/gson/rpc/JsonUtils.java  |  25 +++--
 .../axis2/json/moshi/JSONMessageHandler.java       |  32 +++++-
 .../moshi/rpc/JsonInOnlyRPCMessageReceiver.java    |   7 +-
 .../json/moshi/rpc/JsonRpcMessageReceiver.java     |   8 +-
 .../org/apache/axis2/json/moshi/rpc/JsonUtils.java |  23 ++--
 .../org/apache/axis2/deployment/util/Utils.java    |  73 +++++++++++++
 .../org/apache/axis2/description/AxisService.java  |  64 +++++++++++
 .../dispatchers/JSONBasedDefaultDispatcher.java    | 118 +++++++++++++++++++++
 .../springbootdemo/resources-axis2/conf/axis2.xml  |  44 +-------
 src/site/xdoc/docs/json-springboot-userguide.xml   |   2 +-
 14 files changed, 370 insertions(+), 77 deletions(-)

diff --git a/modules/json/src/org/apache/axis2/json/factory/JsonConstant.java 
b/modules/json/src/org/apache/axis2/json/factory/JsonConstant.java
index 9effd0882f..f4ad434861 100644
--- a/modules/json/src/org/apache/axis2/json/factory/JsonConstant.java
+++ b/modules/json/src/org/apache/axis2/json/factory/JsonConstant.java
@@ -34,6 +34,8 @@ public class JsonConstant {
 
     public static final String MOSHI_XML_STREAM_READER = 
"MoshiXMLStreamReader";
 
+    public static final String JSON_MESSAGE_NAME = "jsonMessageName";
+
     public static final String XMLNODES = "xmlnodes";
 
 
diff --git 
a/modules/json/src/org/apache/axis2/json/gson/JSONMessageHandler.java 
b/modules/json/src/org/apache/axis2/json/gson/JSONMessageHandler.java
index 7cee12aa4c..f7bfadea3d 100644
--- a/modules/json/src/org/apache/axis2/json/gson/JSONMessageHandler.java
+++ b/modules/json/src/org/apache/axis2/json/gson/JSONMessageHandler.java
@@ -35,7 +35,10 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.ws.commons.schema.XmlSchema;
 
+import com.google.gson.stream.JsonReader;
+
 import javax.xml.namespace.QName;
+import java.io.IOException;
 import java.util.List;
 
 public class JSONMessageHandler extends AbstractHandler {
@@ -73,7 +76,6 @@ public class JSONMessageHandler extends AbstractHandler {
                 log.debug("JSON MessageReceiver found, proceeding with the 
JSON request");
                 Object tempObj = 
msgContext.getProperty(JsonConstant.IS_JSON_STREAM);
                 if (tempObj != null) {
-                    log.debug("JSON MessageReceiver found JSON stream, 
proceeding with the JSON request");
                     boolean isJSON = Boolean.valueOf(tempObj.toString());
                     Object o = 
msgContext.getProperty(JsonConstant.GSON_XML_STREAM_READER);
                     if (o != null) {
@@ -83,7 +85,6 @@ public class JSONMessageHandler extends AbstractHandler {
                         gsonXMLStreamReader.initXmlStreamReader(elementQname, 
schemas, msgContext.getConfigurationContext());
                         OMXMLParserWrapper stAXOMBuilder = 
OMXMLBuilderFactory.createStAXOMBuilder(gsonXMLStreamReader);
                         OMElement omElement = 
stAXOMBuilder.getDocumentElement();
-                        log.debug("GsonXMLStreamReader found elementQname: " + 
elementQname);
                         msgContext.getEnvelope().getBody().addChild(omElement);
                     } else {
                         log.error("GsonXMLStreamReader is null");
@@ -94,7 +95,34 @@ public class JSONMessageHandler extends AbstractHandler {
                 }
             }
         } else {
-            log.debug("Axis operation is null, message hasn't been dispatched 
to operation, ignore it");
+            String enableJSONOnly = (String)  
msgContext.getAxisService().getParameterValue("enableJSONOnly");
+            if (enableJSONOnly !=null && 
enableJSONOnly.equalsIgnoreCase("true")) {
+                log.warn("On enableJSONOnly=true Axis operation is null on 
JSON request, message hasn't been dispatched to an operation, proceeding on 
JSON message name discovery and AxisOperation mapping");
+                try{
+                    Object tempObj = 
msgContext.getProperty(JsonConstant.IS_JSON_STREAM);
+                    if (tempObj != null) {
+                        boolean isJSON = Boolean.valueOf(tempObj.toString());
+                        Object o = 
msgContext.getProperty(JsonConstant.MOSHI_XML_STREAM_READER);
+                        if (o != null) {
+                            GsonXMLStreamReader gsonXMLStreamReader = 
(GsonXMLStreamReader) o;
+                        JsonReader jsonReader = 
gsonXMLStreamReader.getJsonReader();
+                            jsonReader.beginObject();
+                            String messageName=jsonReader.nextName();     // 
get message name from input json stream
+                            if (messageName == null) {
+                                log.error("JSONMessageHandler can't find 
messageName: " +messageName);
+                                throw new IOException("Bad Request");
+                            } else {
+                                log.warn("JSONMessageHandler found 
messageName: " +messageName);
+                                msgContext.setProperty("jsonMessageName", 
messageName);
+                            }
+                        }
+                   }
+                } catch(Exception e){
+                   log.error("JSONMessageHandler error: " +e.getMessage());
+                }
+            } else {
+                log.warn("On enableJSONOnly=false Axis operation is null, 
ignore it");
+           }
         }
         return InvocationResponse.CONTINUE;
     }
diff --git 
a/modules/json/src/org/apache/axis2/json/gson/rpc/JsonInOnlyRPCMessageReceiver.java
 
b/modules/json/src/org/apache/axis2/json/gson/rpc/JsonInOnlyRPCMessageReceiver.java
index a77c61726f..5f933e6988 100644
--- 
a/modules/json/src/org/apache/axis2/json/gson/rpc/JsonInOnlyRPCMessageReceiver.java
+++ 
b/modules/json/src/org/apache/axis2/json/gson/rpc/JsonInOnlyRPCMessageReceiver.java
@@ -58,7 +58,8 @@ public class JsonInOnlyRPCMessageReceiver extends 
RPCInOnlyMessageReceiver {
                 AxisOperation op = 
inMessage.getOperationContext().getAxisOperation();
                 String operation = op.getName().getLocalPart();
                 log.debug("JsonInOnlyRPCMessageReceiver.invokeBusinessLogic() 
executing invokeService() with operation: " + operation);
-                invokeService(jsonReader, serviceObj, operation);
+                String enableJSONOnly = (String)  
inMessage.getAxisService().getParameterValue("enableJSONOnly");
+                invokeService(jsonReader, serviceObj, operation, 
enableJSONOnly);
             } else {
                 throw new AxisFault("GsonXMLStreamReader should have put as a 
property of messageContext " +
                         "to evaluate JSON message");
@@ -68,7 +69,7 @@ public class JsonInOnlyRPCMessageReceiver extends 
RPCInOnlyMessageReceiver {
         }
     }
 
-    public void invokeService(JsonReader jsonReader, Object serviceObj, String 
operation_name) throws AxisFault {
+    public void invokeService(JsonReader jsonReader, Object serviceObj, String 
operation_name, String enableJSONOnly) throws AxisFault {
         String msg;
         Class implClass = serviceObj.getClass();
         Method[] allMethods = implClass.getDeclaredMethods();
@@ -76,7 +77,7 @@ public class JsonInOnlyRPCMessageReceiver extends 
RPCInOnlyMessageReceiver {
         Class[] paramClasses = method.getParameterTypes();
         try {
             int paramCount = paramClasses.length;
-            JsonUtils.invokeServiceClass(jsonReader, serviceObj, method, 
paramClasses, paramCount);
+            JsonUtils.invokeServiceClass(jsonReader, serviceObj, method, 
paramClasses, paramCount, enableJSONOnly);
         } catch (IllegalAccessException e) {
             msg = "Does not have access to " +
                     "the definition of the specified class, field, method or 
constructor";
diff --git 
a/modules/json/src/org/apache/axis2/json/gson/rpc/JsonRpcMessageReceiver.java 
b/modules/json/src/org/apache/axis2/json/gson/rpc/JsonRpcMessageReceiver.java
index 7cd29e2fc0..e13dd99c8b 100644
--- 
a/modules/json/src/org/apache/axis2/json/gson/rpc/JsonRpcMessageReceiver.java
+++ 
b/modules/json/src/org/apache/axis2/json/gson/rpc/JsonRpcMessageReceiver.java
@@ -57,7 +57,8 @@ public class JsonRpcMessageReceiver extends 
RPCMessageReceiver {
                 Object serviceObj = getTheImplementationObject(inMessage);
                 AxisOperation op = 
inMessage.getOperationContext().getAxisOperation();
                 String operation = op.getName().getLocalPart();
-                invokeService(jsonReader, serviceObj, operation , outMessage);
+                String enableJSONOnly = (String)  
inMessage.getAxisService().getParameterValue("enableJSONOnly");
+                invokeService(jsonReader, serviceObj, operation , outMessage, 
enableJSONOnly);
             } else {
                 throw new AxisFault("GsonXMLStreamReader should be put as a 
property of messageContext " +
                         "to evaluate JSON message");
@@ -67,8 +68,7 @@ public class JsonRpcMessageReceiver extends 
RPCMessageReceiver {
         }
     }
 
-    public void invokeService(JsonReader jsonReader, Object serviceObj, String 
operation_name,
-                                   MessageContext outMes) throws AxisFault {
+    public void invokeService(JsonReader jsonReader, Object serviceObj, String 
operation_name, MessageContext outMes, String enableJSONOnly) throws AxisFault {
         String msg;
         Class implClass = serviceObj.getClass();
         Method[] allMethods = implClass.getDeclaredMethods();
@@ -76,7 +76,7 @@ public class JsonRpcMessageReceiver extends 
RPCMessageReceiver {
         Class[] paramClasses = method.getParameterTypes();
         try {
             int paramCount = paramClasses.length;
-            Object retObj = JsonUtils.invokeServiceClass(jsonReader, 
serviceObj, method, paramClasses, paramCount);
+            Object retObj = JsonUtils.invokeServiceClass(jsonReader, 
serviceObj, method, paramClasses, paramCount, enableJSONOnly);
 
             // handle response
             outMes.setProperty(JsonConstant.RETURN_OBJECT, retObj);
diff --git a/modules/json/src/org/apache/axis2/json/gson/rpc/JsonUtils.java 
b/modules/json/src/org/apache/axis2/json/gson/rpc/JsonUtils.java
index b0cfcf7888..aca3de9ca9 100644
--- a/modules/json/src/org/apache/axis2/json/gson/rpc/JsonUtils.java
+++ b/modules/json/src/org/apache/axis2/json/gson/rpc/JsonUtils.java
@@ -38,8 +38,8 @@ public class JsonUtils {
                                             Object service,
                                             Method operation ,
                                             Class[] paramClasses ,
-                                            int paramCount ) throws 
InvocationTargetException,
-            IllegalAccessException, IOException  {
+                                            int paramCount,
+                                           String enableJSONOnly ) throws 
InvocationTargetException, IllegalAccessException, IOException  {
 
         Object[] methodParam = new Object[paramCount];
        try {
@@ -49,20 +49,27 @@ public class JsonUtils {
             if( ! jsonReader.isLenient()){
                 jsonReader.setLenient(true);
             }
-            jsonReader.beginObject();
-            String messageName=jsonReader.nextName();     // get message name 
from input json stream
-            if (messageName == null || 
!messageName.equals(operation.getName())) {
-                log.error("JsonUtils.invokeServiceClass() throwing 
IOException, messageName: " +messageName+ " is unknown, it does not match the 
axis2 operation, the method name: " + operation.getName());
-                throw new IOException("Bad Request");
-            }
+
+            if (enableJSONOnly ==null || 
enableJSONOnly.equalsIgnoreCase("false")) {
+                log.debug("JsonUtils.invokeServiceClass() detected 
enableJSONOnly=false, executing jsonReader.beginObject() and then 
jsonReader.beginArray() on method name: " + operation.getName());
+                jsonReader.beginObject();
+                String messageName=jsonReader.nextName();     // get message 
name from input json stream
+                if (messageName == null || 
!messageName.equals(operation.getName())) {
+                    log.error("JsonUtils.invokeServiceClass() throwing 
IOException, messageName: " +messageName+ " is unknown, it does not match the 
axis2 operation, the method name: " + operation.getName());
+                    throw new IOException("Bad Request");
+                }
+            } else {
+                log.debug("JsonUtils.invokeServiceClass() detected 
enableJSONOnly=true, executing jsonReader.beginArray()");
+           }       
+
             jsonReader.beginArray();
     
             int i = 0;
             for (Class paramType : paramClasses) {
                 jsonReader.beginObject();
                 argNames[i] = jsonReader.nextName();
-                log.debug("JsonUtils.invokeServiceClass() on messageName: " 
+messageName+ " , is currently processing argName: " + argNames[i]);
                 methodParam[i] = gson.fromJson(jsonReader, paramType);   // 
gson handle all types well and return an object from it
+                log.trace("JsonUtils.invokeServiceClass() completed processing 
on argNames: " +argNames[i]+ " , methodParam: " 
+methodParam[i].getClass().getName()+ " , from argNames.length: " + 
argNames.length);
                 jsonReader.endObject();
                 i++;
             }
diff --git 
a/modules/json/src/org/apache/axis2/json/moshi/JSONMessageHandler.java 
b/modules/json/src/org/apache/axis2/json/moshi/JSONMessageHandler.java
index 1b7a1fe181..815a647109 100644
--- a/modules/json/src/org/apache/axis2/json/moshi/JSONMessageHandler.java
+++ b/modules/json/src/org/apache/axis2/json/moshi/JSONMessageHandler.java
@@ -35,7 +35,10 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.ws.commons.schema.XmlSchema;
 
+import com.squareup.moshi.JsonReader;
+
 import javax.xml.namespace.QName;
+import java.io.IOException;
 import java.util.List;
 
 public class JSONMessageHandler extends AbstractHandler {
@@ -92,7 +95,34 @@ public class JSONMessageHandler extends AbstractHandler {
                 }
             }
         } else {
-            log.debug("Axis operation is null, message hasn't been dispatched 
to operation, ignore it");
+            String enableJSONOnly = (String) 
msgContext.getAxisService().getParameterValue("enableJSONOnly");
+            if (enableJSONOnly !=null && 
enableJSONOnly.equalsIgnoreCase("true")) {
+                log.warn("On enableJSONOnly=true Axis operation is null on 
JSON request, message hasn't been dispatched to an operation, proceeding on 
JSON message name discovery and AxisOperation mapping");
+                try{
+                    Object tempObj = 
msgContext.getProperty(JsonConstant.IS_JSON_STREAM);
+                    if (tempObj != null) {
+                        boolean isJSON = Boolean.valueOf(tempObj.toString());
+                        Object o = 
msgContext.getProperty(JsonConstant.MOSHI_XML_STREAM_READER);
+                        if (o != null) {
+                            MoshiXMLStreamReader moshiXMLStreamReader = 
(MoshiXMLStreamReader) o;
+                            JsonReader jsonReader = 
moshiXMLStreamReader.getJsonReader();
+                            jsonReader.beginObject();
+                            String messageName=jsonReader.nextName();     // 
get message name from input json stream
+                            if (messageName == null) {
+                                log.error("JSONMessageHandler can't find 
messageName: " +messageName);
+                                throw new IOException("Bad Request");
+                            } else {
+                                log.warn("JSONMessageHandler found 
messageName: " +messageName);
+                                msgContext.setProperty("jsonMessageName", 
messageName);
+                            }
+                        }
+                   }
+                } catch(Exception e){
+                   log.error("JSONMessageHandler error: " +e.getMessage());
+                }
+            } else {
+                log.warn("On enableJSONOnly=false Axis operation is null, 
ignore it");
+           }
         }
         return InvocationResponse.CONTINUE;
     }
diff --git 
a/modules/json/src/org/apache/axis2/json/moshi/rpc/JsonInOnlyRPCMessageReceiver.java
 
b/modules/json/src/org/apache/axis2/json/moshi/rpc/JsonInOnlyRPCMessageReceiver.java
index 6f2c35dacc..4514906a8c 100644
--- 
a/modules/json/src/org/apache/axis2/json/moshi/rpc/JsonInOnlyRPCMessageReceiver.java
+++ 
b/modules/json/src/org/apache/axis2/json/moshi/rpc/JsonInOnlyRPCMessageReceiver.java
@@ -58,7 +58,8 @@ public class JsonInOnlyRPCMessageReceiver extends 
RPCInOnlyMessageReceiver {
                 AxisOperation op = 
inMessage.getOperationContext().getAxisOperation();
                 String operation = op.getName().getLocalPart();
                 log.debug("JsonInOnlyRPCMessageReceiver.invokeBusinessLogic() 
executing invokeService() with operation: " + operation);
-                invokeService(jsonReader, serviceObj, operation);
+                String enableJSONOnly = (String)  
inMessage.getAxisService().getParameterValue("enableJSONOnly");
+                invokeService(jsonReader, serviceObj, operation, 
enableJSONOnly);
             } else {
                 throw new AxisFault("MoshiXMLStreamReader should have put as a 
property of messageContext " +
                         "to evaluate JSON message");
@@ -68,7 +69,7 @@ public class JsonInOnlyRPCMessageReceiver extends 
RPCInOnlyMessageReceiver {
         }
     }
 
-    public void invokeService(JsonReader jsonReader, Object serviceObj, String 
operation_name) throws AxisFault {
+    public void invokeService(JsonReader jsonReader, Object serviceObj, String 
operation_name, String enableJSONOnly) throws AxisFault {
         String msg;
         Class implClass = serviceObj.getClass();
         Method[] allMethods = implClass.getDeclaredMethods();
@@ -76,7 +77,7 @@ public class JsonInOnlyRPCMessageReceiver extends 
RPCInOnlyMessageReceiver {
         Class[] paramClasses = method.getParameterTypes();
         try {
             int paramCount = paramClasses.length;
-            JsonUtils.invokeServiceClass(jsonReader, serviceObj, method, 
paramClasses, paramCount);
+            JsonUtils.invokeServiceClass(jsonReader, serviceObj, method, 
paramClasses, paramCount, enableJSONOnly);
         } catch (IllegalAccessException e) {
             msg = "Does not have access to " +
                     "the definition of the specified class, field, method or 
constructor";
diff --git 
a/modules/json/src/org/apache/axis2/json/moshi/rpc/JsonRpcMessageReceiver.java 
b/modules/json/src/org/apache/axis2/json/moshi/rpc/JsonRpcMessageReceiver.java
index bf90f30f1f..0c74df2010 100644
--- 
a/modules/json/src/org/apache/axis2/json/moshi/rpc/JsonRpcMessageReceiver.java
+++ 
b/modules/json/src/org/apache/axis2/json/moshi/rpc/JsonRpcMessageReceiver.java
@@ -57,7 +57,8 @@ public class JsonRpcMessageReceiver extends 
RPCMessageReceiver {
                 Object serviceObj = getTheImplementationObject(inMessage);
                 AxisOperation op = 
inMessage.getOperationContext().getAxisOperation();
                 String operation = op.getName().getLocalPart();
-                invokeService(jsonReader, serviceObj, operation , outMessage);
+                String enableJSONOnly = (String)  
inMessage.getAxisService().getParameterValue("enableJSONOnly");
+                invokeService(jsonReader, serviceObj, operation , outMessage, 
enableJSONOnly);
             } else {
                 throw new AxisFault("MoshiXMLStreamReader should be put as a 
property of messageContext " +
                         "to evaluate JSON message");
@@ -67,8 +68,7 @@ public class JsonRpcMessageReceiver extends 
RPCMessageReceiver {
         }
     }
 
-    public void invokeService(JsonReader jsonReader, Object serviceObj, String 
operation_name,
-                                   MessageContext outMes) throws AxisFault {
+    public void invokeService(JsonReader jsonReader, Object serviceObj, String 
operation_name, MessageContext outMes, String enableJSONOnly) throws AxisFault {
         String msg;
         Class implClass = serviceObj.getClass();
         Method[] allMethods = implClass.getDeclaredMethods();
@@ -76,7 +76,7 @@ public class JsonRpcMessageReceiver extends 
RPCMessageReceiver {
         Class[] paramClasses = method.getParameterTypes();
         try {
             int paramCount = paramClasses.length;
-            Object retObj = JsonUtils.invokeServiceClass(jsonReader, 
serviceObj, method, paramClasses, paramCount);
+            Object retObj = JsonUtils.invokeServiceClass(jsonReader, 
serviceObj, method, paramClasses, paramCount, enableJSONOnly);
 
             // handle response
             outMes.setProperty(JsonConstant.RETURN_OBJECT, retObj);
diff --git a/modules/json/src/org/apache/axis2/json/moshi/rpc/JsonUtils.java 
b/modules/json/src/org/apache/axis2/json/moshi/rpc/JsonUtils.java
index 712f6ce937..84e7fc5da6 100644
--- a/modules/json/src/org/apache/axis2/json/moshi/rpc/JsonUtils.java
+++ b/modules/json/src/org/apache/axis2/json/moshi/rpc/JsonUtils.java
@@ -49,8 +49,8 @@ public class JsonUtils {
                                             Object service,
                                             Method operation ,
                                             Class[] paramClasses ,
-                                            int paramCount ) throws 
InvocationTargetException,
-            IllegalAccessException, IOException  {
+                                            int paramCount,
+                                           String enableJSONOnly ) throws 
InvocationTargetException, IllegalAccessException, IOException  {
 
         Object[] methodParam = new Object[paramCount];
        try {
@@ -102,12 +102,17 @@ public class JsonUtils {
             Moshi moshiFrom = new 
Moshi.Builder().add(objectFactory).add(Date.class, new 
Rfc3339DateJsonAdapter()).build();
             String[] argNames = new String[paramCount];
     
-            jsonReader.beginObject();
-            String messageName=jsonReader.nextName();     // get message name 
from input json stream
-            if (messageName == null || 
!messageName.equals(operation.getName())) {
-                log.error("JsonUtils.invokeServiceClass() throwing 
IOException, messageName: " +messageName+ " is unknown, it does not match the 
axis2 operation, the method name: " + operation.getName());
-                throw new IOException("Bad Request");
-            }
+            if (enableJSONOnly ==null || 
enableJSONOnly.equalsIgnoreCase("false")) {
+                log.debug("JsonUtils.invokeServiceClass() detected 
enableJSONOnly=false, executing jsonReader.beginObject() and then 
jsonReader.beginArray() on method name: " + operation.getName());
+                jsonReader.beginObject();
+                String messageName=jsonReader.nextName();     // get message 
name from input json stream
+                if (messageName == null || 
!messageName.equals(operation.getName())) {
+                    log.error("JsonUtils.invokeServiceClass() throwing 
IOException, messageName: " +messageName+ " is unknown, it does not match the 
axis2 operation, the method name: " + operation.getName());
+                    throw new IOException("Bad Request");
+                }
+            } else {
+                log.debug("JsonUtils.invokeServiceClass() detected 
enableJSONOnly=true, executing jsonReader.beginArray()");
+           }       
             jsonReader.beginArray();
     
             int i = 0;
@@ -117,7 +122,7 @@ public class JsonUtils {
                 jsonReader.beginObject();
                 argNames[i] = jsonReader.nextName();
                 methodParam[i] = moshiFromJsonAdapter.fromJson(jsonReader);   
// moshi handles all types well and returns an object from it
-                log.trace("JsonUtils.invokeServiceClass() completed processing 
on messageName: " +messageName+ " , arg name: " +argNames[i]+ " , methodParam: 
" +methodParam[i].getClass().getName()+ " , from argNames.length: " + 
argNames.length);
+                log.trace("JsonUtils.invokeServiceClass() completed processing 
on argNames: " +argNames[i]+ " , methodParam: " 
+methodParam[i].getClass().getName()+ " , from argNames.length: " + 
argNames.length);
                 jsonReader.endObject();
                 i++;
             }
diff --git a/modules/kernel/src/org/apache/axis2/deployment/util/Utils.java 
b/modules/kernel/src/org/apache/axis2/deployment/util/Utils.java
index 88ee519ea9..39b1f28b02 100644
--- a/modules/kernel/src/org/apache/axis2/deployment/util/Utils.java
+++ b/modules/kernel/src/org/apache/axis2/deployment/util/Utils.java
@@ -27,6 +27,7 @@ import org.apache.axiom.soap.SOAP12Constants;
 import org.apache.axis2.AxisFault;
 import org.apache.axis2.Constants;
 import org.apache.axis2.jaxrs.JAXRSModel;
+import org.apache.axis2.jaxrs.JAXRSUtils;
 import org.apache.axis2.context.ConfigurationContext;
 import org.apache.axis2.deployment.DeploymentClassLoader;
 import org.apache.axis2.deployment.DeploymentConstants;
@@ -60,6 +61,7 @@ import javax.xml.stream.FactoryConfigurationError;
 import javax.xml.stream.XMLStreamException;
 import java.io.*;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
@@ -402,6 +404,77 @@ public class Utils {
         if (serviceClass == null) {
             return;
         }
+        String enableJSONOnly = (String) 
axisConfig.getParameterValue("enableJSONOnly");
+       if (enableJSONOnly !=null && enableJSONOnly.equalsIgnoreCase("true")) {
+            log.warn("on enableJSONOnly: " +enableJSONOnly+ " starting 
fillAxisService(), serviceClass.name: " + serviceClass.getName());
+            List<Method> serviceMethods = new ArrayList<Method>();
+            Map<String, Method> uniqueMethods = new LinkedHashMap<String, 
Method>();
+            for (Method method : serviceClass.getMethods()) {
+                if (method.getDeclaringClass() == Object.class) {
+                    continue;
+                }
+                if (!Modifier.isPublic(method.getModifiers())) {
+                    // skip non public methods
+                    continue;
+                }
+                String methodName = method.getName();
+                if (excludeOperations.contains(methodName)) {
+                    continue;
+                }
+                boolean addToService = false;
+                AxisOperation axisOperation = axisService.getOperation(new 
QName(methodName));
+                if (axisOperation == null) {
+                    axisOperation = getAxisOperationForJmethod(method);
+                    axisService.addOperation(axisOperation);
+                    log.warn("on methodName: " +methodName+ " , 
enableJSONOnly: " +enableJSONOnly+ " , axisOperation added to service: " 
+axisService.getName()+ " , operation: " + 
axisOperation.getName().getLocalPart());
+                }
+                // by now axis operation should be assigned but we better 
recheck & add the paramether
+                if (axisOperation != null) {
+                    axisOperation.addParameter("JAXRSAnnotaion", 
JAXRSUtils.getMethodModel(JAXRSUtils.getClassModel(serviceClass), method));
+                }
+                if (method.getDeclaringClass() != Object.class) {
+                    serviceMethods.add(method);
+                }
+            }
+            // The order of the methods returned by getMethods is undefined, 
but the test cases assume that the
+            // order is the same on all Java versions. Java 6 seems to use 
reverse lexical order, so we use that
+            // here to make things deterministic.
+            Collections.sort(serviceMethods, new Comparator<Method>() {
+                public int compare(Method o1, Method o2) {
+                    return -o1.getName().compareTo(o2.getName());
+                }
+            });
+    
+            log.debug("fillAxisService() on enableJSONOnly=true found 
serviceMethods: " +serviceMethods);
+
+            PhasesInfo pinfo = axisConfig.getPhasesInfo();
+
+            for (Method jmethod : serviceMethods) {
+                String opName = jmethod.getName();
+                AxisOperation operation = axisService
+                        .getOperation(new QName(opName));
+                // if the operation there in services.xml then try to set it 
schema
+                // element name
+                if (operation == null) {
+                    operation = axisService.getOperation(new QName(
+                            jmethod.getName()));
+                }
+                MessageReceiver mr =
+                        
axisService.getMessageReceiver(operation.getMessageExchangePattern());
+                if (mr == null) {
+                    mr = 
axisConfig.getMessageReceiver(operation.getMessageExchangePattern());
+                }
+                if (operation.getMessageReceiver() == null) {
+                    operation.setMessageReceiver(mr);
+                }
+                pinfo.setOperationPhases(operation);
+                axisService.addOperation(operation);
+                axisService.addJSONMessageNameToOperationMapping(opName, 
operation);
+            }
+            log.warn("fillAxisService() completed on enableJSONOnly=true , 
axisService name: " + axisService.getName());
+           return;
+       }
+
         ClassLoader serviceClassLoader = axisService.getClassLoader();
         // adding name spaces
         NamespaceMap map = new NamespaceMap();
diff --git a/modules/kernel/src/org/apache/axis2/description/AxisService.java 
b/modules/kernel/src/org/apache/axis2/description/AxisService.java
index a89454ec3e..6d1c0fe099 100644
--- a/modules/kernel/src/org/apache/axis2/description/AxisService.java
+++ b/modules/kernel/src/org/apache/axis2/description/AxisService.java
@@ -156,6 +156,12 @@ public class AxisService extends AxisDescription {
      */
     private Map<QName, AxisOperation> messageElementQNameToOperationMap = new 
HashMap<QName, AxisOperation>();
 
+    /*
+     * This is a map between the JSON Object name of a message specified in
+     * the received JSON stream to the Axis2 operations defined in the 
services.xml file
+     */
+    private Map<String, AxisOperation> jsonMessageNameToOperationMap = new 
HashMap<String, AxisOperation>();
+
     private int nsCount = 0;
     private static final Log log = LogFactory.getLog(AxisService.class);
     private URL fileName;
@@ -3232,6 +3238,64 @@ public class AxisService extends AxisDescription {
         this.messageElementQNameToOperationMap = 
messageElementQNameToOperationMap;
     }
 
+    /**
+     * Look up an AxisOperation for this service based off of a JSON message 
name
+     * from the first  'name' read from a JSON message.
+     * 
+     * @param messageName
+     *            The message name to search for.
+     * @return The AxisOperation registered to the JSON message name or null 
if no match was
+     *         found.
+     * @see #setJSONMessageNameToOperationMap(Map)
+     */
+    public AxisOperation getOperationByJSONMessageName(
+            String messageName) {
+
+        return (AxisOperation) jsonMessageNameToOperationMap
+                .get(messageName);
+    }
+
+    /**
+     * Set the map of JSON message names as Strings to AxisOperations for this
+     * service. This map is used during JSON Object name-based routing by
+     * reading the first name in a JSON message during the transport phase in
+     * JSONMessageHandler.
+     * 
+     * @param jsonMessageNameToOperationMap
+     *            The map from JSON message names to AxisOperations.
+     */
+    public void setJSONMessageNameToOperationMap(
+            Map jsonMessageNameToOperationMap) {
+        this.jsonMessageNameToOperationMap = jsonMessageNameToOperationMap;
+    }
+
+    /**
+     * Add an entry to the map between JSON message names in JSON and
+     * AxisOperations for this service.
+     * 
+     * @param messageName
+     *            The message name of the JSON on the first name from the 
input message that maps to the
+     *            given operation.
+     * @param operation
+     *            The AxisOperation to be mapped to.
+     * @see #setJSONMessageNameToOperationMap(Map)
+     */
+    public void addJSONMessageNameToOperationMapping(
+            String messageName, AxisOperation operation) {
+        // when setting an operation we have to set it only if the
+        // messegeName does not
+        // exist in the map.
+        if (jsonMessageNameToOperationMap.containsKey(messageName)
+                && jsonMessageNameToOperationMap.get(messageName) != 
operation) {
+            log.error("jsonMessageNameToOperationMap skipping 'put' on 
messageName: " + messageName + " , containsKey() returned true or value not 
equal to operation: " + operation.getName().getLocalPart());
+        } else {
+            jsonMessageNameToOperationMap.put(messageName,
+                    operation);
+            log.debug("jsonMessageNameToOperationMap 'put' on messageName: " + 
messageName + " with operation: " + operation.getName().getLocalPart());
+        }
+
+    }
+
     /**
      * Look up an AxisOperation for this service based off of an element QName
      * from a WSDL message element.
diff --git 
a/modules/kernel/src/org/apache/axis2/dispatchers/JSONBasedDefaultDispatcher.java
 
b/modules/kernel/src/org/apache/axis2/dispatchers/JSONBasedDefaultDispatcher.java
new file mode 100644
index 0000000000..d281180a26
--- /dev/null
+++ 
b/modules/kernel/src/org/apache/axis2/dispatchers/JSONBasedDefaultDispatcher.java
@@ -0,0 +1,118 @@
+/*
+ * 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 org.apache.axis2.dispatchers;
+
+import org.apache.axiom.om.OMNamespace;
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.context.ConfigurationContext;
+import org.apache.axis2.context.MessageContext;
+import org.apache.axis2.description.AxisOperation;
+import org.apache.axis2.description.AxisService;
+import org.apache.axis2.description.HandlerDescription;
+import org.apache.axis2.description.Parameter;
+import org.apache.axis2.engine.AbstractDispatcher;
+import org.apache.axis2.engine.AxisConfiguration;
+import org.apache.axis2.util.LoggingControl;
+import org.apache.axis2.util.Utils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Dispatches based on the namespace URI of the first child of
+ * the body.
+ */
+public class JSONBasedDefaultDispatcher extends AbstractDispatcher {
+
+    /**
+     * Field NAME
+     */
+    public static final String NAME = "JSONBasedDefaultDispatcher";
+    private static final Log log = 
LogFactory.getLog(JSONBasedDefaultDispatcher.class);
+
+    public AxisOperation findOperation(AxisService service, MessageContext 
messageContext)
+            throws AxisFault {
+
+        String jsonMessageName =  (String) 
messageContext.getProperty("jsonMessageName");
+           
+       if (jsonMessageName == null) {
+            log.error("JSONBasedDefaultDispatcher.findOperation() returning 
null on null jsonMessageName");
+           return null;
+       }
+
+        // Parameter jsonMessageNameParam = 
messageContext.getParameter("jsonMessageName");
+        // String jsonMessageName = 
Utils.getParameterValue(jsonMessageNameParam);
+        // AxisOperation axisOperation = 
service.getOperationByMessageElementQName(null);
+        AxisOperation axisOperation = 
service.getOperationByJSONMessageName(jsonMessageName);
+        // this is required for services uses the RPC message receiver
+        if (axisOperation == null){
+            log.error(messageContext.getLogIDString() + " , axisOperation is 
null in findOperation() with jsonMessageName: " +jsonMessageName+ " , service 
name: " + service.getName());
+           return null;
+        } else {
+            log.debug(messageContext.getLogIDString() + " , axisOperation 
found from  with service name: " + service.getName() + " , operation: " + 
axisOperation.getName().getLocalPart() + " , jsonMessageName: " 
+jsonMessageName);
+       }
+        return axisOperation;
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see 
org.apache.axis2.engine.AbstractDispatcher#findService(org.apache.axis2.context.MessageContext)
+     */
+    public AxisService findService(MessageContext messageContext) throws 
AxisFault {
+        String serviceName;
+
+        String localPart = 
messageContext.getEnvelope().getSOAPBodyFirstElementLocalName();
+
+        if (localPart != null) {
+            OMNamespace ns = 
messageContext.getEnvelope().getSOAPBodyFirstElementNS();
+
+            if (ns != null) {
+                String filePart = ns.getNamespaceURI();
+
+                if (LoggingControl.debugLoggingAllowed && 
log.isDebugEnabled()) {
+                    log.debug(messageContext.getLogIDString() +
+                            " Checking for Service using SOAP message body's 
first child's namespace : "
+                            + filePart);
+                }
+                ConfigurationContext configurationContext =
+                        messageContext.getConfigurationContext();
+                String[] values = 
Utils.parseRequestURLForServiceAndOperation(filePart,
+                                                                              
configurationContext.getServiceContextPath());
+
+                if (values[0] != null) {
+                    serviceName = values[0];
+
+                    AxisConfiguration registry =
+                            configurationContext.getAxisConfiguration();
+
+                    return registry.getService(serviceName);
+                }
+            }
+        }
+
+        return null;
+    }
+
+    public void initDispatcher() {
+        init(new HandlerDescription(NAME));
+    }
+}
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
index 71c176ee50..3b22530667 100644
--- 
a/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/conf/axis2.xml
+++ 
b/modules/samples/userguide/src/userguide/springbootdemo/resources-axis2/conf/axis2.xml
@@ -437,14 +437,6 @@
     <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"/>
@@ -459,20 +451,8 @@
         <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"/>
+            <handler name="JSONBasedDefaultDispatcher"
+                     
class="org.apache.axis2.dispatchers.JSONBasedDefaultDispatcher"/>
         </phase>
         <phase name="RMPhase"/>
         <!--  System predefined phases       -->
@@ -483,11 +463,9 @@
                 <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-->
@@ -506,29 +484,15 @@
         <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"/>
+            <handler name="JSONBasedDefaultDispatcher"
+                     
class="org.apache.axis2.dispatchers.JSONBasedDefaultDispatcher"/>
         </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"/>
diff --git a/src/site/xdoc/docs/json-springboot-userguide.xml 
b/src/site/xdoc/docs/json-springboot-userguide.xml
index b5604e3c21..be360fe5dc 100644
--- a/src/site/xdoc/docs/json-springboot-userguide.xml
+++ b/src/site/xdoc/docs/json-springboot-userguide.xml
@@ -193,7 +193,7 @@ WEB-INF/conf/axis2.xml.
 </pre>
 <p>
 Other required classes for JSON in the axis2.xml file include 
JsonRpcMessageReceiver,
-JsonInOnlyRPCMessageReceiver, JsonBuilder, and JSONMessageHandler.
+JsonInOnlyRPCMessageReceiver, JsonBuilder, JSONBasedDefaultDispatcher and 
JSONMessageHandler.
 </p>
 <p>
 Invoking the client for a login that returns a token can be done as follows:


Reply via email to