ModelMapper cannot map inner static class - modelmapper

I try to map domain object into dto object, but it does not map fields related with inner class -> FieldLabels.
DOMAIN
#Value
#Builder
public class ClassificationDetails {
String description;
boolean disabled;
FieldLabels characterFieldLabels;
#Value
#Builder
public static class FieldLabels {
String fieldLabel1;
String fieldLabel2;
}
}
DTO have the same fields
#Value
#Builder
public class ClassificationDetailsDto {
String description;
boolean disabled;
FieldLabelsDto characterFieldLabels;
#Value
#Builder
public static class FieldLabelsDto {
String fieldLabel1;
String fieldLabel2;
}
modelMapper.map(domain, ClassificationDto.ClassificationDtoBuilder.class).build()
How should I handle it?

Related

how to convert inner class with 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?

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

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

hibernate search analysis not performed on the field #IndexedEmbedded

#Indexed
public class Event implements Serializable {
#DocumentId
private Long id;
#Field
#AnalyzerDiscriminator(impl = LanguageDiscriminator.class) // "de", GermanAnalyzer
private String lang;
#IndexedEmbedded
private User user;
}
#Indexed
#Analyzer(impl = GermanAnalyzer.class)
public class User implements Serializable {
#DocumentId
private Long id;
#Field
private String firstName;
}
firstName field will be analyzed in the index User, and will not be analyzed in the index Event.
This is the correct behavior or not?
It will be analyzed in the Event index but the field name will be user.firstName in that case. You can override the default prefix by using the otional attributes of #IndexedEmbedded.

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