簡體   English   中英

在unmarshal期間,JAXb不會填充對象

[英]JAXb not populating object during unmarshal

我此時有點失落。 我絕不是SOAP / JAXb專家,但是,我正在嘗試創建一個泛型類,它將為任何服務編組/調用/解組。 我使用Weather Service wsdl作為證明這個概念的起點。

我終於得到了編組,調用和解組來執行而沒有錯誤,但是,響應對象沒有被填充。 任何人都可以幫助識別我做錯了什么嗎? 如果可能的話,我也在尋找答案的一個很好的解釋,這樣我就可以從這個經驗中學習。

再次,在排除時沒有錯誤。 問題是GetCityWeatherByZIPResponse.GetCityWeatherByZIPResult的值是null。 我知道文檔正在返回正確的結果,因為結果打印輸出如下:

結果打印輸出:

<?xml version="1.0" encoding="UTF-8"?><GetCityWeatherByZIPResponse xmlns="http://ws.cdyne.com/WeatherWS/">
    <GetCityWeatherByZIPResult>
        <Success>true</Success>
        <ResponseText>City Found</ResponseText>
        <State>MO</State>
        <City>Saint Charles</City>
        <WeatherStationCity>Farmington</WeatherStationCity>
        <WeatherID>4</WeatherID>
        <Description>Sunny</Description>
        <Temperature>79</Temperature>
        <RelativeHumidity>47</RelativeHumidity>
        <Wind>CALM</Wind>
        <Pressure>30.00S</Pressure>
        <Visibility/>
        <WindChill/>
        <Remarks/>
    </GetCityWeatherByZIPResult>
</GetCityWeatherByZIPResponse>

Response: GetCityWeatherByZIPResult: null

測試Web服務: http//wsf.cdyne.com/WeatherWS/Weather.asmx

初始調用(通過JBehave完成):

@Given("I call the weather soap service")
public void givenICallTheWeatherSoapService() {
    GetCityWeatherByZIP weather = new GetCityWeatherByZIP();
    weather.setZIP("63304");
    try {
        new WeatherTools();
        WeatherSoap weatherSoap = new WeatherSoap();
        GetCityWeatherByZIPResponse response = weatherSoap.getCityWeatherByZip("63304");
        System.out.println("Response: " + response);
    } catch (JAXBException | ParserConfigurationException | SOAPException | IOException e) {
        Assert.fail(e.getMessage());
    }
}

肥皂服務類:

public class WeatherSoap extends PTFSoapClient {

    public WeatherSoap() throws JAXBException, ParserConfigurationException, SOAPException {
        super(PTFApplication.getConfig(Environment.executionEnv.getEnv(), "Weather SOAP endpoint"));
    }

    public GetCityWeatherByZIPResponse getCityWeatherByZip(String zip) throws JAXBException, SOAPException, IOException {
        GetCityWeatherByZIP weatherByZip = new GetCityWeatherByZIP();
        weatherByZip.setZIP(zip);
        try {
            sendRequest(weatherByZip);
            return (GetCityWeatherByZIPResponse) unmarshallResponse(GetCityWeatherByZIPResponse.class);
        } catch (ParserConfigurationException | XMLStreamException e) {
            e.printStackTrace();
            return null;
        }
    }
}

基本框架類對調用進行通用化(可用於所有SOAP調用):

public class PTFSoapClient {
    private JAXBContext context;
    private Marshaller marshaller;
    private Object object;
    private SOAPMessage message;
    private String endpoint;
    private SOAPMessage response;

    public PTFSoapClient(String endpoint) {
        this.endpoint = endpoint;
    }

    public void toConsole() throws JAXBException, SOAPException, IOException {
        message.writeTo(System.out);
        System.out.print("\n");
    }

    public SOAPMessage sendRequest(Object obj) throws JAXBException, ParserConfigurationException, SOAPException {
        object = obj;
        context = JAXBContext.newInstance(obj.getClass());
        marshaller = context.createMarshaller();

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document doc = dbf.newDocumentBuilder().newDocument();
        marshaller.marshal(object,doc);
        MessageFactory factory = MessageFactory.newInstance();
        message = factory.createMessage();
        message.getSOAPBody().addDocument(doc);
        message.saveChanges();

        SOAPConnection connection = SOAPConnectionFactory.newInstance().createConnection();
        response = connection.call(message, endpoint);
        connection.close();

        try {
            System.out.println("Response:");
            response.writeTo(System.out);
            System.out.println("");
        } catch (IOException e) {
            e.printStackTrace();
        }

        return response;
    }

    public Object unmarshallResponse(Class<?> classname) throws JAXBException, XMLStreamException, SOAPException, IOException {
        Document doc = response.getSOAPBody().extractContentAsDocument();
        try {
            System.out.println("Document: ");
            printDocument(doc, System.out);
            System.out.println("");
        } catch (TransformerException e) {
            e.printStackTrace();
        }

        Unmarshaller unmarshaller = JAXBContext.newInstance(classname).createUnmarshaller();
        return unmarshaller.unmarshal(doc);
    }

