I have a class SuccessResponse that contains another custom class SuccessCustomerResponseBody, both of these classes are a POJO model for some XML structure.
@JacksonXmlRootElement(localName = "response")
public class SuccessResponse {
private SuccessCustomerResponseBody ok;
public SuccessCustomerResponseBody getOk() {
return ok;
}
public void setOk(SuccessCustomerResponseBody ok) {
this.ok = ok;
}
}
and SuccessCustomerResponseBody
@Getter
@Setter
public class SuccessCustomerResponseBody {
@JacksonXmlElementWrapper(localName = "customers")
private List<Customer> customers;
private String requestId;
@JacksonXmlProperty(localName = "customer")
public List<Customer> getCustomers() {
return customers;
}
}
This model is used to fetch data from a database, and return as an XML response in service controller GetCustomer. It looks okay except when it's required to add another controller to return for example customer packages. So, the easiest way, to create two more classes like SuccessPackageResponse and SuccessPackageResponseBody, rename SuccessResponse to SuccessCustomerResponse and that's it. Well done
@JacksonXmlRootElement(localName = "response")
public class SuccessPackageResponse {
private SuccessPackageResponseBody ok;
public SuccessPackageResponseBody getOk() {
return ok;
}
public void setOk(SuccessPackageResponseBody ok) {
this.ok = ok;
}
}
SuccessPackageResponseBody
@Getter
@Setter
public class SuccessPackageResponseBody {
@JacksonXmlElementWrapper(localName = "packages")
private List<Package> packages;
private String requestId;
@JacksonXmlProperty(localName = "package")
public List<Package> getPackages() {
return packages;
}
}
The main problem is that this approach produces a lot of code. So, I tried to re-use SuccessResponse by implementing this class as generic one.
@JacksonXmlRootElement(localName = "response")
public class SuccessResponse<T> {
private T ok;
public T getOk() {
return ok;
}
public void setOk(T ok) {
this.ok = ok;
}
}
Looks better, right? We can use it like:
SuccessResponse<SuccessCustomerResponseBody> successCustomerResponse = objectMapper.convertValue(node.getMap().get("response"), SuccessResponse.class);
I thought that this is my solution, but I found that ObjectMapper configs are not applied in such approach and I don't understand why.
objectMapper.configOverride(String.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
To finalise, I have two questions:
- Any idea how to re-use
SuccessResponsein case when custom type (SuccessCustomerResponseBody) can be dynamically changed. - Why
ObjectMapperconfig isn't applied in solution with generic?