JAXB 解组不适用于 JDK 1.6

JAXB unmarshal won't work with JDK 1.6

是的,这是一个冗长无聊的发布问题,同时可能非常简单。 :(

我只是从 Java 调用一个用 .NET 平台实现的 SOAP WebService 接口。收到数据后,使用 JAXB.Everything 将其转换为 java 对象在 JDK1.8 中运行良好,但在 JDK1.6

中失败

我注意到解组过程在 GetBjxsDataResponse 级别停止。也就是说,我可以从信封主体中成功获得 GetBjxsDataResponse 的实例,但是该实例的 getBjxsDataResult 成员为空。

这与JAXB RI 版本有关吗?我是 java 世界的新手。需要你的帮助! :)

NamespaceMapper.java

import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper;

public class NamespaceMapper extends NamespacePrefixMapper {

    private static final String SOAP_PREFIX = "x";
    public static final String SOAP_URI = "http://schemas.xmlsoap.org/soap/envelope/";

    private static final String WS_PREFIX = "tem";
    public static final String WS_URI = "http://tempuri.org/";

    public static final String XMLSchema_URI = "http://www.w3.org/2001/XMLSchema";
    public static final String DIFFGR_URI = "urn:schemas-microsoft-com:xml-diffgram-v1";

    @Override
    public String getPreferredPrefix(String arg0, String arg1, boolean arg2) {
        if (SOAP_URI.equals(arg0))
            return SOAP_PREFIX;
        else if (WS_URI.equals(arg0))
            return WS_PREFIX;
        return arg1;
    }
}

Envelope.java

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Envelope", namespace = NamespaceMapper.SOAP_URI)
@XmlAccessorType(XmlAccessType.FIELD)
public class Envelope {

    @XmlElement(name = "Header", namespace = NamespaceMapper.SOAP_URI, required = false)
    private EnvelopeHeader header;

    @XmlElement(name = "Body", namespace = NamespaceMapper.SOAP_URI)
    private EnvelopeBody body;

    public EnvelopeHeader getHeader() {
        return header;
    }

    public void setHeader(EnvelopeHeader header) {
        this.header = header;
    }

    public EnvelopeBody getBody() {
        return body;
    }

    public void setBody(EnvelopeBody body) {
        this.body = body;
    }
}

EnvelopeHeader.java

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(namespace = NamespaceMapper.SOAP_URI)
public class EnvelopeHeader {

}

EnvelopeBody.java

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(namespace = NamespaceMapper.SOAP_URI)
public class EnvelopeBody {

    @XmlAnyElement(lax = true)
    private Object method;

    public Object getMethod() {
        return method;
    }

    public void setMethod(Object method) {
        this.method = method;
    }
}

import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "GetBjxsDataResponse", namespace = NamespaceMapper.WS_URI)
@XmlAccessorType(XmlAccessType.FIELD)
public class GetBjxsDataResponse extends ResponseCommon {

    @XmlAccessorType(XmlAccessType.FIELD)
    private static class GetBjxsDataResult {

        @XmlRootElement
        @XmlAccessorType(XmlAccessType.FIELD)
        private static class Diffgram {

            @XmlAccessorType(XmlAccessType.FIELD)
            private static class NewDataSet {

                @XmlElement(name = "Table")
                private List<Object> lists;
            }

            @XmlElement(name = "NewDataSet")
            private NewDataSet newDataSet;
        };

        @XmlElement
        private Object schema;

        @XmlElement
        private Diffgram diffgram;
    };

    @XmlElement(name="GetBjxsDataResult")
    private GetBjxsDataResult getBjxsDataResult;

    @Override
    public Object getValuableData() {
        return getBjxsDataResult.diffgram.newDataSet.lists;
    }
}

ResponseCommon.java

import javax.xml.bind.annotation.XmlTransient;

public abstract class ResponseCommon {

    @XmlTransient
    private String errorMessage;

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

    public abstract Object getValuableData();
}

GetBjxsDataResponse.java

import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "GetBjxsDataResponse", namespace = NamespaceMapper.WS_URI)
@XmlAccessorType(XmlAccessType.FIELD)
public class GetBjxsDataResponse extends ResponseCommon {

    @XmlAccessorType(XmlAccessType.FIELD)
    private static class GetBjxsDataResult {

        @XmlRootElement
        @XmlAccessorType(XmlAccessType.FIELD)
        private static class Diffgram {

            @XmlAccessorType(XmlAccessType.FIELD)
            private static class NewDataSet {

                @XmlElement(name = "Table")
                private List<Object> lists;
            }

            @XmlElement(name = "NewDataSet")
            private NewDataSet newDataSet;
        };

        @XmlElement
        private Object schema;

