I’m using Jersey to deliver a RESTful web service. I used javax.xml.bind.annotation to set up my POJO data transfer object. My DTO contains some other POJOs which provide values to the main DTO. I’m able to get JSON back from my resource in the browser, hooray, but the JSON is returning a lot more member variables of the objects and in the wrong order.
Here’s the Resource:
@Controller
@Path("/merchants/{merchantId}/profile")
public class MerchantProfileResource {
@Autowired
private MerchantProfileManager merchantProfileManager;
public MerchantProfileResource() {
}
@GET
@Produces("application/json")
// TODO - wire this up
public MerchantProfileDTO getMerchantProfile(@PathVariable String id) {
MerchantProfileDTO merchantProfile = merchantProfileManager.getMerchantProfileDTO(id);
return merchantProfile;
}
public MerchantProfileManager getMerchantProfileManager() {
return merchantProfileManager;
}
public void setMerchantProfileManager(MerchantProfileManager merchantProfileManager) {
this.merchantProfileManager = merchantProfileManager;
}
}
Here’s the DTO class:
@XmlRootElement(name = "response")
@XmlType(propOrder={"merchantId", "email", "paymentMethods", "merchantTaxData"})
public class MerchantProfileDTO {
@XmlElement(name = "merchantId")
private int merchantId;
public int getMerchantId() {
if (merchant == null)
return 0;
return merchant.getMerchantid();
}
@XmlElement(name = "email")
private String email;
public String getEmail() {
if (merchantProfile == null)
return null;
return merchantProfile.getEmail();
}
@XmlElementWrapper(name = "paymentMethods")
@XmlElement(name = "paymentMethod")
private List<PaymentMethod> paymentMethods;
public List<PaymentMethod> getPaymentMethods() {
return paymentMethods;
}
public void setPaymentMethods(List<PaymentMethod> paymentMethods) {
this.paymentMethods = paymentMethods;
}
@XmlElement(name = "merchantTaxData")
private MerchantTaxData merchantTaxData;
public MerchantTaxData getMerchantTaxData() {
return merchantTaxData;
}
public void setMerchantTaxData(MerchantTaxData merchantTaxData) {
this.merchantTaxData = merchantTaxData;
}
private MerchantProfile merchantProfile;
public MerchantProfile getMerchantProfile() {
return merchantProfile;
}
public void setMerchantProfile(MerchantProfile merchantProfile) {
this.merchantProfile = merchantProfile;
}
private Merchant merchant;
public Merchant getMerchant() {
return merchant;
}
public void setMerchant(Merchant merchant) {
this.merchant = merchant;
}
}
Here’s the MerchantProfile class:
@javax.persistence.Table(name = "merchant_profile", schema = "", catalog = "mexp")
@Entity
public class MerchantProfile {
private int merchantid;
@javax.persistence.Column(name = "merchantid", nullable = false, insertable = true, updatable = true, length = 22, precision = 0)
@Id
public int getMerchantid() {
return merchantid;
}
public void setMerchantid(int merchantid) {
this.merchantid = merchantid;
}
private String email;
@javax.persistence.Column(name = "email", nullable = true, insertable = true, updatable = true, length = 255, precision = 0)
@Basic
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Here’s the Merchant class:
@javax.persistence.Table(name = "merchant", schema = "", catalog = "mexp")
@Entity
public class Merchant {
private int merchantid;
@javax.persistence.Column(name = "merchantid", nullable = false, insertable = true, updatable = true, length = 22, precision = 0)
@javax.persistence.Id
public int getMerchantid() {
return merchantid;
}
public void setMerchantid(int merchantid) {
this.merchantid = merchantid;
}
private MerchantProfile merchantProfile;
@OneToOne
@JoinColumn(name = "merchantid", unique = true, nullable = false, updatable = true)
public MerchantProfile getMerchantProfile() {
return merchantProfile;
}
public void setMerchantProfile(MerchantProfile merchantProfile) {
this.merchantProfile = merchantProfile;
}
private Collection<MerchantNexus> merchantNexusesByMerchantid;
@javax.persistence.OneToMany(orphanRemoval = true)
@JoinColumn(name="merchantid")
public Collection<MerchantNexus> getMerchantNexusesByMerchantid() {
return merchantNexusesByMerchantid;
}
public void setMerchantNexusesByMerchantid(Collection<MerchantNexus> merchantNexusesByMerchantid) {
this.merchantNexusesByMerchantid = merchantNexusesByMerchantid;
}
}
And the MerchantTaxData class:
@XmlRootElement(name = "merchantTaxData")
@XmlType(propOrder={"isTaxInfoKnown", "nexusList"})
public class MerchantTaxData {
public MerchantTaxData() {
}
@XmlElement(name = "isTaxInfoKnown")
private boolean isTaxInfoKnown;
public boolean isTaxInfoKnown() {
if (merchant == null)
return false;
return (1 == merchant.getIstaxinfoknown());
}
@XmlElementWrapper(name = "nexusList")
@XmlElement(name = "nexus")
private List<MerchantNexus> nexusList;
public List<MerchantNexus> getNexusList() {
return nexusList;
}
public void setNexusList(List<MerchantNexus> nexusList) {
this.nexusList = nexusList;
}
private Merchant merchant;
public Merchant getMerchant() {
return merchant;
}
public void setMerchant(Merchant merchant) {
this.merchant = merchant;
}
}
What I’d like to get back is
{
response: {
merchantId: 92,
email: "dev-catchall@blah.com",
paymentMethods: [
{paymentMethod: pm1},
...,
{paymentMethod: pmN}
],
merchantTaxData: {
isTaxInfoKnown: true,
nexusList: {
nexus: [
{merchantid: 92,statecode: "CA"},
...,
{merchantid: 92,statecode: "WA"}
]
}
}
}
}
but what I get back is much more than that:
{
response: {
merchantId: 0,
merchantTaxData: {
isTaxInfoKnown: true,
nexusList: {
nexus: [
{merchantid: 92, statecode: "CA"},
...,
{merchantid: 92, statecode: "WA"}
]
},
merchant: {
merchantNexusesByMerchantid: [
{merchantid: 92, statecode: "CA"},
...,
{merchantid: 92, statecode: "WA"}
],
merchantProfile: {
email: "dev-mexp-catchall@pronto.com",
merchantid: 92
},
merchantId: 92
}
},
merchant: {
merchantNexusesByMerchantid: [
{merchantid: 92, statecode: "CA"},
...,
{merchantid: 92, statecode: "WA"}
],
merchantProfile: {
email: "dev-mexp-catchall@pronto.com",
merchantid: 92
},
merchantid: 92
},
merchantProfile: {
email: "dev-mexp-catchall@pronto.com",
merchantid: 92
}
}
}
I should have had my annotations in front of the getters, not the variables.
Beyond that, @SamiKorhonen or @user463324 were right in the comments that using @XmlAccessorType(XmlAccessType.NONE) was the way to go. I invited them to submit a real answer to the question, but neither ever did.
I don’t want to get grief from the community for not accepting answers to my questions.