I am writing a mapper to map fields of 2 different POJOs in java. I have used Dozer mapper for simple mapping but in this case, I have a slightly complex strategy when it comes to set the value to the destination object. The getter is simple, but instead it setting it directly, I want to do some processing on the value.
My question is, can I use dozer mapper for my cause?
In case if its not possible, is it ok (from performance point of view) to use reflection to implement my own mapper (this is because I have defined the mapping in an xml file and dont want to hardcode it in the mapper class)?
<mapping>
<field>
<!-- source -->
<field-a name="cat">
<!-- destination -->
<field-b" name="dog">
</field>
</mapping>
Relevant to this xml, I want the following:
Source c;
Destination d;
d.setDog(someProcessing(c.getPsMessage()));
Note down the extra processing (someProcessing) after getting the value and before setting it to the destination object.
You can set your own getters-setters methods with Dozer. You can even map attributes with different type and name!:
Example:
<field>
<a>yourField</a>
<b set-method="nameOfYourFieldSetter(java.lang.String)">
nameOfYourFieldInOtherClass
</b>
</field>
Note down the extra processing (someProcessing) after getting the value and before setting it to the destination object.
You're overcomplicating things, use KISS principle:
Source c;
Destination d;
// String, Integer or what someProcessing returns!
String name = someProcessing(c.getPsMessage());
d.setDog(name);
Related
I have an attribute which requires custom converter along with the parent context and the particular attribute in the mapper config has been configured like this. Let's call this as ChildMaper which converts from ChildSourceClass to ChildDestinationClass
<field custom-converter="MyCustomConvertorClass">
<a>this</a>
<b>targetField</b>
</field>
And the mapper has been invoked recursively by from another mapper associated with the a ParentClass.
The MyCustomConvertorClass could return null or a HashMap based on certain conditions.
When the conversion happens directly on the ChildSourceClass, the conversion happens as expected. But when the mapper is invoked on the ParentClass and when the convertor returns null, the mapper is setting a empty hashmap and adding key this to the attribute represented by targetField.
Any idea why this is happening?
We are using Jackson XmlMapper and ObjectMapper for parsing XML and JSON files into object models in Java.
Problem is, we are also using them to validate (by catching xmlMapper.readValue(file, type) returning IOExeception, that the file given to parse, matches the model (so long as the required model fields are there, we dont care about unknown properties - as long as the whole object wouldn't be returned as null in all its properties.
So, using xmlMapper.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) does not quite work for us, as it fails the mapping if there are unknown attributes we did not care to map (or know about, or they don't always show up).
However, we STILL would like the mapping to fail, IF the object we are mapping to, becomes null (eg: the xml file given to map, is not at all like the correct structure - eg: it starts with as root element, while the model we are mapping to, starts with element, and doesn't have "pages" anywhere in the XML.
The main class for the model, is annotated as:
#JacksonXmlRootElement(localName = "ResultsSession"), and all attributes we need are annotated as #JacksonXmlProperty(localName = "someValue"), or (isAttribute = true)
Does this make sense?
Is there a way to make sure the mapped object contains the root element, without forcing fail or unknown properties?
I found an acceptable solution which works well.
The correct way of doing it, is though Java Bean Validator, something along the lines of:
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();
Set<ConstraintViolation<Object> violations = validator.validate(mappedObject);
if (violations.size > 0 ) {
for (ConstraintViolation<Object> violation : violations( {
LOGGER.error(violation.getMessage());
}
}
And the Object being validated, would have added something like: #NotNull(Message = "error message") to a key attributes, and that will work nicely.
Reference: https://www.baeldung.com/javax-validation
i habe a question concerning Dozer Bean Mapping. I have the follwing xml configuration parts (i donĀ“t understand some of this facts):
<mapping>
<class-a>
entity.template.TemplateEntity
</class-a>
<class-b>dto.template.TemplateDto
</class-b>
<field>
<a set-method="setLang" get-method="getLang">lang</a>
<b set-method="setLang" get-method="getLang">lang</b>
<a-hint>entity.template.TemplateLanguageEntity</a-hint>
<b-hint>dto.template.TemplateLanguageDto</b-hint>
</field>
</mapping>
What is the concret meaning of "set-method="setLang" get-method="getLang""?
What does the Dozer Bean Mapper do in this part? There is no other configuration, which describes, how to two collection should be mapped?
<a-hint>entity.template.TemplateLanguageEntity</a-hint>
<b-hint>dto.template.TemplateLanguageDto</b-hint>
Does the Dozer Mapper map all fields automatically, which are founded by them if no configuration was set?
Thanks for helping !
Greetz
Marwief
What is the concret meaning of "set-method="setLang" get-method="getLang""?
Beans that might have unorthodox getter and setter methods, Dozer support user specified setter and getter methods.To make a bi-directional mapping in this case, look at the following example below.
The source field in element A specifies a custom setter method and getter method using attributes.
<field>
<a set-method="placeValue" get-method="buildValue">value</a>
<b>value</b>
</field>
What does the Dozer Bean Mapper do in this part? There is no other configuration, which describes, how to two collection should be mapped?
Understand the Custom set() and get() methods dozer documentation.
Lets take for example if we are mapping a String to an ArrayList by calling the addIntegerToList() method.
Note that this is defined as a one-way field type since we can not map an ArrayList to a String.
<!-- we can not map a ArrayList to a String,
hence the one-way mapping -->
<field type="one-way">
<a>integerStr</a>
<b set-method="addIntegerToList">integerList</b>
</field>
Does the Dozer Mapper map all fields automatically, which are founded by them if no configuration was set?
Yes, Dozer Mapper maps all the fields automatically from class-A to class-B iff both the field names are same.
I have a bunch of classes that will be instantiated and passed between my JS front-end and Spring MVC.
I'm using Simple to serialize my object as XML for persistent storage and Jackson to pass it to my UI as JSON. Consequently I need to have an ID attribute that is used to reference an object, and this needs to be consistent in both the JSON, POJO and XML.
This means I need an ID attribute in my Java class. What type should I declare it as? I've seen int being used in the Simple library tutorial and I've also seen UUID being used here.
The Simple library creates id and ref attributes (or any other that you provide) to maintain references:
<parent name="john" id="1">
<children>
<child id="2" name="tom">
<parent ref="1"/>
</child>
</children>
</parent>
The accompanying Java to read it back in:
Strategy strategy = new CycleStrategy("id", "ref");
Serializer serializer = new Persister(strategy);
File source = new File("example.xml");
Parent parent = serializer.read(Parent.class, source);
The id isn't in the original Java object however, so it won't be passed with the JSON to the UI. Should I define a private UUID uid; and pass that, while also letting Simple generate the auxiliary id and ref attributes it uses, or is there a way to use a single Java attribue to do both?
EDIT: Hibernate has an #Id annotation, but I can't find something similar for Simple. Will this do?
#Attribute
private int id;
The problem is that I'll need to instantiate and pass it as JSON, but it needs to be unique as well (meaning it'd be easier to use UID). Also, will Simple use this id for its ref?
EDIT 2:
Using id as an attribute and then using the CycleStrategy causes it to use the value you define from the class and not the internal ones it uses in the XML which the ref point to... I'm using two attributes for now - a uuid I generate together with the id Simple uses internally.
I need to transform inbound payload into map (java.util.Map). There are any way to create map in mule xml configs?
Regards
EDIT:
Payload type is com.novell.LDAPAttributeSet which is set of LDAPAttribute objects. LDAPAttribute object contains name and value fields. I need to extract name and value fields and convert them to map. Extracting fields will done with jxpath expressions. But I don't know how to create map from these fields.
I suggest you use a Groovy transformer:
<script:transformer>
<script:script engine="groovy">
[key1: payload.attr1,
key2: payload.attr2]
</script:script>
</script:transformer>
Where key1,key2 are your choice of keys to use in the map and attr1,attr2 are attributes of the LDAPAttributeSet (or any other valid expression that allows you to get the desired values out of this object).
PS. In case you wonder, the script namespace is declared that way:
xmlns:script="http://www.mulesoft.org/schema/mule/scripting"
xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/scripting
http://www.mulesoft.org/schema/mule/scripting/3.1/mule-scripting.xsd"