        @XmlElement
        private Diffgram diffgram;
    };

    @XmlElement(name="GetBjxsDataResult")
    private GetBjxsDataResult getBjxsDataResult;

    @Override
    public Object getValuableData() {
        return getBjxsDataResult.diffgram.newDataSet.lists;
    }
}

MainTest.java

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

public class MainTest {

    public static void main(String[] args) throws JAXBException {
        System.out.println("---");
        String str = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" 
                + "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> \n"
                + "<soap:Body> \n"
                    + "<GetBjxsDataResponse xmlns=\"http://tempuri.org/\"> \n"
                        + "<GetBjxsDataResult> \n"
                            + "<xs:schema id=\"NewDataSet\" xmlns=\"\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"     xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\"> \n"
                                + "<xs:element name=\"NewDataSet\" msdata:IsDataSet=\"true\" msdata:MainDataTable=\"Table\" msdata:UseCurrentLocale=\"true\"> \n"
                                    + "<xs:complexType> \n"
                                        + "<xs:choice minOccurs=\"0\" maxOccurs=\"unbounded\"> \n"
                                            + "<xs:element name=\"Table\"> \n"
                                                + "<xs:complexType> \n"
                                                    + "<xs:sequence> \n"
                                                        + "<xs:element name=\"xh\" type=\"xs:string\" minOccurs=\"0\" /> \n"
                                                        + "<xs:element name=\"bjbh\" type=\"xs:string\" minOccurs=\"0\" /> \n"
                                                        + "<xs:element name=\"bnbh\" type=\"xs:int\" minOccurs=\"0\" /> \n"
                                                        + "<xs:element name=\"xm\" type=\"xs:string\" minOccurs=\"0\" /> \n"
                                                        + "<xs:element name=\"bjmc\" type=\"xs:string\" minOccurs=\"0\" /> \n"
                                                    + "</xs:sequence> \n"
                                                + "</xs:complexType> \n"
                                            + "</xs:element> \n"
                                        + "</xs:choice> \n"
                                    + "</xs:complexType> \n"
                                + "</xs:element> \n"
                            + "</xs:schema> \n"
                            + "<diffgr:diffgram xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\" xmlns:diffgr=\"urn:schemas-microsoft-com:xml-diffgram-v1\"> \n"
                                + "<NewDataSet xmlns=\"\"> \n"
                                    + "<Table diffgr:id=\"Table1\" msdata:rowOrder=\"0\"> \n"
                                        + "<xh>320130001</xh> \n"
                                        + "<bjbh>3101</bjbh> \n"
                                        + "<bnbh>1</bnbh> \n"
                                        + "<xm>陈馨儿</xm> \n"
                                        + "<bjmc>高一(01)班          </bjmc> \n"
                                    + "</Table> \n"
                                    + "<Table diffgr:id=\"Table2\" msdata:rowOrder=\"1\"> \n"
                                        + "<xh>320130002</xh> \n"
                                        + "<bjbh>3101</bjbh> \n"
                                        + "<bnbh>2</bnbh> \n"
                                        + "<xm>丁灵</xm> \n"
                                        + "<bjmc>高一(01)班          </bjmc> \n"
                                    + "</Table> \n"
                                    + "<Table diffgr:id=\"Table3\" msdata:rowOrder=\"2\"> \n"
                                        + "<xh>320130003</xh> \n"
                                        + "<bjbh>3101</bjbh> \n"
                                        + "<bnbh>3</bnbh> \n"
                                        + "<xm>童欣欣</xm> \n"
                                        + "<bjmc>高一(01)班          </bjmc> \n"
                                    + "</Table> \n"
                                + "</NewDataSet> \n"
                            + "</diffgr:diffgram> \n"
                        + "</GetBjxsDataResult> \n"
                    + "</GetBjxsDataResponse> \n"
                + "</soap:Body> \n"
            + "</soap:Envelope> \n";
        System.out.println(str);

        JAXBContext jaxbContext2 =JAXBContext.newInstance(
            Envelope.class, GetBjxsDataResponse.class);

        InputStream is = new ByteArrayInputStream(str.getBytes());
        Unmarshaller unmarshaller = jaxbContext2.createUnmarshaller();
        Envelope responseEnvelope = (Envelope)unmarshaller.unmarshal(is);

        GetBjxsDataResponse getBjxsDataResponse = 
            (GetBjxsDataResponse)responseEnvelope.getBody().getMethod();

        @SuppressWarnings("unchecked")
        List<Object> bjxsDatas = (List<Object>)getBjxsDataResponse.getValuableData();
        System.out.println(bjxsDatas.size());
    }
}

最后我选择用JAXM api and turn the result to Java object instance by Java reflection解析XML格式的响应。