tofindabhishek
tofindabhishek

Reputation: 121

SOAP MTOM functionality after ,Upgrading axiom-impl-1.2.20.jar to axiom-impl-1.4.0.jar throws NULL Pointer for Datahandler

I have upgraded axiom-impl-1.2.20.jar to axiom-impl-1.4.0.jar and its corresponding jars axiom jars However , I am facing a NullPointerException issue in the existing code which is used for SOAP-MTOM functionality. Following is the stacktrace.

Caused by: java.lang.NullPointerException
    at org.apache.axiom.om.impl.OMMultipartWriter.writePart(OMMultipartWriter.java:165)
    at org.apache.axiom.om.impl.OMMultipartWriter.writePart(OMMultipartWriter.java:183)
    at org.apache.axiom.om.impl.llom.AxiomContainerImpl.serialize(Unknown Source)
    at org.apache.axiom.om.impl.llom.AxiomContainerImpl.serializeAndConsume(Unknown Source)

I did try to inject datahandler using following piece of code,check enableMTOM4SpecifiedNodes commented code however, after this change MTOM functionality does not seem to work

String soapVersion = config.soapVersion;
        String soapAction = config.soapAction;
        soap.getSOAPMessage().saveChanges();//save current changes
        MimeHeaders mhs = soap.getMimeHeaders();
        String[] contentTypes = mhs.getHeader("Content-Type");
        ContentType cType = new ContentType(contentTypes[0]);
        String boundary = cType.getParameter("boundary");
        if (boundary == null) {
            boundary = DCMimeMessage.getRFC2822MsgID().replace(DCMimeMessage.CH_AT, BCMimeMessage.CH_DOT);
        }
        String start = cType.getParameter("start");
        if (start == null) {
            start = DCMimeMessage.getRFC2822MsgID();//need to be fixed using standard
        } else {
            if (start.startsWith("<")) {
                start = start.substring(1);
                if (start.endsWith(">")) {
                    start = start.substring(0, start.length()-1);
                }
            }
        }
        
        String primaryType = cType.getPrimaryType();
        String subType = cType.getSubType();
        String startinfo = null;
        if (StringUtils.equalsIgnoreCase(primaryType, "multipart")) {
            startinfo = cType.getParameter("type");
        } else if (StringUtils.equalsIgnoreCase(primaryType, "application")
            && StringUtils.equalsIgnoreCase(subType, "soap+xml")) {
            startinfo = DCSoapConstants.BCSOAP_12_CONTENTTYPE;
        } else if (StringUtils.equalsIgnoreCase(primaryType, "text")
                && StringUtils.equalsIgnoreCase(subType, "xml")) {
            startinfo = DCSoapConstants.BCSOAP_11_CONTENTTYPE;
        }
        if (startinfo == null) {
            if (StringUtils.equalsIgnoreCase(soapVersion, SOAPConstants.SOAP_1_1_PROTOCOL)) {
                startinfo = DCSoapConstants.BCSOAP_11_CONTENTTYPE;
            } else {
                startinfo = DCSoapConstants.BCSOAP_12_CONTENTTYPE;
            }
        }
        startinfo = "start-info=\"" + startinfo + "\"";
        if(StringUtils.equalsIgnoreCase(soapVersion, SOAPConstants.SOAP_1_2_PROTOCOL)
                && soapAction != null) {
            startinfo = startinfo + "; action=\"" + soapAction + "\"";
        }
        

        mmh.addHeader("Content-Type", "Multipart/Related;boundary=\"" 
                + boundary + "\";type=\"application/xop+xml\";start=\"<" 
                + start + ">\";" + startinfo);
        SOAPEnvelope env = soap.getSOAPEnvelope();
        org.apache.axiom.soap.SOAPEnvelope omEnv = null;
        if (env instanceof org.apache.axis2.saaj.SOAPEnvelopeImpl) {
            omEnv = saaj.toOM(env);
        } else if (env instanceof org.apache.axiom.soap.SOAPEnvelope) {
            omEnv = (org.apache.axiom.soap.SOAPEnvelope)env;
        } else {
            return null;
        }
         
        if (omEnv == null) {
            return null;
        }
        omEnv.declareNamespace("http://www.w3.org/2004/08/xop/include", "xop");
        Iterator children = omEnv.getBody().getChildElements();
        if (children != null && children.hasNext()) {
            HashMap<String, Boolean> tagNamesUsedMap = new HashMap<String, Boolean>();
            for (int i=0, s=tagNames.size(); i<s; i++) {
                tagNamesUsedMap.put(tagNames.get(i), false);
            }
            enableMTOM4SpecifiedNodes(children, tagNamesUsedMap);
            List<String> notUsedTagNames = getNotUsedTagNames(tagNamesUsedMap);
            if (!notUsedTagNames.isEmpty()) {
                throw new D2CException("tagNames is given, but some of the items is not used : " + notUsedTagNames);
            }
        } else {
            if (tagNames != null) {
                throw new D2CException("tagNames is given, but there isn't any payload found.");
            }
        }
        OMOutputFormat format = new OMOutputFormat();
        format.setDoOptimize(true);
        format.setSOAP11(StringUtils.equalsIgnoreCase(soapVersion, SOAPConstants.SOAP_1_1_PROTOCOL));
        format.setMimeBoundary(boundary);
        if (start != null) {
            format.setRootContentId(start);
        }
                
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        omEnv.serializeAndConsume(baos, format);
public static void enableMTOM4SpecifiedNodes(Iterator iter, HashMap<String, Boolean> tagNames) {
        while (iter.hasNext()) {
            Object obj = iter.next();
            if (obj instanceof OMElement) {
                OMElement ome = (OMElement) obj;
                OMFactory fac = OMAbstractFactory.getOMFactory();
                Iterator children = ome.getChildElements();
                if (children == null || !children.hasNext()) {
                    String nodeName = ome.getLocalName();
                    if (tagNames.containsKey(nodeName)) {
                        tagNames.put(nodeName, true);
                        Iterator niter = ome.getChildren();
                        while (niter.hasNext()) {
                            Object nobj = niter.next();
                            if (nobj instanceof OMText) {
                                OMText omt = (OMText)nobj;
//                              byte[] bytes = new String(omt.getTextCharacters()).getBytes(StandardCharsets.UTF_8);
//                              ByteArrayDataSource rawData = new ByteArrayDataSource(bytes);
//                              DataHandler datahandler = new DataHandler(rawData);
//                              omt = fac.createOMText(datahandler, true);
                                omt.setOptimize(true);
                            }
                        }
                    }
                } else {
                    enableMTOM4SpecifiedNodes(children, tagNames);
                }
            }
        }

Upvotes: 0

Views: 150

Answers (1)

Andreas Veithen
Andreas Veithen

Reputation: 9154

The minimal code to reproduce this is actually:

OMFactory factory = OMAbstractFactory.getOMFactory();
OMElement element = factory.createOMElement("root", null);
OMText text = factory.createOMText(element,
        Base64.getEncoder().encodeToString("foobar".getBytes(StandardCharsets.UTF_8)));
text.setOptimize(true);
OMOutputFormat format = new OMOutputFormat();
format.setDoOptimize(true);
element.serialize(System.out, format);

This is indeed a bug in Axiom versions 1.3.0 and later. I've created https://issues.apache.org/jira/browse/AXIOM-519 to track this issue.

Upvotes: 0

Related Questions