Dozer Deep Property Mapping - java-8

public class Something{
private string id;
private SomethingElse somethingElse;
private OtherProperties...
}
public class SomethingElse{
private string id;
private OtherProperties...
}
public class SomethingDto{
private string id;
private string somethingElseId;
private OtherProperties...
}
When mapping from something to SomethingDto I have to do
<mapping>
<class-a>Something</class-a>
<class-b>SomethingDto</class-b>
<field>
<a>somethingElse.id</a>
<b>somethingElse</b>
</field>
</mapping>
I'm not sure how to do the opposite what I want is "new SomethingElse" and then set the id like this
public class Something{
private string id;
private SomethingElse somethingElse;
private OtherProperties...
public void setSomethingElseById(String somethingElseId){
somethingElse = new SomethingElse;
somethingElse.setId(somethingElseId);
}
}
<mapping>
<class-a>SomethingDto</class-a>
<class-b>Something</class-b>
<field>
<a>somethingElse</a>
<b set-method='setSomethingElseById(SomethingElse)' >somethingElse</b>
</field>
</mapping>
This really looks like a bad solution so I tried the custom converter
public class SomethingDtoToSomethingConverter extends DozerConverter<String, SomethingElse> {
public SomethingDtoToSomethingConverter () {
super(String.class, SomethingElse.class);
}
#Override
public SomethingElse convertTo(String source, SomethingElse destination) {
destination = new SomethingElse();
destination.setId(source);
return destination;
}
#Override
public String convertFrom(SomethingElse source, String destination) {
destination = source.getId();
return destination ;
}
}
This looks like a ridiculous amount of code for something really simple
How can I achieve a cleaner solution?

What version of Dozer are you using? This should just work out of the box using the first mapping you defined as Dozer mappings are bi-directional by default.
I've created an example based on your code with a unit test which passes:
Something.java
public class Something {
private String id;
private SomethingElse somethingElse;
...
}
SomethingElse.java
public class SomethingElse {
private String id;
...
}
SomethingDto.java
public class SomethingDto {
private String id;
private String somethingElseId;
...
}
dozer.xml
<mapping>
<class-a>Something</class-a>
<class-b>SomethingDto</class-b>
<field>
<a>somethingElse.id</a>
<b>somethingElseId</b>
</field>
</mapping>
Unit Test
public class DozerMappingTest {
private DozerBeanMapper beanMapper;
#Test
public void sourceToDestination() {
List<String> mappingFiles = new ArrayList<String>();
mappingFiles.add("dozer.xml");
this.beanMapper = new DozerBeanMapper(mappingFiles);
Something source = new Something();
source.setId("A");
SomethingElse somethingElse = new SomethingElse();
somethingElse.setId("B");
source.setSomethingElse(somethingElse);
SomethingDto dest = beanMapper.map(source, SomethingDto.class);
assertEquals("A", dest.getId());
assertEquals("B", dest.getSomethingElseId());
}
#Test
public void destinationToSource() {
List<String> mappingFiles = new ArrayList<String>();
mappingFiles.add("dozer.xml");
this.beanMapper = new DozerBeanMapper(mappingFiles);
SomethingDto source = new SomethingDto();
source.setId("A");
source.setSomethingElseId("B");
Something dest = beanMapper.map(source, Something.class);
assertEquals("A", dest.getId());
assertEquals("B", dest.getSomethingElse().getId());
}
}

Related

Return the built Enum to JSON

I have an object and an enum for it. When I give away an object, I want my enum inside the object to be displayed as an object with the name and value attributes without using DTO, or to be partially used. I want json to build this object itself (enum with name and value), and I give only the object in which this enum is contained.
public enum MyType {
TT("Time Tu"), TD("Time dust");
MyType(String value) {
this.value = value;
}
private String value;
public String getValue() {
return value;
}
#Override
public String toString() {
return value;
}
Here is the DTO, it may be necessary (get/set/constructor auto generated by Intellij Idea)
public class MyTypeWrapper {
private String name;
private String value;
}
#Entity
public class MyObject {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
private String number;
........
private MyType myType;
........
}
Perhaps serialization/deserialization is needed? How to do it?
It should go something like this:
{
.....
myType: {
"name: "TT",
"value: "TD"
},
.....
}
Perhaps this is a piece of the solution? But I'm not sure that it will work, and it's not clear how to serialize
public enum MyType {
......
#JsonValue
private MyTypeWrapper getWrapper()
return new MyTypeWrapper(this.name, this.value)
}
......
}
This turned out to be the solution
public enum MyType {
......
#JsonValue
private MyTypeWrapper getWrapper()
return new MyTypeWrapper(this.name, this.value)
}
......
}

