I have a situation where I have an object(obj1) which I have to map to another object(obj2) but in this Mapping some of obj2's fields are already having some values while other fields are null, so I have to pick only those fields which are null in obj2 and then send data from obj1 to those fields. I am not sure if ModelMapper will be useful in this case.
Thanks in advance.
You can use ModelMapper. This library is used to perform this entity-DTO conversion.
Add below maven dependancy :
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>0.7.4</version>
</dependency>
Autowire the ModelMapper -
#Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
Sample Code transforming DTO to entity :
private Employee convertToDto(EmployeeDto employeeDto) {
Employee employee = modelMapper.map(employeeDto, Employee.class);
return employee;
}
Copying of one bean to another is possible using Apache commons library
for direct object to object copy you can use
copyProperties(Object dest, Object orig)
for individual copy you can use
setProperty(Object bean, String name, Object value)
This is alternative solution i have used in my projects
Based on what you need you can write a simple mapper on your own (with usage of Java reflection API to reduce boilerplate) or you can use such tools as Dozer
I recommend mapstruct(faster type-safe and easy to understand ). Java reflection libraries are too slow and and Error could be thrown in Java's execution time.
http://mapstruct.org
Related
I have a web application where the user client calls a web service (lets call it svc1), which in turn calls another web service (svc2) to get some data.
The UI sends an input DTO to svc1 which converts it to input MODEL for svc2, svc2 then returns output MODEL to svc1 which is converted to output DTO to be sent to the browser.
The svc1 code is implemented as below:
public OutputDto svc1(InputDto dto1){
InputModel model1 = inputAssembler.convertViewToModel(dto1);
Output model2 = svc2.call(model1);
return outputAssembler.convertModelToView(model2);
}
I want to know how to implement a design which will take care of calling the convertViewToModel() and convertModelToView() everytime the svc1 method is executed. I have the design in such a way that every Model/View pair has an Assembler (Mapper) class that has got two methods called convertViewToModel() and convertModelToView()
interface Assembler<S,T>{
S convertModelToView(T t);
T convertViewToModel(S s);
}
class InputAssembler<InputDto, InputModel> implements Assembler{
....
}
I am thinking about AOP, but I think I am missing something.
You could try using a simple mapper dependency like MapStruct , which have functions that automatically map between two Java Beans.This is particularly useful for cases when there is a lot of boiler plate code needed to convert one DTO to model and vice-versa.
The added advantage is that Mapstruct has inbuilt support for spring and Dependency Injection.
The dependency that is needed is :
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.3.0.Beta2</version>
</dependency>
Also take care to include the mapstruct-processor plugin in pom.
Then you can provide an interface like (not accurate as i don't know your dto class and fields) :
#Mapper public interface OutputMapper {
#Mappings({
#Mapping(target="id", source="input.id"),
#Mapping(target="name", source="input.name")
})
EmployeeDTO inputToOutputDTO(Input entity);
#Mappings({
#Mapping(target="id", source="dto.id"),
#Mapping(target="name", source="dto.name")
})
Employee outputDTOtoInput(OutputDTO dto); }
But for your use case i think you will need to use Generic Type Converters. You will have to use java generics to define generic converters for each of the object type.One sample i found.
I'm using ModelMapper to convert some objects to complex DTOs and vice-versa.
Even though I've tried to understand the documentation, I've found hard to understand when to use a Converter or a Provider or an AbstractConverter.
Now, for example, if I want to convert String properties to little DTOs inside of the destination DTO, I'm doing it manually inside an abstract converter.
For instance:
dest.setAddressDTO(new AddressDTO(source.getStreet(), source.getNumber()));
Is though that the right way to do it?
When should I use a provider?
And if I want to set properties with conditionals, can I use Conditional from within the converter or that's only when using a PropertyMap ?
Additionally, is it a good practice to use the same modelMapper instance to convert several different types of objects?
Thanks in advance
The right way to work with this is to use Converters.
For example, let's say I want to create a converter to convert a dto into a domain object.
So first you define a converter:
private Converter companyDtoToCompany = new AbstractConverter<CompanyDto, Company>() {
#Override
protected Company convert(CompanyDto source) {
Company dest = new Company();
dest.setName(source.getName());
dest.setAddress(source.getAddress());
dest.setContactName(source.getContactName());
dest.setContactEmail(source.getContactEmail());
(...)
dest.setStatus(source.getStatus());
return dest;
}
};
Then you add it to the mapper in the configureMappings() method:
modelMapper = new ModelMapper();
// Using STRICT mode to prevent strange entities mappin
modelMapper.getConfiguration()
.setMatchingStrategy(MatchingStrategies.STRICT);
modelMapper.addConverter(companyDtoToCompany);
// modelMapper.addConverter(otherConverter);
}
And finally you just need to add the mapping methods for those types you can use from your code:
public Company convertCompanyReqDtoToCompany(CompanyDto dto, Class<Company> destinationType) {
return modelMapper.map(dto, destinationType);
}
It is okay to use Parcelable, Realm, and GSON in one project in Android development? I'm just wondering how to implement it simultaneously because each of these libraries/frameworks has different annotations when making a POJO. Another one is Realm and Parcelable both persist data, so do I need to implement both?
GSON used to have quirkiness with Realm and required the following config
Gson gson = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
#Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class);
}
#Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
})
.create();
GSON uses field reflection to read data from objects, which means that on managed RealmObjects, your fields will be null value.
This is because GSON also does not offer the option of using accessors to obtain the data, but Realm proxies do not copy the data to memory.
If you need an object that can be sent through Retrofit with #Body annotation and is a managed RealmObject, when you need to do apiService.sendObject(realm.copyFromRealm(myObject));.
Parcelable is not necessary for RealmObject in most cases, because any object that is managed by the Realm is already persisted, and readily available anywhere as long as you have its primary key.
But if you need to make detached modifiable copies of data and you're bent on using an unmanaged instance of the class directly to build the object you intend to save, then you can easily create Parcelable class using Parceler library.
In short:
RealmObjects are easily persistable to Parcelable using Parceler, but you typically don't need it, you just send the primary key between Activities and not the whole object
GSON doesn't work well with managed objects, because GSON is kinda dumb so you need to make an in-memory copy first
Personally, I prefer to keep my API response and my RealmModels separate, it's easier if you rely on mapping to a more optimal schema.
This should be no problem cause you can use multiple annotations to one method or one class.
If an annotation have the same name, you should give it the exactly package name like #java.lang.Override
I wanted to populate bean from other bean.
Example:
// this is mapped to db using hibernate.
class A {
string name;
string age;
Date dateA;
B obj;
}
// this was mapped to db but now I'd like to populate it from class A member dateA;
class B{
Date date;
}
When I try to set B Object, I got nullpointerexception. Any idea how to process this issue?
Dozer is a Java Bean to Java Bean mapper that recursively copies data from one object to another.
Mapper mapper = new DozerBeanMapper();
DestinationObject destObject = mapper.map(sourceObject, DestinationObject.class);
For more information, follow
Dozer.
You should instantiate B Obj = new B() before invoking obj.setDate() .
If you are already doing this, If i am missing something please provide sufficient info in the question.
Apache Commons BeanUtils has several different methods to accomplish your goal.
You could use BeanUtils.copyProperties(). There is also BeanUtils.cloneBean().
A very popular library to do this sort of mapping is Apache commons BeanUtils.
It has got comprehensive set of functionality to copy one bean properties to another.
You can go through usage examples here and here.
I am using BeanUtils.copyProperties() for bean to dto mapping when I need to map all fields and field names are same. But I need not all field of source bean to map in destination dto, I used DozerBeanMapper.map() , because I haven't idea about to use BeanUtils in this situation.
So I think both methods having their own functionality, and there is no any similarity between both. Am I right? Please guide me.
You might check out my ModelMapper. It will intelligently map properties (fields/methods) even if the names are not exactly the same. Defining specific properties to be mapped or skipped is simple and uses real code instead of XML:
ModelMapper modelMapper = new ModelMapper();
modelMapper.addMappings(new PropertyMap<Order, OrderDTO>() {
protected void configure() {
map().setBillingStreet(source.getBillingStreetAddress());
skip().setBillingCity(null);
}
});
Check out the project homepage for more info:
http://modelmapper.org
We considered mapstruct for our usecase. See a sample below:
#Mapper
public interface MyMapper {
MyMapper INSTANCE = Mappers.getMapper(MyMapper.class);
To to(From from);
}
Here is a performance comparison of MapStruct against Selma, Orika, ModelMapper, Dozer and manual mapping:
Selma vs. MapStruct