diff --git a/org.adempiere.server-feature/server.product.functionaltest.launch b/org.adempiere.server-feature/server.product.functionaltest.launch
index 28861aa5ac..36707c3a71 100644
--- a/org.adempiere.server-feature/server.product.functionaltest.launch
+++ b/org.adempiere.server-feature/server.product.functionaltest.launch
@@ -197,6 +197,7 @@
+
diff --git a/org.adempiere.server-feature/server.product.launch b/org.adempiere.server-feature/server.product.launch
index fef50c0513..c49b806bcd 100644
--- a/org.adempiere.server-feature/server.product.launch
+++ b/org.adempiere.server-feature/server.product.launch
@@ -201,6 +201,7 @@
+
diff --git a/org.idempiere.p2.targetplatform/maven.locations.xml b/org.idempiere.p2.targetplatform/maven.locations.xml
index 0c53948298..aa930b3714 100644
--- a/org.idempiere.p2.targetplatform/maven.locations.xml
+++ b/org.idempiere.p2.targetplatform/maven.locations.xml
@@ -834,6 +834,12 @@ Export-Package: *;version="${version}";-noimport:=true
3.1.18
jar
+
+ org.codehaus.jettison
+ jettison
+ 1.4.1
+ jar
+
org.dom4j
dom4j
diff --git a/org.idempiere.p2.targetplatform/org.idempiere.p2.targetplatform.target b/org.idempiere.p2.targetplatform/org.idempiere.p2.targetplatform.target
index f27d9cd1b9..1c7b18a166 100644
--- a/org.idempiere.p2.targetplatform/org.idempiere.p2.targetplatform.target
+++ b/org.idempiere.p2.targetplatform/org.idempiere.p2.targetplatform.target
@@ -1,7 +1,7 @@
-
+
@@ -967,6 +967,12 @@ Export-Package: *;version="${version}";-noimport:=true
3.1.18
jar
+
+ org.codehaus.jettison
+ jettison
+ 1.4.1
+ jar
+
org.dom4j
dom4j
diff --git a/org.idempiere.test/idempiere.unit.test.launch b/org.idempiere.test/idempiere.unit.test.launch
index a7ba0cc5f2..4b3251cbce 100644
--- a/org.idempiere.test/idempiere.unit.test.launch
+++ b/org.idempiere.test/idempiere.unit.test.launch
@@ -159,6 +159,7 @@
+
diff --git a/org.idempiere.webservices-feature/feature.xml b/org.idempiere.webservices-feature/feature.xml
index c23652b400..b385d7d022 100644
--- a/org.idempiere.webservices-feature/feature.xml
+++ b/org.idempiere.webservices-feature/feature.xml
@@ -332,4 +332,11 @@
version="0.0.0"
unpack="false"/>
+
+
diff --git a/org.idempiere.webservices/META-INF/MANIFEST.MF b/org.idempiere.webservices/META-INF/MANIFEST.MF
index 9419b8a0a1..2da1abadf0 100644
--- a/org.idempiere.webservices/META-INF/MANIFEST.MF
+++ b/org.idempiere.webservices/META-INF/MANIFEST.MF
@@ -105,7 +105,8 @@ Require-Bundle: org.adempiere.base;bundle-version="0.0.0",
wrapped.org.springframework.spring-core;bundle-version="5.2.15",
wrapped.org.springframework.spring-expression;bundle-version="5.2.15",
wrapped.org.apache.xmlbeans.xmlbeans;bundle-version="3.1.0",
- wrapped.org.springframework.spring-web;bundle-version="5.2.15"
+ wrapped.org.springframework.spring-web;bundle-version="5.2.15",
+ org.codehaus.jettison.jettison;bundle-version="1.4.1"
Bundle-ClassPath: .,
lib/idempiere-xmlbeans.jar
Export-Package: org.compiere.model,
diff --git a/org.idempiere.webservices/META-INF/cxf/rest-context.xml b/org.idempiere.webservices/META-INF/cxf/rest-context.xml
index 6d22ac05f4..0deccfe408 100644
--- a/org.idempiere.webservices/META-INF/cxf/rest-context.xml
+++ b/org.idempiere.webservices/META-INF/cxf/rest-context.xml
@@ -19,6 +19,7 @@ http://cxf.apache.org/schemas/jaxrs.xsd">
+
@@ -27,4 +28,7 @@ http://cxf.apache.org/schemas/jaxrs.xsd">
+
+
\ No newline at end of file
diff --git a/org.idempiere.webservices/WEB-INF/src/org/idempiere/adinterface/ModelADService.java b/org.idempiere.webservices/WEB-INF/src/org/idempiere/adinterface/ModelADService.java
index 1f8f5ccf9a..155d459b31 100644
--- a/org.idempiere.webservices/WEB-INF/src/org/idempiere/adinterface/ModelADService.java
+++ b/org.idempiere.webservices/WEB-INF/src/org/idempiere/adinterface/ModelADService.java
@@ -49,8 +49,8 @@ import org.idempiere.adInterface.x10.StandardResponseDocument;
import org.idempiere.adInterface.x10.WindowTabDataDocument;
@Path("/model_adservice/")
-@Consumes("application/xml")
-@Produces("application/xml")
+@Consumes({"application/xml", "application/json"})
+@Produces({"application/xml", "application/json"})
@WebService(targetNamespace="http://idempiere.org/ADInterface/1_0")
@SOAPBinding(style=Style.RPC,use=Use.LITERAL,parameterStyle=ParameterStyle.WRAPPED)
public interface ModelADService {
diff --git a/org.idempiere.webservices/WEB-INF/src/org/idempiere/jaxrs/provider/xmlbeans/XMLBeansJSONProvider.java b/org.idempiere.webservices/WEB-INF/src/org/idempiere/jaxrs/provider/xmlbeans/XMLBeansJSONProvider.java
new file mode 100644
index 0000000000..bb5aac378f
--- /dev/null
+++ b/org.idempiere.webservices/WEB-INF/src/org/idempiere/jaxrs/provider/xmlbeans/XMLBeansJSONProvider.java
@@ -0,0 +1,201 @@
+/***********************************************************************
+ * This file is part of iDempiere ERP Open Source *
+ * http://www.idempiere.org *
+ * *
+ * Copyright (C) Contributors *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
+ * MA 02110-1301, USA. *
+ * *
+ * Contributors: *
+ * - hengsin *
+ **********************************************************************/
+package org.idempiere.jaxrs.provider.xmlbeans;
+
+/**
+ * @author hengsin
+ *
+ */
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.net.HttpURLConnection;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.Provider;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.cxf.jaxrs.provider.xmlbeans.XMLBeanStreamSerializer;
+import org.apache.cxf.jaxrs.provider.xmlbeans.XMLBeansElementProvider;
+import org.apache.xmlbeans.XmlObject;
+import org.codehaus.jettison.mapped.Configuration;
+import org.codehaus.jettison.mapped.MappedXMLOutputFactory;
+import org.idempiere.jettison.mapped.CustomMappedNamespaceConvention;
+import org.idempiere.jettison.mapped.MappedXMLInputFactory;
+
+/**
+ * JSON provider for XMLBeans data objects.
+ */
+@Produces("application/json")
+@Consumes("application/json")
+@Provider
+public class XMLBeansJSONProvider extends XMLBeansElementProvider {
+
+ private static final String AD_INTERFACE_1_0_NAMESPACE = "http://idempiere.org/ADInterface/1_0";
+
+ /** {@inheritDoc} */
+ @Override
+ public XmlObject readFrom(Class type, Type genericType,
+ Annotation[] annotations, MediaType m,
+ MultivaluedMap headers, InputStream is)
+ throws IOException {
+ XmlObject result = null;
+
+ try {
+
+ Map nstojns = new HashMap();
+ nstojns.put(AD_INTERFACE_1_0_NAMESPACE, "");
+
+ Configuration conf = new Configuration(nstojns);
+ conf.setIgnoreNamespaces(false);
+ CustomMappedNamespaceConvention convention = new CustomMappedNamespaceConvention(conf);
+ convention.addNamespacePrefix("i", AD_INTERFACE_1_0_NAMESPACE);
+ MappedXMLInputFactory factory = new MappedXMLInputFactory(convention);
+ XMLStreamReader xsr = factory.createXMLStreamReader(is);
+ result = parseXmlBean(type, xsr);
+
+ xsr.close();
+ } catch (XMLStreamException e) {
+ throw new WebApplicationException(HttpURLConnection.HTTP_INTERNAL_ERROR);
+ }
+
+ return result;
+ }
+
+ /**
+ * Create an XMLBean data object using a stream Reader
+ *
+ * @param type declared type of the desired XMLBean data object
+ * @param reader
+ * @return an instance of the required object, otherwise null
+ */
+ protected XmlObject parseXmlBean(Class> type, XMLStreamReader xsr) {
+ XmlObject result = null;
+
+ Class> factory = getFactory(type);
+
+ try {
+
+ // get factory method parse(InputStream)
+ Method m = factory.getMethod("parse", XMLStreamReader.class);
+ Object[] args = {xsr};
+ Object obj = m.invoke(type, args);
+
+ if (obj instanceof XmlObject) {
+ result = (XmlObject)obj;
+ }
+
+ } catch (NoSuchMethodException nsme) {
+ nsme.printStackTrace();
+ } catch (InvocationTargetException ite) {
+ ite.printStackTrace();
+ } catch (IllegalAccessException iae) {
+ iae.printStackTrace();
+ }
+
+ return result;
+ }
+
+ /**
+ * Locate the XMLBean Factory
inner class.
+ *
+ * @param type
+ * @return the Factory class if present, otherwise null.
+ */
+ private Class> getFactory(Class> type) {
+ Class> result = null;
+
+ Class>[] declared = type.getDeclaredClasses();
+ for (Class> c : declared) {
+
+ if (c.getSimpleName().equals("Factory")) {
+ result = c;
+ }
+ }
+
+ if (result == null) {
+ Class>[] interfaces = type.getInterfaces();
+
+ // look for XMLBeans inner class Factory
+ for (Class> inter : interfaces) {
+
+ declared = inter.getDeclaredClasses();
+
+ for (Class> c : declared) {
+
+ if (c.getSimpleName().equals("Factory")) {
+ result = c;
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void writeTo(XmlObject obj, Class> cls, Type genericType, Annotation[] annotations,
+ MediaType m, MultivaluedMap headers, OutputStream os) {
+
+ try {
+
+ // Set up the JSON StAX implementation
+ Map nstojns = new HashMap();
+ Configuration conf = new Configuration(nstojns);
+ conf.setIgnoreNamespaces(true);
+ XMLOutputFactory factory = new MappedXMLOutputFactory(conf);
+ XMLStreamWriter xsw = factory.createXMLStreamWriter(os);
+ xsw.writeStartDocument();
+ if (obj instanceof XmlObject) {
+
+ XmlObject xObj = obj;
+ XMLBeanStreamSerializer ser = new XMLBeanStreamSerializer();
+ ser.serialize(xObj, xsw);
+ }
+
+ xsw.flush();
+ xsw.close();
+
+ } catch (XMLStreamException e) {
+ throw new WebApplicationException(HttpURLConnection.HTTP_INTERNAL_ERROR);
+ } catch (IOException ioe) {
+ throw new WebApplicationException(HttpURLConnection.HTTP_INTERNAL_ERROR);
+ }
+ }
+}
diff --git a/org.idempiere.webservices/WEB-INF/src/org/idempiere/jettison/mapped/CustomMappedNamespaceConvention.java b/org.idempiere.webservices/WEB-INF/src/org/idempiere/jettison/mapped/CustomMappedNamespaceConvention.java
new file mode 100644
index 0000000000..3d8058e848
--- /dev/null
+++ b/org.idempiere.webservices/WEB-INF/src/org/idempiere/jettison/mapped/CustomMappedNamespaceConvention.java
@@ -0,0 +1,104 @@
+/***********************************************************************
+ * This file is part of iDempiere ERP Open Source *
+ * http://www.idempiere.org *
+ * *
+ * Copyright (C) Contributors *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
+ * MA 02110-1301, USA. *
+ * *
+ * Contributors: *
+ * - hengsin *
+ **********************************************************************/
+package org.idempiere.jettison.mapped;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.codehaus.jettison.Node;
+import org.codehaus.jettison.mapped.Configuration;
+import org.codehaus.jettison.mapped.MappedNamespaceConvention;
+
+/**
+ * @author hengsin
+ *
+ */
+public class CustomMappedNamespaceConvention extends MappedNamespaceConvention {
+
+ private Map namespacePrefix;
+ private Map namespacePrefixReversed;
+
+ /**
+ * @param config
+ */
+ public CustomMappedNamespaceConvention(Configuration config) {
+ super(config);
+ namespacePrefix = new HashMap();
+ namespacePrefixReversed = new HashMap();
+ }
+
+ /**
+ * @param prefix namespace prefix
+ * @param uri namespace uri
+ */
+ public void addNamespacePrefix(String prefix, String uri) {
+ namespacePrefix.put(uri, prefix);
+ namespacePrefixReversed.put(prefix, uri);
+ }
+
+ /* (non-Javadoc)
+ * @see org.codehaus.jettison.mapped.MappedNamespaceConvention#createQName(java.lang.String, org.codehaus.jettison.Node)
+ */
+ @Override
+ public QName createQName(String rootName, Node node) {
+ int dot = rootName.lastIndexOf( '.' );
+ QName qname = null;
+ String local = rootName;
+
+ if ( dot == -1 ) {
+ dot = 0;
+ }
+ else {
+ local = local.substring( dot + 1 );
+ }
+
+ String jns = rootName.substring( 0, dot );
+ String xns = (String) getNamespaceURI( jns );
+
+ if ( xns == null ) {
+ qname = new QName( rootName );
+ }
+ else {
+ String prefix = namespacePrefix.get(xns);
+ if (prefix != null && prefix.trim().length() > 0)
+ {
+ qname = new QName( xns, local, prefix );
+ if (node.getObject() != null && namespacePrefixReversed.isEmpty())
+ node.setNamespace(prefix, xns);
+ }
+ else
+ qname = new QName( xns, local );
+ }
+
+ if (!namespacePrefixReversed.isEmpty()) {
+ node.setNamespaces(namespacePrefixReversed);
+ }
+ return qname;
+ }
+
+
+}
diff --git a/org.idempiere.webservices/WEB-INF/src/org/idempiere/jettison/mapped/MappedXMLInputFactory.java b/org.idempiere.webservices/WEB-INF/src/org/idempiere/jettison/mapped/MappedXMLInputFactory.java
new file mode 100644
index 0000000000..dddaffe1fd
--- /dev/null
+++ b/org.idempiere.webservices/WEB-INF/src/org/idempiere/jettison/mapped/MappedXMLInputFactory.java
@@ -0,0 +1,76 @@
+/***********************************************************************
+ * This file is part of iDempiere ERP Open Source *
+ * http://www.idempiere.org *
+ * *
+ * Copyright (C) Contributors *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
+ * MA 02110-1301, USA. *
+ * *
+ * Contributors: *
+ * - hengsin *
+ **********************************************************************/
+package org.idempiere.jettison.mapped;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.codehaus.jettison.AbstractXMLInputFactory;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.codehaus.jettison.json.JSONTokener;
+import org.codehaus.jettison.mapped.MappedNamespaceConvention;
+import org.codehaus.jettison.mapped.MappedXMLStreamReader;
+
+/**
+ * @author hengsin
+ *
+ */
+public class MappedXMLInputFactory extends AbstractXMLInputFactory {
+
+
+ private MappedNamespaceConvention convention;
+
+ /**
+ *
+ * @param convention
+ */
+ public MappedXMLInputFactory(MappedNamespaceConvention convention) {
+ this.convention = convention;
+ }
+
+ /**
+ * @param tokener
+ * @return {@link XMLStreamReader}
+ */
+ public XMLStreamReader createXMLStreamReader(JSONTokener tokener) throws XMLStreamException {
+ try {
+ JSONObject root = createJSONObject(tokener);
+ return new MappedXMLStreamReader(root, convention);
+ } catch (JSONException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ /**
+ *
+ * @param tokener
+ * @return {@link JSONObject}
+ * @throws JSONException
+ */
+ protected JSONObject createJSONObject(JSONTokener tokener) throws JSONException {
+ return new JSONObject(tokener);
+ }
+}
diff --git a/org.idempiere.webservices/testScripts/iDempiereWebServices-soapui-project.xml b/org.idempiere.webservices/testScripts/iDempiereWebServices-soapui-project.xml
index 0839ad9ffd..2a84e146a2 100644
--- a/org.idempiere.webservices/testScripts/iDempiereWebServices-soapui-project.xml
+++ b/org.idempiere.webservices/testScripts/iDempiereWebServices-soapui-project.xml
@@ -1,5 +1,5 @@
-https://localhost:8443/ADInterface/services/ModelADService?wsdl
+https://localhost:8443/ADInterface/services/ModelADService?wsdl
@@ -461,7 +461,7 @@
-]]>http://schemas.xmlsoap.org/wsdl/https://localhost:8443/ADInterface/services/ModelADServiceUTF-8https://localhost:8443/ADInterface/services/ModelADService
+]]>http://schemas.xmlsoap.org/wsdl/https://localhost:8443/ADInterface/services/ModelADServiceUTF-8https://localhost:8443/ADInterface/services/ModelADService
<_0:createData>
@@ -511,7 +511,7 @@
-]]>Global HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/ModelADService
+]]>Global HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/ModelADService
<_0:deleteData>
@@ -535,7 +535,7 @@
-]]>Global HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/ModelADService
+]]>Global HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/ModelADService
<_0:getList>
@@ -558,7 +558,7 @@
-]]>Global HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/ModelADService
+]]>Global HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/ModelADService
<_0:queryData>
@@ -587,7 +587,7 @@
-]]>Global HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/ModelADService
+]]>BasicBasicGlobal HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/ModelADService
<_0:readData>
@@ -611,7 +611,7 @@
-]]>Global HTTP SettingsExample on how to run report Storage Detail with HQ Warehouse and Patio Chair as parameters You need to define web service security for: Web Service Type: RunStorageDetail Web Service Parameters: AD_Process_ID Constant 236 AD_Menu_ID Constant 0 AD_Record_ID Constant 0 And allow execution to the WebService role on the report. UTF-8https://localhost:8443/ADInterface/services/ModelADService
+]]>BasicBasicGlobal HTTP SettingsExample on how to run report Storage Detail with HQ Warehouse and Patio Chair as parameters You need to define web service security for: Web Service Type: RunStorageDetail Web Service Parameters: AD_Process_ID Constant 236 AD_Menu_ID Constant 0 AD_Record_ID Constant 0 And allow execution to the WebService role on the report. UTF-8https://localhost:8443/ADInterface/services/ModelADService
<_0:runProcess>
@@ -637,7 +637,7 @@
-]]>Global HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/ModelADService
+]]>Global HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/ModelADService
<_0:runProcess>
@@ -658,7 +658,7 @@
-]]>Global HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/ModelADService
+]]>Global HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/ModelADService
<_0:setDocAction>
@@ -682,7 +682,7 @@
-]]>Global HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/ModelADService
+]]>Global HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/ModelADService
<_0:updateData>
@@ -711,4 +711,36 @@
-]]>Global HTTP Settings
\ No newline at end of file
+]]>Global HTTP SettingsUTF-8https://localhost:8443/ADInterface/services/rest/model_adservice/query_data{
+ "ModelCRUDRequest": {
+ "ModelCRUD": {
+ "serviceType": "QueryBPartner",
+ "TableName": "C_BPartner",
+ "Filter": "name < 'S'",
+ "Action": "Read",
+ "DataRow": { //optional filter by column values
+ "field": [
+ {
+ "@column": "C_BP_Group_ID",
+ "val": "103"
+ }
+ ]
+ }
+ },
+ "ADLoginRequest": {
+ "user": "WebService",
+ "pass": "WebService",
+ "lang": "en_US",
+ "ClientID": "11",
+ "RoleID": "50004",
+ "OrgID": "11",
+ "WarehouseID": "103",
+ "stage": "9"
+ }
+ }
+}
+
+BasicBasicGlobal HTTP Settings
\ No newline at end of file