I've a question in spring data elasticsearch.I would like to know how whether we can set the annotation values of #Document annotation from a properties file or set it dynamically.
For eg :-
#Document(indexName = "myindex",type="mytype")
public class DocumentModel {
......
}
Here,I want to set the values of this annotation from a .properties file or use some setter methods for the same instead of hard coding it. Is there any proper way to do this ? Please help!
If you're using elasticsearchTemplate, there is a simpler variant, you can do it like this:
IndexQuery indexQuery = new IndexQueryBuilder()
.withId(docModel.getId())
.withObject(docModel)
.withIndex("myindex"+docModel.getUserId()).withTypes(<type_name>).build();
the call to withIndex("...") will override whatever index name you have in the #Document annotation
Related
We have a pojo generated from yml which has #JsonProperty defined on the getter. This is based on maven plugin for openapi. For one such yml, we have a field settlementType. We can't change the name as this is the field to be sent to the vendor in the rest api call. When using jackson's ObjectMapper to deserializa the object, we get the following error -
Conflicting setter definitions for property "settlementType":
settlementType(1 param) vs setSettlementType(1 param).
I tried for a mixin class.
public class SettlementTypeMixin {
#JsonProperty("settlementType"
String settlementType;
#JsonIgnore
public void setSettlementType(String settlementType) {
this.settlementType = settelementType;
}
}
I added the mixin to the mapper using addMixinAnnotations method. But I don't see any change in the behavior.
I also tried setting the fieldVisibility, getterVisibility, setterVisibility and CreatorVisibilities as well. There are other types as well which the yml needs and at the end I have to enable the visibility for all the types mentioned below.
I am not able to get the object mapped using jackson. Please let me know if there is a way out for this.
I have the following bean that describes a mongo document, and that uses lombok:
#JsonDeserialize(builder = MyClass.MyClassBuilder.class)
#Builder(toBuilder = true)
#Value
public class MyClass {
private final String id;
#Default
private final String field = "defaultValue";
#JsonPOJOBuilder(withPrefix = "")
public static class MyClassBuilder {}
}
When deserializing {"id": "document"} with jackson, I end-up with a bean containing both id=document and field=defaultValue because it used the builder that provide a default value for the field.
Now what I want to do, is to have the defaultValue set for documents coming out of the database (coming from ReactiveMongoTemplate). But it seems to use the all args constructor even if I set it private (or some reflect black magic)
So the main question is: is it possible to tell spring to use the builder to build the bean when coming out of the database?
You are not going to be able to use your custom serialiser because when I go through the source code of MappingMongoConverter in spring mongodb (debugged it with a sample app) , I see only the following steps.
Once the value from db is available as org.bson.Document, MappingMongoConverter.java is looking to create your entity object.
First, it checks if you have any custom converters registered and if you have it, then use it. So one option is to use a custom converter registered.
If there is no custom converters registered, it goes and find the PersistenceConstructor and use it. I had an object with 3 constructors (no param, one param, and all param) and it chose my no param constructor.
However, if I annotate a constructor with #PersistenceConstructor, it is choosing that constructor. So could follow this approach but then you have to keep String field un-initialised and getting initialised differently in each constructor
MappingMongoConverter.java
conversions.hasCustomReadTarget
persistenceConstructor
I have a Spring, Hibernate application. I would like to set scheme property of #Table annotation like this using value from application.properties file.
#Entity
#Table(schema = "${hibernate.scheme}")
public class Holidays {
// code
}
But it does not work. Spring does not substitute ${hibernate.scheme} with property value. Is there a way to solve it?
I am trying to do this to use different scheme for tests.
You can try default_schema: ${schema} in your app.yml and in test, you can supply the value of schema in app-test.yml.
I have a "details.yml" file, considering all the setting for getting all values from "yml.file" is done. But I am unable to store Map values into
"Map"
Here is my "details.yml" file below
details:
company:XYZ
values:
name: Manish
last: Raut
And in my class file i am able to get the values of "company" from yml file using #Value("${company}")
#Component
#EnableConfigurationProperties
#ConfigurationProperties(prefix = "details")
public class abcd() {
#Value("${company}")
String company;
#Value("${values}")
Map<String, String> values =new HashMap<String, String>();
...............................
}
i am not able to get those values in Mao which i created in this class, but i am getting values for "Company".
Help me with this?
Im the past, I added getter/setter for MAP type and it was work.
Did you try it? (getter/setter for 'values')
I'm not really sure what marshalling framework Spring uses behind the scenes and how it configures it (you could probably find out with some debugging and maybe make it work for your case), but you could always add an extra layer to your application and configure your own.
For instance you could use Jackson with yaml dataformat - https://dzone.com/articles/read-yaml-in-java-with-jackson.
I am using following mapper to map entities:
public interface AssigmentFileMapper {
AssigmentFileDTO assigmentFileToAssigmentFileDTO(AssigmentFile assigmentFile);
AssigmentFile assigmentFileDTOToAssigmentFile(AssigmentFileDTO assigmentFileDTO);
#Mapping(target = "data", ignore = true)
List<AssigmentFileDTO> assigmentFilesToAssigmentFileDTOs(List<AssigmentFile> assigmentFiles);
List<AssigmentFile> assigmentFileDTOsToAssigmentFiles(List<AssigmentFileDTO> assigmentFileDTOs);
}
I need to ignore the "data" field only for entities that mapped as collection.
But it looks like #Mapping works only for single entities. Also I've noticed that generated method assigmentFilesToAssigmentFileDTOs just uses assigmentFileToAssigmentFileDTO in for-loop. Is there any solution for that?
MapStruct uses the assignment that it can find for the collection mapping. In order to achieve what you want you will have to define a custom method where you are going to ignore the data field explicitly and then use #IterableMapping(qualifiedBy) or #IterableMapping(qualifiedByName) to select the required method.
Your mapper should look like:
public interface AssigmentFileMapper {
AssigmentFileDTO assigmentFileToAssigmentFileDTO(AssigmentFile assigmentFile);
AssigmentFile assigmentFileDTOToAssigmentFile(AssigmentFileDTO assigmentFileDTO);
#IterableMapping(qualifiedByName="mapWithoutData")
List<AssigmentFileDTO> assigmentFilesToAssigmentFileDTOs(List<AssigmentFile> assigmentFiles);
List<AssigmentFile> assigmentFileDTOsToAssigmentFiles(List<AssigmentFileDTO> assigmentFileDTOs);
#Named("mapWithoutData")
#Mapping(target = "data", ignore = true)
AssignmentFileDto mapWithouData(AssignmentFile source)
}
You should use org.mapstruct.Named and not javax.inject.Named for this to work. You can also define your own annotation by using org.mapstruct.Qualifier
You can find more information here in the documentation.