how to send string constant to a field value using dozer mapping? - java

'<mapping map-id="vehicle Info">
<class-a>vehicle Info</class-a>
<class-b>uninsured</class-b>
<field>
<a>CONSTANT_CAR</a>
<b>car.value</b>
</field>
</mapping>'
I'm trying to send the constant value of "CONSTANT_CAR" into the field of "car.value" which is located inside the vehicle
Can someone please guide me how can I pass the constant value to a setter which is located in the destination class.

You should be able to access the constant by setting the 'is-accessible="true"' for the constant field. So, your mapping could look something like this:
<mapping map-id="vehicle-info">
<class-a>path.to.VehicleInfo</class-a>
<class-b>path.to.Uninsured</class-b>
<field>
<a is-accessible="true">CONSTANT_CAR</a>
<b>car.value</b>
</field>
</mapping>
Make sure when naming the classes in the <class-a> and <class-b> tags you put the full path to the class.
I just tested with some sample code and it mapped the constant as expected. Let me know if it works for you!

Related

Apache Camel Dozer Expresison Mapping

I'm trying to map a class to another with Apache Camel and Dozer mapping.
Within my route I save an object of a class in a property, like .setProperty("test", testClass). Now I want to get the class object out of this property and map it to a field of a new class.
The camel dozer documentation Camel Dozer says that it is possible to map an expression to a field. If I'm trying to map the value of the property to the corresponding field, I'm getting always null as value.
This is the way I'm trying to get the value of the property
<field custom-converter-id="_expressionMapping" custom-converter-param="simple:${exchangeProperty.test}">
<a>expression</a>
<b>targetField</b>
</field>
Is there a possibility to do this?
Just off the top of my head, and looking at the documentation, you may just be missing a '\' in front of the '$' sign:
<field custom-converter-id="_expressionMapping"
custom-converter-param="simple:\${exchangeProperty.test}">
<a>expression</a>
<b>targetField</b>
</field>
I think its even specifically mentioned at the very end of the documentation:
Note that any properties within your expression must be escaped with "\" to prevent an error when Dozer attempts to resolve variable values defined using the EL.

Mapping with DOZER without method set

I am trying to convert two classes that have an attribute of type java.util.List, but one of the classes does not have a method "set*" only the method "get*" like this:
<mapping>
<class-a>com.mycompany.bean.SocioPj</class-a>
<class-b>com.mycompany.jaxb.SocioPjXml</class-b>
<field>
<a set-method="getListaSocios().add">listaSocios</a>
<b>listaSocios</b>
<a-hint>com.mycompany.bean.SocioPf,com.mycompany.bean.SocioPj</a-hint>
<b-hint>com.mycompany.jaxb.SocioPfXml,com.mycompany.jaxb.SocioPjXml</b-hint>
</field>
</mapping>
The example above the class: SocioPj doesn´t have a method setListSocios() when I tried to convert I catch this error:
[Time:2015-03-24 11:29:08,055][Level:ERROR][Thread:http-bio-8080-exec-10][OnboardingCCMFulfillmentImpl] org.dozer.MappingException: java.lang.ClassNotFoundException: /add
Has anyone faced this problem?
You can tell Dozer to directly access the field without calling the getter/setter (Even if the field is private):
<field>
<a is-accessible="true">listaSocios</a>
<b>listaSocios</b>
</field>

Call custom converter after default in dozer

Does Dozer could call custom converter after default?
I want to create something like chain. At first I want to call default converter to make most of convertion work and only after that call custom converter to populate complex fields?
EDIT
by default when I create custom converter I need to override two methods. Each of this method has 2 arguments source object and target object. But when we call convertTo method second argument(target object) equals to null. So may be I need to specify something in mapping file to make dozer process default converter before custom?
Sorry for bad english
After look into source code I understand that this probably imposible. Instead of this dozer library propose using custom-converters at field level like this:
<mapping wildcard="false" >
<class-a>package.A</class-a>
<class-b>package.B</class-b>
<field>
<a>id</a>
<b>id</b>
</field>
<field custom-converter="test.AtoBNameFieldCustomConverter">
<a>name</a>
<b>name</b>
</field>
</mapping>
May be this help someone.

Is there a way to utilize a generic mapping in dozer instead of duplicating it?