MapStruct: mapping from object with a list of complex object

Supposing I have the following classes:
public class A {
private String id;
private List<B> related;
}
public class B {
private String id;
private String name;
}
public class ADTO {
private String id;
private List<BDTO> relations;
}
public class BDTO {
private String identificator;
private String relatedName;
}
How can I create a mapper that given an A object type returns me an ADTO object with all the information? I have to create two different mappers? Can it be done in only one mapper? I think it would be something like the following, but I don't know how to map the atributtes from the list:
#Mapper
public interface MyMapper {
#Mappings({ #Mapping(source = "related", target = "relations") })
ADTO mapperA(A obj);
}
Thanks in advance.
try this (not tested but should work properly)
when you mapping lists you should make a map for both the class element and the list to map all the elements of the list)
#Mapper
public interface MyMapper {
#Mappings({ #Mapping(source = "related", target = "relations") })
ADTO mapperA(A obj);
#Mappings(
{ #Mapping(source = "id", target = "identificator") },
{ #Mapping(source = "name", target = "relatedName") })
BDTO bDTOMapping(B b);
List<BDTO> bDTOListMapping(List<B> bList);
}

How to reference a properties value inside the schema attribute of an entity?

There is an entity :
#Entity
#Table(name = "ITMMASTER" , schema = "TOMCTB")
public class Article {
#Id
#Column(name = "ITMREF_0")
private String code_article;
#Column(name = "ACCCOD_0")
private String acccod;
public String getCode_article() {
return code_article;
}
public void setCode_article(String code) {
this.code_article = code;
}
public String getAcccod() {
return acccod;
}
public void setAcccod(String acccod) {
this.acccod = acccod;
}
}
I want to make the schema attribute to be dynamic depending on a properties file property value , for example : env.schema = TOMEXPL.
How to achieve that ?
I didn't tried it but I guess this should work.
public class DynamicNamingStrategy extends DefaultNamingStrategy {
#Value("db.table.name")
private String name;
#Override
public String tableName(String tableName) {
return name;
}
...
}
SessionFactory sessionFactory;
Configuration config = new AnnotationConfiguration()
.configure("hibernate.cfg.xml")
.setNamingStrategy( new DynamicNamingStrategy() );
sessionFactory = config.buildSessionFactory();
session = sessionFactory.openSession();

How to load key/value pairs from properties file loaded via PropertyPlaceholderConfigurer in Spring

I have a property file with key/value pairs that looks like below:
#state/city/counties
fl.regionA.counties=abc,def,ghi,jkl
fl.regionB.counties=xyz,qrs,tuv,wxy
The property file is loaded via code snippet below:
#Configuration
public class Config {
#Bean
public static PropertyPlaceholderConfigurer properties(){
...
}
How can I load the a list of StateRegionMappings where StateRegionMapping:
public class StateRegionMapping{
private List<String> counties;
private String state;
private String region;
...
}
Update 5/23/2017:
My other alternate key/value structure is like this:
states.config[0].state=fl
states.config[0].name=regionA
states.config[0].counties=abc,def,ghi,jkl
states.config[1].state=fl
states.config[1].name=regionB
states.config[1].counties=xyz,qrs,tuv,wxy
If I get you right, you want to configure a list of states where each state has a region and each region a list of counties. With properties files this would look like this:
states-config.states[0].name=fl
states-config.states[0].regions[0].name=regionA
states-config.states[0].regions[0].counties[0]=abc
states-config.states[0].regions[0].counties[1]=def
states-config.states[0].regions[0].counties[2]=ghi
states-config.states[0].regions[0].counties[3]=jkl
states-config.states[0].regions[1].name=regionB
states-config.states[0].regions[1].counties[0]=xyz
states-config.states[0].regions[1].counties[1]=qrs
states-config.states[0].regions[1].counties[2]=tuv
states-config.states[0].regions[1].counties[3]=wxy
With YAML this is a bit more readable:
states-config:
states:
- name: fl
regions:
- name: regionA
counties:
- abc
- def
- ghi
- jkl
- name: regionB
counties:
- xyz
- qrs
- tuv
- wxy
The needed java config would look like this:
#ConfigurationProperties("states-config")
public class Config {
private List<State> states = new ArrayList<>();
public List<State> getStates() {
return states;
}
public void setStates(List<State> states) {
this.states = states;
}
public static class State {
private String name;
private List<Region> regions = new ArrayList<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Region> getRegions() {
return regions;
}
public void setRegions(List<Region> regions) {
this.regions = regions;
}
}
public static class Region {
private String name;
private List<String> counties = new ArrayList<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getCounties() {
return counties;
}
public void setCounties(List<String> counties) {
this.counties = counties;
}
}
}
To your update: this would work with the following config using your StateRegionMapping class:
#ConfigurationProperties("states")
public class Config {
private List<StateRegionMapping> config = new ArrayList<>();
public List<StateRegionMapping> getConfig() {
return config;
}
public void setConfig(List<StateRegionMapping> config) {
this.config = config;
}
}
Just one minor change: since in your StateRegionMapping class the region is named region, your must use this also in the properties instead of name:
states.config[0].state=fl
states.config[0].region=regionA
....
It is absolutely possible! Try this.
This should be present in your class where you want to load.
#Value("#{${passingscore.subjectwise}}")
private Map<String, String> passingScorePerSubjectMap;
The should be present in the application.properties file and define the key-value map properties like below.
passingscore.subjectwise= {'Maths': '40','Physics':'50','Chemistry':'70'}

XML to Objects mapper

I am trying to make one application file format parser & generator. Application uses xml files with custom DTD. Currently I am thinking about writing object mapper with nokogiri to parse xml to objects and use these object to generate xml back. I have tried HappyMapper and xml-mapping but they didn't utilize full xml format. So Currently now I have made this but I think it is bit bad design.
http://pastie.org/5393012
You can use C# with XMLSerilaizer, it is the best. Here is the example:
---------------just a lot of entity ----------------------
using System;
namespace BuilderSerialization {
public class Address {
public Address() {}
public string Address1;
public string Address2;
public string City;
public string State;
public string Zip;
public string Country;
} }
using System;
namespace BuilderSerialization {
public class Author {
public Author() { }
public string FirstName;
public string MiddleName;
public string LastName;
public string Title;
public string Gender;
public Address AddressObject;
} }
namespace BuilderSerialization {
public class Book {
public Book() { }
public string Title;
public Author AuthorObject;
public string ISBN;
public double RetailPrice;
public string Publisher;
}}
-------------------------------------------------------
using System;
using System.Xml.Serialization;
using System.IO;
namespace BuilderSerialization {
class TestClass {
static void Main(string[] args) {
Book BookObject = new Book();
XmlSerializer ser = new XmlSerializer(typeof(Book));
TextWriter writer = new StreamWriter("booktest.xml");
BookObject.Title = "Practical LotusScript";
BookObject.ISBN = "1884777767 ";
BookObject.Publisher = "Manning Publications";
BookObject.RetailPrice = 43.95;
BookObject.AuthorObject = new Author();
BookObject.AuthorObject.FirstName = "Tony";
BookObject.AuthorObject.LastName = "Patton";
BookObject.AuthorObject.Gender = "Male";
BookObject.AuthorObject.AddressObject = new Address();
BookObject.AuthorObject.AddressObject.Address1 = "1 Main Street";
BookObject.AuthorObject.AddressObject.City = "Anywhere";
BookObject.AuthorObject.AddressObject.State = "KY";
BookObject.AuthorObject.AddressObject.Zip = "40000";
BookObject.AuthorObject.AddressObject.Country = "USA";
ser.Serialize(writer, BookObject);
writer.Close();
} } }
After that you get the XML:
<?xml version="1.0" encoding="utf-8"?>
<Book xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Title>Practical LotusScript</Title>
<AuthorObject>
<FirstName>Tony</FirstName>
<LastName>Patton</LastName>
<Gender>Male</Gender>
<AddressObject>
<Address1>1 Main Street</Address1>
<City>Anywhere</City>
<State>KY</State>
<Zip>40000</Zip>
<Country>USA</Country>
</AddressObject>
</AuthorObject>
<ISBN>1884777767 </ISBN>
<RetailPrice>43.95</RetailPrice>
<Publisher>Manning Publications</Publisher>
</Book>

Resources