I know to create a JAXB Class to marshal/unmarshall an xml like this
<outertag>
<innerelement>
<innerElementDetail1>some value</inner-element-detail1>
</innerelement>
</outertag>
here is the class I created
#XmlRootElement(name ="outertag")
#XmlAccessorType(XmlAccessType.FIELD)
public class OuterTag {
#XmlElement(name = "innerelement")
private List<InnerElement> innerElemements
public static InnerElement{
private String innerElementDetail;
// getters and setters
}
}
If I have to have an attribute on one of the inner elements like this
<outertag>
<innerelement attribute1="attribute1value">
<innerElementDetail1>some value</inner-element-detail1>
</innerelement>
</outertag>
how do I do that ?
This should do it :
#XmlRootElement(name ="outertag")
#XmlAccessorType(XmlAccessType.FIELD)
public class OuterTag {
#XmlElement(name = "innerelement")
private List<InnerElement> innerElemements
public static InnerElement{
#XmlAttribute(name = "attribute1")
protected String attribute1;
private String innerElementDetail;
// getters and setters
}
}
Related
I am trying to use MapStruct for a structure similar to the following:
#Data
public class ClassAEntity {
private int id;
private String name;
private String numT;
private List<ClassBEntity) bs;
}
#Data
public class ClassBEntity {
private int id;
private String name;
private String numT;
private List<Other> oc;
}
#Data
public class ClassA {
private int id;
private String name;
private List<ClassB) bs;
}
#Data
public class ClassB {
private int id;
private String name;
private List<Other> oc;
}
In the interface I have added the following mapping:
ClassAEntity map(ClassA classA, String numT)
I get a warning because it can't map numT to classBEntity.numT and I can't add it with #Mapping in the following way:
#Mapping(source = "numT", target = "bs[].numT")
On the other hand I need to ignore the parameter oc of classBEntity because "Other" object contains classAEntity and forms a cyclic object. (because I use oneToMany JPA). I have tried the following:
#Mapping(target = "bs[].oc", ignore = true)
Thank you for your help
MapStruct does not support defining nested mappings for collections. You will have to define more explicit methods.
For example to map numT into bs[].numT and ignore bs[].oc you'll need to do something like:
#Mapper
public MyMapper {
default ClassAEntity map(ClassA classA, String numT) {
return map(classA, numT, numT);
}
ClassAEntity map(ClassA classA, String numT, #Context String numT);
#AfterMapping
default void setNumTOnClassBEntity(#MappingTarget ClassBEntity classB, #Context String numT) {
classB.setNumT(numT);
}
#Mapping(target = "oc", ignore = "true")
ClassBEntity map(ClassB classB);
}
Is it possible to rename the parameters used inside a GET webservice in spring? Like search.limitResults in the following example:
localhost:8080/firstname=test&search.limitResults=10
You get the idea. Can this be achieved?
#RestController
public class MyServlet {
#RequestMapping(value = "/", method = RequestMethod.GET)
private String test(RestParams p) {
}
}
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class RestParams {
private String firstname;
private String lastname;
//is that possible to nest?
#XmlElement(name = "search")
private MyComplexSearch search;
public MyComplexSearch getSearch() {return search;}
public void setSearch(MyComplexSearch) {this.search = search;}
#XmlRootElement(name = "search")
#XmlAccessorType(XmlAccessType.FIELD)
public class MyComplexSearch {
private int limitResults;
//some more
}
}
The request will not work with the code above. Instead one would have to use myComplexSearch as the objects name.
localhost:8080/firstname=test&myComplexSearch.limitResults=10
How can I redefine the name of the input property, without having to rename the java class itself?
Nested classes have to be static.
public static class MyComplexSearch
i have a code similar to this
#XmlRootElement(name = "root")
#XmlType(propOrder={"param1", "param2""})
public class Demo{
public Demo() {
}
private int param1;
private String param2;
private String param3;
public int getparam1() {
return param1;
}
#XmlElement
public void setparam1(int param1) {
this.param1= param1;
}
//other setters and getters here except for param3
}
but it gives me
n4 counts of IllegalAnnotationExceptions
exception when i try to run the program (i have 6 parameters in total in original code and only 4 is use for Marshall )
What would be the reason for this?
There is an error in the #XmlType anntation:
#XmlType(propOrder={"param1", "param2","param3"})
If this not fix the problem, try to check the name of the properties in the propOrder OR directly use field accessor type:
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(propOrder={"param1", "param2", "param3"})
public class Demo{
public Demo() {
}
private int param1;
private String param2;
private String param3;
//getter & setters without annotations
}
I have the following XML file to unmarshall
<root>
<emp>Google</emp>
<emp>Yahoo</emp>
<xyz>random</xyz>
</root>
And i have used annotations in the following way,
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
#XmlElement(name = "emp")
private String emp1;
#XmlElement(name = "emp")
private String emp2;
#XmlElement(name = "xyz")
private String xyz;
// added getters and setters for these fields
}
My problem is while i'm trying to get
obj.getEmp1(); // result is Yahoo instead of Google
obj.getEmp2(); // result is null.
Kindly clarify me, what am i doing wrong?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
The standard JAXB (JSR-222) annotations do not support mapping 2 different properties to the same XML element.
You could use EclipseLink JAXB (MOXy)'s #XmlPath extension for this use case.
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
#XmlPath("emp[1]/text()")
private String emp1;
#XmlPath("emp[2]/text()")
private String emp2;
#XmlElement(name = "xyz")
private String xyz;
// added getters and setters for these fields
}
For More Information
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
If for whatever reason you cannot use MOXy, another solution would be to map the emp element as a list
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
#XmlElement(name = "emp")
private List<String> emp;
#XmlElement(name = "xyz")
private String xyz;
// added getters and setters for these fields
}
And then use the following code to get the values:
obj.getEmp().get(0);
obj.getEmp().get(1);
But Blaise's solution is more elegant
You could have a String[] field and have your current accessor methods access the String[].
import javax.xml.bind.annotation.*;
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
private String[] emp = new String[2];
private String xyz;
public String getEmp1() {
return emp[0];
}
public void setEmp1(String emp1) {
this.emp[0] = emp1;
}
public String getEmp2() {
return emp[1];
}
public void setEmp2(String emp2) {
this.emp[1] = emp2;
}
public String getXyz() {
return xyz;
}
public void setXyz(String xyz) {
this.xyz = xyz;
}
}
This might work.
<root>
<emp1>Google</emp1>
<emp2>Yahoo</emp2>
<xyz>random</xyz>
</root>
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class abc {
#XmlElement(name = "emp1")
private String emp1;
#XmlElement(name = "emp2")
private String emp2;
#XmlElement(name = "xyz")
private String xyz;
}
I have a class like this:
#XmlRootElement(name = "PricingGroup")
public class PricingGroup {
...
#XmlAttribute(name = "partyName")
#XmlJavaTypeAdapter(CustomerGroupRelationships.Adapter.class)
private List<BilltoCustomer> billtoCustomers = new ArrayList<BilltoCustomer>();
#XmlAttribute(name = "partyName")
#XmlJavaTypeAdapter(PartyNames.Adapter.class)
private PartyName partyName;
...
}
It seems JAXB can't map two #XmlJavaTypeAdapters for one attribute (here partyName). If I comment out either the annotations on billtoCustomers or the annotations on partyName, the other member variable is read from XML without problems.
How can I get both values at the same time?
You could map one of the properties (partyName) and then use an afterUnmarshal event to derive the other property (billToCustomers):
#XmlRootElement(name = "PricingGroup")
public class PricingGroup {
...
#XmlTransient
private List<BilltoCustomer> billtoCustomers = new ArrayList<BilltoCustomer>();
#XmlAttribute(name = "partyName")
#XmlJavaTypeAdapter(PartyNames.Adapter.class)
private PartyName partyName;
void afterUnmarshal(Unmarshaller u, Object parent) {
// Derive billToCustomers from partyName
}
...
}