I am working on writing a dozer mapping to map fields from ClassA to ClassB. I have two use cases to address:
Use Case 1: Map all fields from ClassA to ClassB including "null" fields. This way I would be able to wipe out the value of a field from ClassB if it doesn't have a value in ClassA.
Use Case 2: Map only "not null" fields from ClassA to ClassB. This way I would be able to preserve fields in ClassB even when they don't have values in ClassA.
Currently, I have to write two different mappings to address this situation. The mappings are exactly alike, apart from the value of the attribute "map-null".
Question:
Is there a way to avoid this duplication of mappings and set the "map-null" attribute at runtime and just have one generic mapping defined in Dozer?
<mapping map-id="myMappings1" map-null="true">
<class-a>test.ClassA</class-a>
<class-b>test.ClassB</class-b>
<field>
<a>sampleVariable</a>
<b>samplevariable</b>
</field>
</mapping>
<mapping map-id="myMappings2" map-null="false">
<class-a>test.ClassA</class-a>
<class-b>test.ClassB</class-b>
<field>
<a>sampleVariable</a>
<b>samplevariable</b>
</field>
</mapping>

Dozer deep mapping not working

I am trying to use dozer 4.1 to map between classes. I have a source class that looks like this:
public class initRequest{
protected String id;
protected String[] details
}
I have a destination class that looks like this:
public class initResponse{
protected String id;
protected DetailsObject detObj;
}
public class DetailsObject{
protected List<String> details;
}
So essentially i want the string in the details array to be populated into the List in the Details object.
I have tried a mapping like this:
<mapping wildcard="true" >
<class-a>initRequest</class-a>
<class-b>initResponse</class-b>
<field>
<a is-accessible="true">details</a>
<b is-accessible="true">detObj.details</b>
</field>
</mapping>
But I get this error:
Exception in thread "main" net.sf.dozer.util.mapping.MappingException: java.lang.NoSuchFieldException: detObj.details
at net.sf.dozer.util.mapping.util.MappingUtils.throwMappingException(MappingUtils.java:91)
at net.sf.dozer.util.mapping.propertydescriptor.FieldPropertyDescriptor.<init>(FieldPropertyDescriptor.java:43)
at net.sf.dozer.util.mapping.propertydescriptor.PropertyDescriptorFactory.getPropertyDescriptor(PropertyDescriptorFactory.java:53)
at net.sf.dozer.util.mapping.fieldmap.FieldMap.getDestPropertyDescriptor(FieldMap.java:370)
at net.sf.dozer.util.mapping.fieldmap.FieldMap.getDestFieldType(FieldMap.java:103)
at net.sf.dozer.util.mapping.util.MappingsParser.processMappings(MappingsParser.java:95)
at net.sf.dozer.util.mapping.util.CustomMappingsLoader.load(CustomMappingsLoader.java:77)
at net.sf.dozer.util.mapping.DozerBeanMapper.loadCustomMappings(DozerBeanMapper.java:149)
at net.sf.dozer.util.mapping.DozerBeanMapper.getMappingProcessor(DozerBeanMapper.java:132)
at net.sf.dozer.util.mapping.DozerBeanMapper.map(DozerBeanMapper.java:94)
How can i map this so that it works?
This works for me. I am using 5.2.1 version
<mapping wildcard="true" >
<class-a>initRequest</class-a>
<class-b>initResponse</class-b>
<field>
<a>details</a>
<b is-accessible="true">detObj.details</b>
</field>
</mapping>
Note that "is-accessable" is not required for . Hope it helps
Problem solved...
is-accesible allows an object to be updated regardless of access modifier and presence of getters/setters (essential for objects generated using JAXB)
"dot" notation for deep mapping works to access nested objects
Combining the two is a feature that does not work in Dozer (maybe it does in a newer version)
solution...
modify the xsd such that the deep mapping is not required. This is not my ideal solution but its better than writing a custom converter for every object
In case of JaxB, use can download and use the plugin for generating the setters. Refer to this link for more details, https://jaxb2-commons.dev.java.net/collection-setter-injector/
I would guess that accessors (getter / setter) are missing.
By the way I think that you'll also need to provide an empty constructor for DetailsObject so dozer can instanciate it.
<b is-accessible="true">detObj.details</b>
Should be replaced with
<b is-accessible="true">DetailsObject.details</b>
While it does seem you cannnot use the "is-accessible" and dot notation together another approach is to break your deep mapping into smaller mappings.
We ran into this situation with JAX-WS generated code. You have lists that have no setter methods and in our case were deeply nested. We found our solution by simply breaking the large deep mapping into smaller mappings that "walked" our way to what we wanted. I tried to explain this in my blog here:
http://btarlton.blogspot.com/2014/08/dozer-deep-nestinga-different-approach.html
But the trick is just walking the object tree by smaller mappings and using is-accessible="true" when necessary to access the list with no setter and using "this" as the property name to keep passing the source along.
Hope this helps!
To summarize there are following options for this issue
1) Use JaxB pluggin to enable setters as discussed by Naveen
2) Use is-accessible for such properties
I believe using first approach unnecessarily exposes setters for collections/lists as you can risk of setting them with null.
We decided to enable is-accessible for such fields (and not to entire class) to avoid any side effects.
I have discussed the solution at Dozer Mapping Class level is-accessible

Categories

Resources