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 <[email protected]>
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: