how to convert inner class with modelmapper - modelmapper

modelmapper 3.1.0
i have following class:
#Data
public class Outter {
private int id;
private String name;
private List<Inner> innerList;
}
#Data
public class Inner {
private int id;
private String code;
}
i want to convert Outter to OutterDto, and i tried create the OutterDto as follows:
#Data
public class OutterDto {
private String name;
private List<InnerDto> innerList;
#Data
class InnerDto {
private String code;
}
}
the InnerDto is the inner class of OutterDto.
however, it thrown an error:
Failed to instantiate instance of destination example.model.OutterDto$InnerDto. Ensure that example.model.OutterDto$InnerDto has a non-private no-argument constructor.
even i add a constructor public InnterDto() {} for InnerDto.
so does the modelmapper support for inner class?
if it does, how can i do that?

Related

ModelMapper failed to convert java.lang.String to java.lang.Long

I have rest models that I use to build JSON that I send.
A rest model
#Getter #Setter
#ToString
public class OrderRequestModel {
private String orderKeyId;
private String paymentMode;
private double totalAmount;
private List<ProductRequestModel> orderProducts;
private UserDetailsRequestModel seller;
private Date createdAt;
}
The ProductRequestModel is similar
#Getter #Setter
#ToString
public class ProductRequestModel {
private String productKeyId;
private String name;
private double price;
private int qty;
private String imgPath;
private CategoryRequestModel category;
}
I'm passing the models to a DTO layer which is in relation with database (they include a long Id):
#Getter #Setter
#ToString
public class OrderDto implements Serializable {
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private static final long serialVersionUID = 1L;
private Long id;
private String orderKeyId;
private String paymentMode;
private double totalAmount;
private List<ProductDto> orderProducts;
private UserDto seller;
private Date createdAt;
}
And my ProductDto :
#Getter #Setter
#ToString
public class ProductDto implements Serializable {
// ommit this member and do not generate getter / setter
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private static final long serialVersionUID = 1L;
private Long id;
private String productKeyId;
private String name;
private double price;
private int qty;
private String imgPath;
private CategoryDto category = new CategoryDto();
}
When i try to map OrderDto with the associated model i do it implicitelly :
OrderDto orderDto = modelMapper.map(orderRequestModel, OrderDto.class);
In theory, orderKeyId from the model should match with its equivalent in the Dto. Unfortunatelly It returns an error :
Converter org.modelmapper.internal.converter.NumberConverter#3e36f4cc failed to convert java.lang.String to java.lang.Long.
Caused by: org.modelmapper.MappingException: ModelMapper mapping errors:
I do need the Id in the DTO because if i want to make an update I do use "id"
This issue is caused because of the Mapping Strategies. We can set the Mapping Strategies to STRICT so that when mapping from source object property to target object's property it only maps only those property which are perfectly matching in property name as well as it's data type. Below is an example.
public ModelMapper modelMapper() {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration()
.setMatchingStrategy(MatchingStrategies.STRICT);
}
FYI:
http://modelmapper.org/user-manual/configuration/#matching-strategies

Why is XStream ignoring #XmlTransient?

Does XStream handle JAXB #XmlTransient attributes by default? XStream seems to be ignoring the #XmlTransient attribute & serializing the field anyway.
In the sample code below. ExampleClass2 is getting serialized even though I don't want it to be. Further details are that these classes are being populated by OpenJPA.
XStream Code
XStream _x0 =null;
_x = XStreamImpl.getInstance();
_x.toXML(_object)
Class I want to serialize
#DataCache
#Entity
public class ExampleClass implements Serializable {
private short defaultOption;
private int primaryKey;
private short orderId;
#XmlTransient
private ExampleClass2 _exampleClass2;
#XmlTransient
public ExampleClass2 getTblPpwsCommCfgCombo() {
return _exampleClass2;
}
#XmlTransient
public void setExampleClass2(ExampleClass2 _exampleClass2) {
this._exampleClass2 = _exampleClass2;
}
public short getDefaultOption() {
return defaultOption;
}
public void setDefaultOption(short defaultOption) {
this.defaultOption = defaultOption;
}
public short getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(int primaryKey) {
this.primaryKey = primaryKey;
}
public short getOrderId() {
return orderId;
}
public void setOrderId(short orderId) {
this.orderId = orderId;
}
}
You can use the #Transient annotation or transiet key word:
#Transient
private ExampleClass2 _exampleClass2;
~

