我遇到的问题是类与XML元素的绑定不成功。相反,它返回NullPointerException。下面是示例XML
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sh="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns:getNumberResponse
xmlns="http://ccm.intra.bt.com/manageServiceFault/2006/06" xmlns:ns="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:cds="http://capabilities.nat.bt.com/xsd/manageServiceFault/2010/06/Contact/Details"
xmlns:sh="http://wsi.nat.bt.com/2005/06/StandardHeader/"
xsi:schemaLocation="http://ccm.intra.bt.com/manageServiceFault/2006/06 MSF_5.0.xsd">
<sh:standardHeader>
<sh:e2e>
<sh:E2EDATA>E2E.graphID=2.1,E2E.from=ORESB,E2E.to=ORautofix,E2E.compTxnName=FaultProcessing,E2E.compTxnID=385h6g8lbh,E2E.busTxnStage=REQ,E2E.busProcID=1-CKMT1EEV,E2E.busProcType=ManageFaultRequests,E2E.busTxnSeq=385h5smgod,E2E.threadID=385h6g8koz,E2E.busTxnSys=AddFault,tradingPartnerId=735380615,E2E.busTxnHdr=PCK002069,E2E.busTxnType=AddFault,E2E.busProcOriginator=ORESB-default,E2E.busTxnUsr=siebel,E2E.busTxnLoc=UNKNOWN,E2E.threadID.4=APP10639:385h6g75io:385h6g8koz,E2E.threadID.3=:385h6fq4wv,E2E.threadID.2=ORSiebel:385h5smh48:385h6fq4wv,E2E.threadID.1=:
</sh:E2EDATA>
</sh:e2e>
<sh:serviceState>
<sh:stateCode>OK</sh:stateCode>
<sh:errorCode />
<sh:errorDesc />
<sh:errorText />
<sh:errorTrace />
</sh:serviceState>
</sh:standardHeader>
<actionRequestId />
<appointment>
<apptRequired>Y</apptRequired>
<apptSlot>0</apptSlot>
<apptType>Type</apptType>
<apptReference>Reference001</apptReference>
<earliestApptSlot>1</earliestApptSlot>
<earliestDate>2015-05-25T01:00:00</earliestDate>
</appointment>
<endUserDetails>
<firstName>Chris</firstName>
<lastName>Wong</lastName>
<priTelephone>+60123333333</priTelephone>
<secTelephone>+60123333334</secTelephone>
<cssDBID>1234</cssDBID>
</endUserDetails>
<serviceAffectingFlag>N</serviceAffectingFlag>
<number>123456789</number>
<service>
<serviceId xsi:nil="false">ONEA20160721_0067</serviceId>
</service>
<service>
<serviceId xsi:nil="false">ONEA20160721_0068</serviceId>
</service>
</ns:getNumberResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
以下是我的域类:UserDetail
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "endUserDetails")
@XmlAccessorType(XmlAccessType.FIELD)
public class UserDetail {
private String firstName;
private String lastName;
private String priTelephone;
private String secTelephone;
private String cssDBID;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getPriTelephone() {
return priTelephone;
}
public void setPriTelephone(String priTelephone) {
this.priTelephone = priTelephone;
}
public String getSecTelephone() {
return secTelephone;
}
public void setSecTelephone(String secTelephone) {
this.secTelephone = secTelephone;
}
public String getCssDBID() {
return cssDBID;
}
public void setCssDBID(String cssDBID) {
this.cssDBID = cssDBID;
}
}
这是预约
package com.bt.automation.domain;
import java.util.Date;
public class Appointment {
private String apptRequired;
private String apptSlot;
private String apptType;
private String apptReference;
private String earliestApptSlot;
private Date earliestDate;
public String getApptRequired() {
return apptRequired;
}
public void setApptRequired(String apptRequired) {
this.apptRequired = apptRequired;
}
public String getApptSlot() {
return apptSlot;
}
public void setApptSlot(String apptSlot) {
this.apptSlot = apptSlot;
}
public String getApptType() {
return apptType;
}
public void setApptType(String apptType) {
this.apptType = apptType;
}
public String getApptReference() {
return apptReference;
}
public void setApptReference(String apptReference) {
this.apptReference = apptReference;
}
public String getEarliestApptSlot() {
return earliestApptSlot;
}
public void setEarliestApptSlot(String earliestApptSlot) {
this.earliestApptSlot = earliestApptSlot;
}
public Date getEarliestDate() {
return earliestDate;
}
public void setEarliestDate(Date earliestDate) {
this.earliestDate = earliestDate;
}
}
最后是另一个域类响应
package com.bt.automation.domain;
import java.util.List;
import javax.xml.bind.annotation.*;
import com.bt.automation.domain.autofix.UserDetail;
@XmlRootElement(name = "Envelope")
@XmlAccessorType(XmlAccessType.FIELD)
public class Response {
private long number;
private String actionRequestId;
private String serviceAffectingFlag;
private Appointment appointment;
private UserDetail userDetail;
private List<MyService> service;
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number = number;
}
public String getActionRequestId() {
return actionRequestId;
}
public void setActionRequestId(String actionRequestId) {
this.actionRequestId = actionRequestId;
}
public String getServiceAffectingFlag() {
return serviceAffectingFlag;
}
public void setServiceAffectingFlag(String serviceAffectingFlag) {
this.serviceAffectingFlag = serviceAffectingFlag;
}
public List<MyService> getService() {
return service;
}
public void setService(List<MyService> service) {
this.service = service;
}
public Appointment getAppointment() {
return appointment;
}
public void setAppointment(Appointment appointment) {
this.appointment = appointment;
}
public UserDetail getUserDetail() {
return userDetail;
}
public void setUserDetail(UserDetail userDetail) {
this.userDetail = userDetail;
}
}
在代码中,我想将类UserDetail绑定到XML元素endUserDetails。以下是我的代码
package com.bt.automation.xml;
import java.io.FileReader;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import com.bt.automation.domain.Appointment;
import com.bt.automation.domain.MyService;
import com.bt.automation.domain.Response;
import com.bt.automation.domain.autofix.UserDetail;
public class UnmarshalResponse {
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newFactory();
XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("response.xml"));
xsr.nextTag(); // Advance to Envelope tag
int i = 0;
while (!xsr.getLocalName().equals("getNumberResponse")) {
System.out.println(i + xsr.getLocalName());
xsr.nextTag();
i = i + 1;
}
System.out.println("Current element: " + xsr.getLocalName());
System.out.println("Namespace: " + xsr.getNamespaceContext().getNamespaceURI("ns"));
JAXBContext jc = JAXBContext.newInstance(Response.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement<Response> je = unmarshaller.unmarshal(xsr, Response.class);
xsr.close();
Response response = je.getValue();
System.out.println("Object: " + response);
System.out.println("Number: " + response.getNumber());
System.out.println("Request ID: " + response.getActionRequestId());
System.out.println("Flag: " + response.getServiceAffectingFlag());
Appointment app = response.getAppointment();
System.out.println("Appointment.apptRequired: " + app.getApptRequired());
System.out.println("Appointment.apptReference: " + app.getApptReference());
System.out.println("Appointment.apptType: " + app.getApptType());
System.out.println("Appointment.earliestApptSlot: " + app.getEarliestApptSlot());
System.out.println("Appointment.apptSlot: " + app.getApptSlot());
System.out.println("Appointment.earliestDate: " + app.getEarliestDate());
UserDetail userDetail = response.getUserDetail();
System.out.println("UserDetail.getFirstName: " + userDetail.getFirstName());
System.out.println("UserDetail.getLastName: " + userDetail.getLastName());
System.out.println("UserDetail.getPriTelephone: " + userDetail.getPriTelephone());
System.out.println("UserDetail.getSecTelephone: " + userDetail.getSecTelephone());
System.out.println("UserDetail.getCssDBID: " + userDetail.getCssDBID());
List<MyService> list = response.getService();
for (i = 0; i < list.size(); i++) {
System.out.println("Service " + i + ": " + response.getService().get(i).getServiceId());
}
}
}
但是,当我运行代码时,它返回NullPointerException。这里的一个问题是,域类必须与绑定的XML元素具有相同的名称吗?
答案 0 :(得分:0)
您有一个NullPointerException
,因为response.getAnnotation()
是null
。实际上response
的所有属性都是null
,因为没有相应的XML内容被成功解组。
原因是:您的Java类完全忽略XML命名空间。
ns:getNumberResponse
XML元素中的命名空间和所有
没有名称空间前缀的子元素(appointment
,endUserDetails
,service
,...)
不要匹配Java类中的命名空间。
要了解有关JAXB注释的更多信息,我建议您阅读this tutorial以及包javax.xml.bind.annotation
的javadoc,特别是XmlElement
和XmlRootElement
。
为了解决您的问题,您有两种选择:
以下解决方案假设您更喜欢更改Java类并且不更改XML内容。
班级Response
:
在@XmlRootElement
中,您需要设置正确的name
和namespace
对于所有属性,您需要设置正确的namespace
对于属性userDetail
,您需要设置name = "endUserDetails"
。
@XmlRootElement(name = "getNumberResponse", namespace = "http://schemas.xmlsoap.org/soap/envelope/")
@XmlAccessorType(XmlAccessType.FIELD)
public class Response {
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private long number;
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private String actionRequestId;
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private String serviceAffectingFlag;
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private Appointment appointment;
@XmlElement(name = "endUserDetails", namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private UserDetail userDetail;
@XmlElement(name = "service", namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private List<MyService> service;
// ... getters/setters
}
班级Appointment
:
对于所有属性,您需要设置正确的namespace
。
@XmlAccessorType(XmlAccessType.FIELD)
public class Appointment {
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private String apptRequired;
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private String apptSlot;
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private String apptType;
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private String apptReference;
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private String earliestApptSlot;
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private Date earliestDate;
// ... getters/setters
}
班级UserDetail
:
对于所有属性,您需要设置正确的namespace
您可以省略@XmlRootElement
,因为它对非根元素没有影响。
@XmlAccessorType(XmlAccessType.FIELD)
public class UserDetail {
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private String firstName;
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private String lastName;
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private String priTelephone;
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private String secTelephone;
@XmlElement(namespace = "http://ccm.intra.bt.com/manageServiceFault/2006/06")
private String cssDBID;
// ... getters/setters
}
您没有发布课程MyService
。我想你也需要在那里做类似的修正。