Is there a global setting in Mapstruct that will trim a string value prior to setting it to a destination bean property - mapstruct

Is it possible to trim a string value before it is set against a bean property of type string in the destination bean?
Dozer offers such a facility through its mapping configuration for example,
<configuration>
<trim-strings>true</trim-strings>
</configuration>
Also see Dozer Global Configuration
With MapStruct 1.0.0.Final I can achieve this through Expressions or Before/After Mapping customization.
But wanted to know if there is a better way to handle such use cases.
Thanks in advance.

It appears MapStruct in its current form does not support this.
However one can achieve this effect with custom mapper methods, for example implement a class with a method that trims a String argument passed to it and then reference this class in the use attribute of the #Mapper annotation.
More at Invoking other mappers
If you require fine gained access control you could use
Selection based on Qualifiers
I was made aware of these approaches in response to a question I posted in mapstruct Google group

Example from #venkat-srinivasan answer's:
public class StringTrimmer {
public String trimString(String value) {
return value.trim();
}
}
and then in your mapper interface or class:
#Mapper(uses = StringTrimmer.class)
public interface MyMapper {

Related

BsonSerializationException when passing concrete Parameter in constructor to fill more general Property with .net driver

I have a Identity class that is extended by two classes StringIdentity and GuidIdentity. I want to use them in Objects as Property and save them in a MongoDb. For Example a class would look like this:
public class MyEvent : IDomainEvent
{
public MyEvent(GuidIdentity entityId)
{
EntityId = entityId;
}
public Identity EntityId { get; }
}
IDomainEvent forces me to implement the Identity Property, so I can (and do not want to) change the property type to GuidIdentity.
When I deserialize my class I get an exception like this:
Creator map for class Microwave.Eventstores.UnitTests. MyEvent has 1
arguments, but none are configured.
Which seems logical according to the .net driver doku, as my property does not match the type of the parameter and therefore can not be serialized. I had the solution to use the Identity as constructor parameter or make the constructor private and instantiate the class with a static Create method that takes the GuidIdentity as parameter. I also messed around with the BsonClassMap, but I really do not want to write all this kind of duplicate code for every class that implements IDomainEvent
So is there a way to tell the .net Driver to use the concrete class from the constructor instead of the more general PropertyType for all Types? Some kind of silver bullet solution? ;)
I am very new to mongodb so I am not aware of all the tricks that come with it, maybe someone can help me out here.

HTL Access Property Without Getter

I'm writing an AEM component and I have an object being returned that is a type from an SDK. This type has public properties and no getters. For simplicity, it might be defined like this:
class MyItem {
public String prop1;
public String prop2;
}
Now normally, I would need a getter, like so:
class MyItem {
public String prop1;
public String prop2;
public String getProp1() {
return prop1;
}
}
But I do not have this luxury. Right now, I've got a Java implementation that uses another type to resolve this, but I think it's sort of crazy that HTL doesn't allow me to just access prop1 directly (it calls the getter). I've reviewed the documentation and can't see any indication of how this could be done. I'd like to be able to write:
${item.prop1}
And have it access the public property instead of calling getProp1().
Is this possible?
You don't need getters for public fields if those fields were declared by your Java Use-class. There's actually a test in Apache Sling that covers this scenario:
https://github.com/apache/sling/blob/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/use/repopojo.html
This also applies to Use-classes exported from bundles.
For Sling Models using the adapter pattern [0] I've created https://issues.apache.org/jira/browse/SLING-7075.
[0] - https://sling.apache.org/documentation/bundles/models.html#specifying-an-alternate-adapter-class-since-110
From the official documentation
Once the use-class has initialized, the HTL file is run. During this stage HTL will typically pull in the state of various member variables of the use-class and render them for presentation.
To provide access to these values from within the HTL file you must define custom getter methods in the use-class according to the following naming convention:
A method of the form getXyz will expose within the HTL file an object property called xyz.
For example, in the following example, the methods getTitle and getDescription result in the object properties title and description becoming accessible within the context of the HTL file:
The HTL parser does enumerate all the public properties just like any java enumeration of public fuields which include getters and public memebers.
Although it is questionable on whether you should have public variable but thats not part of this discussion. In essence ot should work as pointed by others.

Spring Data JPA repository methods don't recognize property names with underscores

I have underscores in the entity property names, and when Spring tries to create the JPA repository implementation, it results in an exception trying to resolve the name of the property.
Entity:
#Entity
public class Student {
#Id
private String s_id;
private String s_name;
...
}
Repository:
#Repository
#Transactional
public interface StudentRepository extends CrudRepository<Student, String> {
List<Student> findByS__name(String name);
}
Exception:
org.springframework.data.mapping.PropertyReferenceException:
No property s found for type Student
It is said here http://docs.spring.io/spring-data/jpa/docs/current/reference/html/
If your property names contain underscores (e.g. first_name) you can
escape the underscore in the method name with a second underscore. For
a first_name property the query method would have to be named
findByFirst__name(…).
I just did as document said, but I still got the exception.
I dont want write #Query by myself, and I need underscore in my property name, how to fix this problem?
I use Spring data jpa 1.8.0.RELEASE + hibernate 4.3.9.Final
Avoid using underscores in the entity property names if you have control over the property naming. This will resolve your repository woes, and will result in a cleaner code-base. Developers dealing with the code after you will thank you.
Note, it's not just my opinion: Spring specifically discourages using underscores.
As we treat underscore as a reserved character we strongly advise to
follow standard Java naming conventions (i.e. not using underscores in
property names but camel case instead).
this JIRA issue shows why the documentation was updated with this reccomendation, and the part describing the double underscore option were removed.
I suspect your root problem is that Spring/Hibernate is not mapping camel case property names to the snake case names you have for your columns in the database. What you really need is for your property name to be interpreted in the SQL that hiberate generates as S_NAME.
Is that why underscores in your property name are "required"? If so, there are a few solutions:
Option 1: #Column annotation
To get JPA/Hibernate to map to the correct column names you can tell it the names explicitly. Use the annotation #Column(name="...") to tell it what column names to use in SQL. Then the field names are not constrained by the column names.
#Entity
public class Student {
#Id
#Column(name="s_id")
private String sId;
#Column(name="s_name")
private String sName;
//...getters and setters...
}
Option 2: Improved Naming Strategy
Or if your application has a large number of entities, rather than adding #Column to every property, change the default naming strategy in your configuration file to the hibernate improved naming strategy.
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
This naming strategy will convert camelCase to SNAKE_CASE. Then your class could look as simple as this:
#Entity
public class Student {
#Id
private String sId;
private String sName;
//...getters and setters...
}
Using either of those options, when it creates the SQL it will resolve the column names to:
S_ID
S_NAME
Note: If you are using, or can use Spring Boot, the auto-configuration default will use SpringNamingStrategy, which is a slightly modified version of the hibernate improved strategy. You won't have to do anything to get this improved naming strategy.
The finish line:
Using camel case in your property names you can write your repository method name using camel case, and you can stop trying to wrangle the double underscore:
#Repository
#Transactional
public interface StudentRepository extends CrudRepository<Student, String> {
List<Student> findBySName(String name);
}
Writing double underscore i.e. writing findByS__Name() for property name s_name just does not work. I have tried and tested it. Go by the above answer and change the name of existing instance variables in your entity class. Just dont change getters and setters as they might be used in the existing code.
If you cant change the entities which was my case then better use jqpl query or native sql query on top of repository method
#Query("select s from Student s where s.s_name=?")
List<Student> findBySName();

Is it possible to specify a property naming strategy with an annotation?

I have a class defined as:
class Person {
public int age;
public String firstName;
}
Note that I use camel case for the field names. Also, I know that I could have generated getters and setters but I tend to not do that for simple domain objects.
When I deserialize a JSON or XML response in my REST API, it should spit out:
<Person><Age>11</Age><FirstName>Johnson</FirstName></Person>
You will notice that the first letter is upper-cased.
I could use, for example, #JsonPoperty("FirstName") on my POJO to get the output the way I need it, but this doesn't scale when there are too many fields. I'd like to use a custom property naming strategy (as described in How To Use Property Naming Strategy In Jackson). But instead of configuring an ObjectMapper, I was wondering if its possible to specify a naming strategy using annotations?
Thanks

mybatis interface mapper - overloaded methods

Can we have overloaded methods in mapper interface? If yes, how does mybatis differentiate the elements in mapper xml?
Can we have overloaded methods in mapper interface? If you mean to implement Mapper interface --> NO
Mybatis defferentiate the elements in mapper xml by the "id".
For example if we have an addUser method without annotation we can overload it in xml file by specifying id="addUser":
public interface UserMapper {
void addUser( String name);
}
xml Mapper :
<insert id="addUser" ... >
No. I am afraid that is not supported and seems it won't be. More recent request was made for the same feature, but it is marked as wontfix