I tried enabling the -parameters flag in a project in order to use the JDBI ConstructorMapper without having to annotate each parameter.
What I then discovered was that the Jackson serialization changed behavior. I have been able to identify two things that have changed, but I have been unable to find any documentation on it.
When using the JsonCreator with mode default it now defaults to mode PROPERTIES when before it defaulted to mode DELEGATING. I now have to set this explicitly.
When using JsonProperty on a constructor parameter, that name is also kept when serializing the object. It used to serialize to the getter name, unless anything else was specified.
Are these all the changes to Jackson behavior? Also, are there any global settings I can change, so that I don't have to add lots of new annotations to my codebase?
I have tried looking for documentation, but it is hard to find the correct search terms.
Related
I have a problem with serialization of "is getter" accessor to property name.
I have a class with boolean isState() accessor method and property with name isState.
During serialization I see that object mapper is convert isState() method as state property.
Of course I can use #JsonProperty annotation but I need to do it generically for all such cases.
Before jackson-databind 2.12.0 it worked, unfortunately it stopped now because AccessorNamingStrategy has been added with a new way to find field names for getters. I can extend the AccessorNamingStrategy class and change the way to find field names, but it's too much code duplication to achieve such a minor goal. Issue: Extract getter/setter/field name mangling from 'BeanUtil' into pluggable 'AccessorNamingStrategy'
I tried to fight setAccessorNaming because it came out from version 2.12.0 and setPropertyNamingStrategy but unfortunately with poor results.
Edit:
I was able to fix the problem like this (image), if anyone has something better please let me know.
Quite often, when I use annotations from Java libraries in Kotlin code, I have to specify target in order to specify what element in the compilled code has to be annotated:
data class User(
val id: String,
#get:Email
val email: String
)
Instead of specifying #get:Email, I would love to be able to use simply #Email, especially if it occurs in many places.
Question: Is there a way to hint Kotlin compiler to use a different target in all places so that if I use #Email it will handle it as if it was #get:Email? Or is there any other way to omit specifying target? How can it be achieved? May it be done on the compilation stage via annotation processing (like Lombok does)?
I would appreciate any ideas even if they don't answer my question directly.
You can't override it. Maybe create annotation that will target #Email annotation and provide the property getter when it tries to call target.
Specifying target is dictated by the annotation target. When the target of the annotation is specified to jvm use-targets then you must use #get: to specify that the annotation targets the getter of the property.
In order to use simply #Email you must use kotlin target types for your annotation, probably PROPERTY. Note that, PROPERTY target doesn't work with Java.
#Retention(AnnotationRetention.RUNTIME)
#Target(AnnotationTarget.PROPERTY)
annotation class Email
It should be possible with Kotlin Compiler plugins API. It's a complicated way, tho.
To achieve this you will need to add a ClassBuilder interceptor with a visitor handling #Email annotation and specifying a correct target.
Can't say without getting deeper if visitor will be enough or you will also need to modify source code on one of the compiler stages, check TreeVisitor.
I am getting started with MapStruct. I am unable to understand when do we use "expression" tag in MapStruct? Why do we have certain mappings where we use "target" tag and "expression" tag? Does it mean that expressions are used when you want to map two or more fields within a bean to a single property/field in the target as mentioned in the documentation "http://mapstruct.org/documentation/stable/reference/html/#expressions"
Expressions are used when you can't map a source - to a target property or when a constant does not apply. MapStruct envisioned that several language could be used to address expressions. However, only plain java is implemented (hence "java(... )" ). EL was envisioned but not yet realised.
A typical use case that I use is generating a UUID. But even there you could try the new #Context to achieve that goal.
Remember, the stuff within the brackets is put directly in the generated code. The IDE can't check its correctness, and you will only spot problems during compilation.
Expressions are IMHO a fallback means / gap filler for stuff that is not yet implemented in MapStruct.
Note: Mapping target-to-source by means of a custom method as suggested in the other answers can be done automatically. MapStruct will recognised the signature (return type, source type) and call your custom method. You can do this in the same interface (default method) or in a used mapper.
In general, MapStruct expressions are used when you simple cannot write a MapStruct mapper. They should be used as a fallback approach when the library doesn't apply to your use-case.
For example, -- as the documentation says -- when a mapping requires more than one source variable, an expression can be used to "inject" them to a mapper method.
Another use case is when the source variable you need to use -- say bar -- is not a part of the source class but a member of one of its variables (here, classVar). You would map it to the target field foo using a custom myCustomMethod method with #Mapping(target="foo", expression="java(myCustomMethod(source.classVar.bar)))".
Just another Java problem (I'm a noob, I know): is it possible to use dynamic property binding in a Custom Control with a dynamic property getter in a Java bean?
I'll explain. I use this feature extensively in my Custom Controls:
<xp:inputTextarea id="DF_TiersM">
<xp:this.value><![CDATA[#{compositeData.dataSource[compositeData.fieldName]}]]></xp:this.value>
This is used in a control where both datasource and the name of the field are passed as parameters. This works, so far so good.
Now, in some cases, the datasource is a managed bean. When the above lines are interpreted, apparently code is generated to get or set the value of ... something. But what exactly?
I get this error: Error getting property 'SomeField' from bean of type com.sjef.AnyRecord which I guess is correct for there is no public getSomeField() in my bean. All properties are defined dynamically in the bean.
So how can I make XPages read the properties? Is there a universal getter (and setter) that allows me to use the name of a property as a parameter instead of the inclusion in a fixed method name? If XPages doesn't find getSomeField(), will it try something else instead, e.g. just get(String name) or so?
As always: I really appreciate your help and answers!
The way the binding works depends on whether or not your Java object implements a supported interface. If it doesn't (if it's just some random Java object), then any properties are treated as "bean-style" names, so that, if you want to call ".getSomeField()", then the binding would be like "#{obj.someField}" (or "#{obj['someField']}", or so forth).
If you want it to fall back to a common method, that's a job for either the DataObject or Map interfaces - Map is larger to implement, but is more standard (and you could inherit from AbstractMap if applicable), while DataObject is basically an XPages-ism but one I'm a big fan of (for reference, document data sources are DataObjects). Be warned, though: if you implement one of those, EL will only bind to the get or getValue method and will ignore normal setters and getters. If you want to use those when present, you'll have to write reflection code to do that (I recommend using Apache BeanUtils).
I have a post describing this in more detail on my blog: https://frostillic.us/f.nsf/posts/expanding-your-use-of-el-%28part-1%29
We just upgraded some maven dependencies, that triggered an update of Jackson from 1.7.x to 1.9.x
We use to annotate #JsonIgnore on setter methods, on methods not supposed to be set from client side. for example: the owner of an object (with should be set from the authentication principal), etc.
It seems to us that the semanthincs of this annotation have changed, is that possible? now the field is been jsonignored in all case, and not only when being set.
is that the case? is there an alternative way in 1.9 to implement ignore SET only?
thanks!
r.
Ok, I think I found and explicit mention to this issue in the javadoc. (jackson documentation is not easy to go through).
In addition, starting with Jackson 1.9, if this is the only annotation associated with a property, it will also cause cause the whole property to be ignored: that is, if setter has this annotation and getter has no annotations, getter is also effectively ignored. It is still possible for different accessors to use different annotations; so if only "getter" is to be ignored, other accessors (setter or field) would need explicit annotation to prevent ignoral (usually JsonProperty).