    public static void printDocument(Document doc, OutputStream out) throws IOException, TransformerException {
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

        transformer.transform(new DOMSource(doc), 
             new StreamResult(new OutputStreamWriter(out, "UTF-8")));
    }
}

基礎解組對象:

@XmlRootElement(name = "GetCityWeatherByZIPResponse",
                namespace = "http://ws.cdyne.com/WeatherWS/")
public class GetCityWeatherByZIPResponse {
    GetCityWeatherByZIPResult GetCityWeatherByZIPResult;

    public GetCityWeatherByZIPResult getGetCityWeatherByZIPResult() {
        return GetCityWeatherByZIPResult;
    }

    public void setGetCityWeatherByZIPResult(GetCityWeatherByZIPResult GetCityWeatherByZIPResult) {
        this.GetCityWeatherByZIPResult = GetCityWeatherByZIPResult;
    }

    @Override
    public String toString() {
        return "GetCityWeatherByZIPResult: " + GetCityWeatherByZIPResult;
    }
}

子umarshal對象:

public class GetCityWeatherByZIPResult {
    boolean Success;
    String ResponseText;
    String State;
    String City;
    String WeatherStationCity;
    String WeatherID;
    String Description;
    int Temperature;
    int RelativeHumidity;
    String Wind;
    String Pressure;
    String Visibility;
    String WindChill;
    String Remarks;

    public boolean isSuccess() {
        return Success;
    }

    public void setSuccess(boolean success) {
        Success = success;
    }

    public String getResponseText() {
        return ResponseText;
    }

    public void setResponseText(String responseText) {
        ResponseText = responseText;
    }

    public String getState() {
        return State;
    }

    public void setState(String state) {
        State = state;
    }

    public String getCity() {
        return City;
    }

    public void setCity(String city) {
        City = city;
    }

    public String getWeatherStationCity() {
        return WeatherStationCity;
    }

    public void setWeatherStationCity(String weatherStationCity) {
        WeatherStationCity = weatherStationCity;
    }

    public String getWeatherID() {
        return WeatherID;
    }

    public void setWeatherID(String weatherID) {
        WeatherID = weatherID;
    }

    public String getDescription() {
        return Description;
    }

    public void setDescription(String description) {
        Description = description;
    }

    public int getTemperature() {
        return Temperature;
    }

    public void setTemperature(int temperature) {
        Temperature = temperature;
    }

    public int getRelativeHumidity() {
        return RelativeHumidity;
    }

    public void setRelativeHumidity(int relativeHumidity) {
        RelativeHumidity = relativeHumidity;
    }

    public String getWind() {
        return Wind;
    }

    public void setWind(String wind) {
        Wind = wind;
    }

    public String getPressure() {
        return Pressure;
    }

    public void setPressure(String pressure) {
        Pressure = pressure;
    }

    public String getVisibility() {
        return Visibility;
    }

    public void setVisibility(String visibility) {
        Visibility = visibility;
    }

    public String getWindChill() {
        return WindChill;
    }

    public void setWindChill(String windChill) {
        WindChill = windChill;
    }

    public String getRemarks() {
        return Remarks;
    }

    public void setRemarks(String remarks) {
        Remarks = remarks;
    }
}

你當前的地圖

@XmlRootElement批注上指定namespace屬性時,它僅適用於該一個元素。

@XmlRootElement(name = "GetCityWeatherByZIPResponse",
                namespace = "http://ws.cdyne.com/WeatherWS/")
public class GetCityWeatherByZIPResponse {

您的XML文檔

您的XML文檔指定了默認命名空間。 這意味着沒有其他顯式命名空間映射的所有元素也是http://ws.cdyne.com/WeatherWS/命名空間的一部分。

<?xml version="1.0" encoding="UTF-8"?><GetCityWeatherByZIPResponse xmlns="http://ws.cdyne.com/WeatherWS/">
    <GetCityWeatherByZIPResult>
        <Success>true</Success>

命名空間修復

您將要在包級別指定命名空間映射,以便它適用於所有元素映射。 這是在名為package-info特定類上使用包級別@XmlSchema注釋完成的。

@XmlSchema( 
    namespace = "http://ws.cdyne.com/WeatherWS/", 
    elementFormDefault = XmlNsForm.QUALIFIED) 
package example;

import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

欲獲得更多信息

我在博客上寫了更多關於JAXB和命名空間限定的文章:


更新

默認元素名稱

屬性的默認元素與XML不匹配。 對於預期元素名稱下面的屬性,將是getCityWeatherByZIPResult因此您需要使用@XmlElement批注覆蓋默認值。

@XmlElement(name="GetCityWeatherByZIPResult")
public GetCityWeatherByZIPResult getGetCityWeatherByZIPResult() {
    return GetCityWeatherByZIPResult;
}

調試提示

當您遇到解組問題時,請填充對象模型並對其進行編組,以查看基於當前映射的預期XML。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM