Author: jleroux
Date: Sat Feb 11 10:50:56 2012 New Revision: 1243026 URL: http://svn.apache.org/viewvc?rev=1243026&view=rev Log: OFBiz SOAP implementation was not handling * null values in Map * BigDecimal * correctly TimeStamp format (we use xsd:dateTime in ModelService.getTypes()) So CXF was not able to unmarshall a List of Maps with those types in them. It does not introduce any regressions: * A new specific SOAP null type is introduced using ("nillable","true") and ("xsi:nil","true) attributes. I had also to set the http://www.w3.org/2001/XMLSchema-instance schema on the null node. Because it was impossible to add it in the envelope header, not a big deal anyway. * I introduced a 'T' in the TimeStamp format. It's is OK, the deserialisation handles it well (we use xsd:dateTime, see http://www.w3.org/TR/xmlschema-2/#dateTime)/. We don't handle TimeZone... * BigDecimal was missing and is now correctly handled. I used 10 decimals and half up rounding (ROUND_HALF_UP) Also improves the SOAPEventHandler.sendError() method by passing the serviceName in the message Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/serialize/XmlSerializer.java ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelService.java ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/SOAPEventHandler.java Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/serialize/XmlSerializer.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/serialize/XmlSerializer.java?rev=1243026&r1=1243025&r2=1243026&view=diff ============================================================================== --- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/serialize/XmlSerializer.java (original) +++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/serialize/XmlSerializer.java Sat Feb 11 10:50:56 2012 @@ -22,6 +22,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.Serializable; import java.lang.ref.WeakReference; +import java.math.BigDecimal; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -130,7 +131,7 @@ public class XmlSerializer { public static Element serializeSingle(Object object, Document document) throws SerializeException { if (document == null) return null; - if (object == null) return document.createElement("null"); + if (object == null) return makeElement("null", object, document); // - Standard Objects - if (object instanceof String) { @@ -147,9 +148,13 @@ public class XmlSerializer { return makeElement("std-Boolean", object, document); } else if (object instanceof Locale) { return makeElement("std-Locale", object, document); + } else if (object instanceof BigDecimal) { + String stringValue = ((BigDecimal) object).setScale(10, BigDecimal.ROUND_HALF_UP).toString(); + return makeElement("std-BigDecimal", stringValue, document); // - SQL Objects - } else if (object instanceof java.sql.Timestamp) { - return makeElement("sql-Timestamp", object, document); + String stringValue = object.toString().replace(' ', 'T'); + return makeElement("sql-Timestamp", stringValue, document); } else if (object instanceof java.sql.Date) { return makeElement("sql-Date", object, document); } else if (object instanceof java.sql.Time) { @@ -268,7 +273,15 @@ public class XmlSerializer { } public static Element makeElement(String elementName, Object value, Document document) { - if (value == null) return document.createElement("null"); + if (value == null) { + Element element = document.createElement("null"); + element.setAttribute("xsi:nil", "true"); + // I tried to put the schema in the envelope header (in createAndSendSOAPResponse) + // resEnv.declareNamespace("http://www.w3.org/2001/XMLSchema-instance", null); + // But it gets prefixed and that does not work. So adding in each instance + element.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); + return element; + } Element element = document.createElement(elementName); element.setAttribute("value", value.toString()); Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelService.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelService.java?rev=1243026&r1=1243025&r2=1243026&view=diff ============================================================================== --- ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelService.java (original) +++ ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelService.java Sat Feb 11 10:50:56 2012 @@ -1365,6 +1365,18 @@ public class ModelService extends Abstra /*--------- Standard Objects --------*/ /*-----------------------------------*/ + /* null Element */ + Element stdNullElement = document.createElement("xsd:element"); + stdNullElement.setAttribute("name", "null"); + Element stdNullElement0 = document.createElement("xsd:complexType"); + stdNullElement.appendChild(stdNullElement0); + Element stdNullElement1 = document.createElement("xsd:attribute"); + stdNullElement0.appendChild(stdNullElement1); + stdNullElement1.setAttribute("name", "value"); + stdNullElement1.setAttribute("type", "xsd:string"); + stdNullElement1.setAttribute("use", "required"); + stdNullElement1.setAttribute("nillable", "true"); + schema.appendChild(stdNullElement); /* std-String Element */ Element stdStringElement = document.createElement("xsd:element"); stdStringElement.setAttribute("name", "std-String"); @@ -1442,6 +1454,17 @@ public class ModelService extends Abstra stdLocaleElement1.setAttribute("type", "xsd:string"); stdLocaleElement1.setAttribute("use", "required"); schema.appendChild(stdLocaleElement); + /* std-BigDecimal Element */ + Element stdBigDecimalElement = document.createElement("xsd:element"); + stdBigDecimalElement.setAttribute("name", "std-BigDecimal"); + Element stdBigDecimalElement0 = document.createElement("xsd:complexType"); + stdBigDecimalElement.appendChild(stdBigDecimalElement0); + Element stdBigDecimalElement1 = document.createElement("xsd:attribute"); + stdBigDecimalElement0.appendChild(stdBigDecimalElement1); + stdBigDecimalElement1.setAttribute("name", "value"); + stdBigDecimalElement1.setAttribute("type", "xsd:decimal"); + stdBigDecimalElement1.setAttribute("use", "required"); + schema.appendChild(stdBigDecimalElement); /*-----------------------------------*/ /*----------- SQL Objects -----------*/ @@ -1652,6 +1675,12 @@ public class ModelService extends Abstra mapValueComplexType.setAttribute("name", "map-Value"); Element mapValueComplexType0 = document.createElement("xsd:choice"); mapValueComplexType.appendChild(mapValueComplexType0); + Element mapValueComplexTypeNull = document.createElement("xsd:element"); + mapValueComplexTypeNull.setAttribute("ref", "tns:null"); + mapValueComplexTypeNull.setAttribute("minOccurs", "1"); + mapValueComplexTypeNull.setAttribute("maxOccurs", "1"); + mapValueComplexTypeNull.setAttribute("nillable", "true"); + mapValueComplexType0.appendChild(mapValueComplexTypeNull); Element mapValueComplexType1 = document.createElement("xsd:element"); mapValueComplexType1.setAttribute("ref", "tns:std-String"); mapValueComplexType1.setAttribute("minOccurs", "1"); @@ -1778,12 +1807,24 @@ public class ModelService extends Abstra mapValueComplexType25.setAttribute("maxOccurs", "1"); mapValueComplexType0.appendChild(mapValueComplexType25); schema.appendChild(mapValueComplexType); + Element mapValueComplexType26 = document.createElement("xsd:element"); + mapValueComplexType26.setAttribute("ref", "tns:std-BigDecimal"); + mapValueComplexType26.setAttribute("minOccurs", "1"); + mapValueComplexType26.setAttribute("maxOccurs", "1"); + mapValueComplexType0.appendChild(mapValueComplexType26); + schema.appendChild(mapValueComplexType); /* col-Collection Complex Type */ Element colCollectionComplexType = document.createElement("xsd:complexType"); colCollectionComplexType.setAttribute("name", "col-Collection"); Element colCollectionComplexType0 = document.createElement("xsd:choice"); colCollectionComplexType.appendChild(colCollectionComplexType0); + Element colCollectionComplexTypeNull = document.createElement("xsd:element"); + colCollectionComplexTypeNull.setAttribute("ref", "tns:null"); + colCollectionComplexTypeNull.setAttribute("minOccurs", "0"); + colCollectionComplexTypeNull.setAttribute("maxOccurs", "unbounded"); + colCollectionComplexTypeNull.setAttribute("nillable", "true"); + colCollectionComplexType0.appendChild(colCollectionComplexTypeNull); Element colCollectionComplexType1 = document.createElement("xsd:element"); colCollectionComplexType1.setAttribute("ref", "tns:std-String"); colCollectionComplexType1.setAttribute("minOccurs", "0"); @@ -1910,6 +1951,12 @@ public class ModelService extends Abstra colCollectionComplexType25.setAttribute("maxOccurs", "unbounded"); colCollectionComplexType0.appendChild(colCollectionComplexType25); schema.appendChild(colCollectionComplexType); + Element colCollectionComplexType26 = document.createElement("xsd:element"); + colCollectionComplexType26.setAttribute("ref", "tns:std-BigDecimal"); + colCollectionComplexType26.setAttribute("minOccurs", "0"); + colCollectionComplexType26.setAttribute("maxOccurs", "unbounded"); + colCollectionComplexType0.appendChild(colCollectionComplexType26); + schema.appendChild(colCollectionComplexType); types.setDocumentationElement(schema); return types; Modified: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/SOAPEventHandler.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/SOAPEventHandler.java?rev=1243026&r1=1243025&r2=1243026&view=diff ============================================================================== --- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/SOAPEventHandler.java (original) +++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/SOAPEventHandler.java Sat Feb 11 10:50:56 2012 @@ -56,7 +56,6 @@ import org.ofbiz.service.ServiceUtil; import org.ofbiz.service.engine.SoapSerializer; import org.ofbiz.webapp.control.ConfigXMLReader.Event; import org.ofbiz.webapp.control.ConfigXMLReader.RequestMap; -import org.ofbiz.webapp.control.ConfigXMLReader; import org.ofbiz.webapp.control.RequestHandler; import org.w3c.dom.Document; @@ -97,7 +96,7 @@ public class SOAPEventHandler implements } catch (GenericServiceException e) { serviceName = null; } catch (WSDLException e) { - sendError(response, "Unable to obtain WSDL"); + sendError(response, "Unable to obtain WSDL", serviceName); throw new EventHandlerException("Unable to obtain WSDL", e); } @@ -112,7 +111,7 @@ public class SOAPEventHandler implements } return null; } else { - sendError(response, "Unable to obtain WSDL"); + sendError(response, "Unable to obtain WSDL", serviceName); throw new EventHandlerException("Unable to obtain WSDL"); } } @@ -137,7 +136,7 @@ public class SOAPEventHandler implements writer.flush(); return null; } catch (Exception e) { - sendError(response, "Unable to obtain WSDL"); + sendError(response, "Unable to obtain WSDL", null); throw new EventHandlerException("Unable to obtain WSDL"); } } @@ -163,30 +162,31 @@ public class SOAPEventHandler implements } } } catch (Exception e) { - sendError(response, "Problem processing the service"); + sendError(response, "Problem processing the service", null); throw new EventHandlerException("Cannot get the envelope", e); } Debug.logVerbose("[Processing]: SOAP Event", module); + String serviceName = null; try { SOAPBody reqBody = reqEnv.getBody(); validateSOAPBody(reqBody); OMElement serviceElement = reqBody.getFirstElement(); - String serviceName = serviceElement.getLocalName(); + serviceName = serviceElement.getLocalName(); Map<String, Object> parameters = UtilGenerics.cast(SoapSerializer.deserialize(serviceElement.toString(), delegator)); try { // verify the service is exported for remote execution and invoke it ModelService model = dispatcher.getDispatchContext().getModelService(serviceName); if (model == null) { - sendError(response, "Problem processing the service"); + sendError(response, "Problem processing the service", serviceName); Debug.logError("Could not find Service [" + serviceName + "].", module); return null; } if (!model.export) { - sendError(response, "Problem processing the service"); + sendError(response, "Problem processing the service", serviceName); Debug.logError("Trying to call Service [" + serviceName + "] that is not exported.", module); return null; } @@ -198,19 +198,19 @@ public class SOAPEventHandler implements } catch (GenericServiceException e) { if (UtilProperties.getPropertyAsBoolean("service", "secureSoapAnswer", true)) { - sendError(response, "Problem processing the service, check your parameters."); + sendError(response, "Problem processing the service, check your parameters.", serviceName); } else { if(e.getMessageList() == null) { - sendError(response, e.getMessage()); + sendError(response, e.getMessage(), serviceName); } else { - sendError(response, e.getMessageList()); + sendError(response, e.getMessageList(), serviceName); } Debug.logError(e, module); return null; } } } catch (Exception e) { - sendError(response, e.getMessage()); + sendError(response, e.getMessage(), serviceName); Debug.logError(e, module); return null; } @@ -236,6 +236,7 @@ public class SOAPEventHandler implements // setup the response Debug.logVerbose("[EventHandler] : Setting up response message", module); String xmlResults = SoapSerializer.serialize(serviceResults); + //Debug.log("xmlResults ==================" + xmlResults, module); XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(xmlResults)); StAXOMBuilder resultsBuilder = new StAXOMBuilder(reader); OMElement resultSer = resultsBuilder.getDocumentElement(); @@ -272,15 +273,15 @@ public class SOAPEventHandler implements } } - private void sendError(HttpServletResponse res, String errorMessage) throws EventHandlerException { + private void sendError(HttpServletResponse res, String errorMessage, String serviceName) throws EventHandlerException { // setup the response - sendError(res, ServiceUtil.returnError(errorMessage)); + sendError(res, ServiceUtil.returnError(errorMessage), serviceName); } - private void sendError(HttpServletResponse res, List<String> errorMessages) throws EventHandlerException { - sendError(res, ServiceUtil.returnError(errorMessages)); + private void sendError(HttpServletResponse res, List<String> errorMessages, String serviceName) throws EventHandlerException { + sendError(res, ServiceUtil.returnError(errorMessages.toString()), serviceName); } - private void sendError(HttpServletResponse res, Object object) throws EventHandlerException { + private void sendError(HttpServletResponse res, Object object, String serviceName) throws EventHandlerException { try { // setup the response res.setContentType("text/xml"); @@ -293,11 +294,18 @@ public class SOAPEventHandler implements SOAPFactory factory = OMAbstractFactory.getSOAP11Factory(); SOAPEnvelope resEnv = factory.createSOAPEnvelope(); SOAPBody resBody = factory.createSOAPBody(); - OMElement errMsg = factory.createOMElement(new QName("Response")); + OMElement errMsg = factory.createOMElement(new QName((serviceName != null ? serviceName : "") + "Response")); errMsg.addChild(resultSer.getFirstElement()); resBody.addChild(errMsg); resEnv.addChild(resBody); + // The declareDefaultNamespace method doesn't work see (https://issues.apache.org/jira/browse/AXIS2-3156) + // so the following doesn't work: + // resService.declareDefaultNamespace(ModelService.TNS); + // instead, create the xmlns attribute directly: + OMAttribute defaultNS = factory.createOMAttribute("xmlns", null, ModelService.TNS); + errMsg.addAttribute(defaultNS); + // log the response message if (Debug.verboseOn()) { try { |
Free forum by Nabble | Edit this page |