问题
I have one to many mapping in my Pojo classes. A shop has a branch and a branch has many shops Here's Shop's Code:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="Shop")
public class Shop {
@XmlID
private String name;
@XmlIDREF
@XmlElement(name="ShopBranch",type=Branch.class)
private Branch branch;
//Getter Setter
}
Below is Branch Code:
@XmlAccessorType(XmlAccessType.FIELD)
public class Branch {
@XmlID
private String name;
private String address;
@XmlIDREF
@XmlElement(nillable=false,required=true)
private List<Shop> shops;
//Getter and Setters
}
I'm publishing a webservice with some basic methods. and my wsimport is generating Branch class as below
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "branch", propOrder = {
"branchName",
"address",
"branchShop"
})
public class Branch {
@XmlElement(name = "BranchName")
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
@XmlID
@XmlSchemaType(name = "ID")
protected String branchName;
protected String address;
@XmlElementRef(name = "BranchShop", type = JAXBElement.class)
protected List<JAXBElement<Object>> branchShop;
//Getter-Setter
}
I have no idea why it is List<JAXBElement<Object>> and not List<JAXBElement<Shop>>. But anyway. I have a method which returns all branches and that is working fine. When i extract branchShop from branch's instance i'm getting correct size for branchShop list but for all of the items in list getValue is returning NULL. Below is brief code:
PencilCatalog service= new PencilCatalog();
com.pencilhouse.webservices.PencilService port=service.getPencilCatalogPort();
((BindingProvider)port).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, Constant.PENCIL_SERVICE);
List<Branch> branches= port.getAllBranches();
for(Branch b:branches)
{
System.out.println("******************Branch:"+b.getBranchName()+" "+b.getAddress()+"******************");
JAXBElement<Object>o=b.getBranchShop().get(0);
System.out.println(o+"Value"+o.getScope()+" "+o.getValue());
}
o/p
******************Branch:KukatPalli Steer 2 Kukatpalli****************** javax.xml.bind.JAXBElement@45d9d7beValueclass com.pencilhouse.webservices.Branch null
The WSDL generated is quite large. I'm posting only type of Branch and Shop. I'm publishing webservice using Endpoint
XML generated:
<xs:complexType name="shop">
<xs:sequence>
<xs:element name="name" type="xs:ID" minOccurs="0"/>
<xs:element name="ShopBranch" type="xs:IDREF" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="branch">
<xs:sequence>
<xs:element name="BranchName" type="xs:ID" minOccurs="0"/>
<xs:element name="address" type="xs:string" minOccurs="0"/>
<xs:element name="BranchShop" type="xs:IDREF" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
Intercepted Information: Request:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getAllBranches xmlns:ns2="PencilServiceHouse"/>
</S:Body>
</S:Envelope>
Response:
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getAllBranchesResponse xmlns:ns2="PencilServiceHouse">
<return>
<name>
KukatPalli
</name>
<address>
Steer 2 Kukatpalli
</address>
<shops>
Pencil World <!-- This is Shop Information which is coming as NULL in java, This is Shop's Name field which is declared as id using @XmlId -->
</shops>
<shops>
Pencils Den
</shops>
<shops>
Pencils Bag
</shops>
</return>
<return>
<name>
Salt Lake
</name>
<address>
Sec V Salt Lake
</address>
<shops>
Pencil World
</shops>
<shops>
Pencils Den
</shops>
</return>
<return>
<name>
Noida
</name>
<address>
Noida Sec 43
</address>
<shops>
Pencils Bag
</shops>
</return>
</ns2:getAllBranchesResponse>
</S:Body>
</S:Envelope>
回答1:
@XmlIDREF
provides a way to specify intra-document references. It is required that each object be refrerenced through a sepearate nested relationship (such as @XmlElement
) to get the data into the XML document.
I have written more about @XmlIDREF
on my blog:
- http://blog.bdoughan.com/2010/10/jaxb-and-shared-references-xmlid-and.html
UPDATE
I saw your blog, I'm getting data in my xml response but the issue is that when i generate my classes on client side using wsimport it is generating type Object for @XmlIDRef and it doesn't set data for these properties as i explained in my question.
In your example you are going: classes -> schema -> classes. Since Java classes and XML Schema are not a perfect match, and JAXB does not put any JAXB specific metadata in the generated schema some information is lost. You can fix this as follows:
You can use an external bindings file to type the IDREF property.
<jaxb:bindings schemaLocation="schema.xsd" node="/xsd:schema">
<jaxb:bindings node="xsd:complexType[@name='branch']//xsd:element[@name='BranchShop']">
<jaxb:property>
<jaxb:baseType name="org.example.Shop"/>
</jaxb:property>
</jaxb:bindings>
</jaxb:bindings>
回答2:
This is not an answer, but it is to big for a comment and uses some formatting, so I have to post it as an answer.
Somehow your examples just don't add up.
First thing which is suspicious to be is that you have two Branch
classes. Which already looks weird. Why do you need the second one? Or are these, like, service and client implementations?
Next, your Branch
classes use the BranchName
and BranchShop
elements whereas your XML uses name
and shop
elements. This does not fit. Seems like your web service does not give the XML you expect. This would explain why the data is missing, but what puzzles me is - why do you get an element in the branchShop
at all. I would actually expect the list to be empty but you seem to have something there.
My suggestion would be to figure out, why XML you get does not match your schema and to implement an isolated unmarshalling unit-test to test unmarshalling of the intercepted XML.
来源:https://stackoverflow.com/questions/26357458/jaxbelement-getvalue-is-returning-null