JAXB Marshalling: Creating an empty element with an attribute

I use a JAXB marshaller and I would like to add an empty element with a specific attribute. This is a dummy class:
#XmlRootElement(name="observation")
public class Observation {
#XmlAttribute
public static final String classCode = "OBS";
#XmlAttribute
public static final String moodCode = "EVN";
private String data;
#XmlElement
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
This creates the following XML:
<observation classCode="OBS" moodCode="EVN">
<data>fsdfsdfd</data>
</observation>
Is there any way to add a new element with a specific attribute only (no value at all)? E.g.
<observation classCode="OBS" moodCode="EVN">
<templateId root="2.16.840.1.113883.10.20.1.31"/>
<data>fsdfsdfd</data>
</observation>
This should do it:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "TemplateIdType")
public class TemplateIdType {
#XmlAttribute(name = "root")
protected String root;
// getter and setter
}
(And you add an element of this class to Observation.)

How to override JAXB #XMLAccessorType(XMLAccessType.FIELD) specified at a Class level with #XMLElement on a getter method for a property?

In the example code below, Employee class has been specified with JAXB field level access type. For the property dept, however, the access type has been specified at getter method level with #XMLElement annotation.
During marshalling of Organization class, the following exception is thrown -
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "dept"
this problem is related to the following location:
at public java.lang.String com.playground.jaxb.Employee.getDept()
this problem is related to the following location:
at private java.lang.String com.playground.jaxb.Employee.dept
Can you help me understand why this overriding of JAXB accessor type is not working please? Also any solution would be highly appreciated.
Example
Root Element Class
package com.playground.jaxb;
#XMLRootElement(name="organization")
public class Organization {
#XmlElementWrapper(name = "employees")
#XmlElement(name = "employee")
private Set<Employee> employees;
public Organization{}
// Remainder omitted...
}
Employee Class
package com.playground.jaxb;
#XMLAccessorType(XMLAccessType.FIELD)
public class Employee {
private String name;
private String dept;
#XMLElement(name="department")
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
public Employee {}
// Remainder omitted...
}
You can re-name getter/setter pair, e.g. getDept() -> getDepartment()
private String dept;
#XmlElement(name="department")
public String getDeptartment() {
return dept;
}
public void setDeptartment(String dept) {
this.dept = dept;
}
but in this case you will have duplicate in XML
<dept>my_dept</dept>
<department>my_dept</department>
Or you can annotate field dept with #XmlTransient annotation, if you want to change access type it.
#XmlTransient
private String dept;
#XmlElement(name="department")
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
In this case, dept field will be ignored and getter/setter pair will be used instead

using JAXB, the XML is loaded into a class. This class is then used within another class to be marshalled out differently

Given an XML file of offerings that is then loaded into a class called Offerings via JAXB.
This class has the following:
Name, Price sub-Class, Modifiers, Ordering Rules etc.
I then create an order and within that order
Order
public class ProductOrder {
private String OrderId;
private Date createDate;
private OrderStatus orderStatus;
private int CustomerOrderID;
private ArrayList<ProductOrderItem> productOrderItems = new ArrayList<ProductOrderItem>();
}
Order Item
public class ProductOrderItem {
private int OrderItemID;
private **Offering** offering;
private Map<String, Integer> qtylist = new HashMap<String, Integer>();
private ArrayList<Modifier> modifiers = new ArrayList<Modifier>();
private int qty;
}
Offering
#XmlRootElement(name = "offering")
#XmlAccessorType(XmlAccessType.FIELD) // NONE)
public class Offering {
#XmlAttribute
private String id;
#XmlElement
private String offeringName;
#XmlElement
private String description;
#XmlElement
private Integer price;
}
The Offering and Modifiers are classes with JAXB already which I only want to push part of the XML. How would I change the anotations such that only part of the elements are sent? For example not the offering -> modifiers?
Use #XmlTransient instead of the #XmlElement tag.

Resources