Skip to content

DATAES-568 - MappingBuilder must use the @Field annotation's name att… #281

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

sothawo
Copy link
Collaborator

@sothawo sothawo commented Apr 30, 2019

…ribute.

I changed the MappingBuilder to use the ElasticsearchPersistentEntity and ElasticsearchPersistentProperty classes instead of doing it's own reflection on the class and fields. Using these we can now use the getFieldname() of the property to get the customized field name.

The logic of the MappingBuilder itself was not changed besides the different field name. What need to be changed was the call to setup the MappingBuilder - which now is an object instead of a collection of static functions - therefore there are some necessary changes in the Template classes and the test setups.

  • You have read the Spring Data contribution guidelines.
  • There is a ticket in the bug tracker for the project in our JIRA.
  • You use the code formatters provided here and have them applied to your changes. Don’t submit any formatting related changes.
  • You submit test cases (unit or integration tests) that back your changes.
  • You added yourself as author in the headers of the classes you touched. Amend the date range in the Apache license header if needed. For new types, add the license header (copy from another file and set the current year only).

@sothawo
Copy link
Collaborator Author

sothawo commented Apr 30, 2019

@xhaggi , @christophstrobl , @mp911de if yould hav a look please

Copy link
Member

@mp911de mp911de left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a review pass from a code perspective and not so much from a functional one and left a few comments. That's more food for thought than real issues.


xContentBuilder = buildMapping(clazz, persistentEntity.getIndexType(), property.getFieldName(),
persistentEntity.getParentType());
final MappingBuilder mappingBuilder = new MappingBuilder(elasticsearchConverter);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: No need for final variables.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


xContentBuilder = buildMapping(clazz, persistentEntity.getIndexType(), property.getFieldName(),
persistentEntity.getParentType());
final MappingBuilder mappingBuilder = new MappingBuilder(elasticsearchConverter);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: No need for final variables.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

for (java.lang.reflect.Field field : fields) {
if (entity != null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling getRequiredPersistentEntity(…) in the calling code guarantees that entity is not null.

On a related note: We typically annotate fields/parameters/methods with @org.springframework.lang.Nullable to indicate a field/parameter can be null or whether a method can return null. You get proper IDE support for @Nullable with IntelliJ IDEA and Eclipse.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the initial call this is true. But on the recursive call, the entity can be null, for example on processing the StockPrice entity in the MappingBuilder.shouldUseValueFromAnnotationType()test.

Wouldn't we need a package-info.java with the @org.springframework.lang.NonNullApi in it? I was thinking about that, but adding it to the packages I changed would have meant that I impose this on all the existing classes and therefore I refrained from it.

Nevertheless, I changed the nullable arguments in the MappingBuilder methods accordingly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, a package-info.java controls nullability defaults.

if (isGeoPointField) {
applyGeoPointFieldMapping(xContentBuilder, field);
}
final Iterator<? extends TypeInformation<?>> iterator = property.getPersistentEntityTypes().iterator();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: No need for final variables.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

applyGeoPointFieldMapping(xContentBuilder, field);
}
final Iterator<? extends TypeInformation<?>> iterator = property.getPersistentEntityTypes().iterator();
final ElasticsearchPersistentEntity<?> persistentEntity = iterator.hasNext()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related: You can use PersistentProperty.isEntity() to check whether a property references an entity.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, but to get the actual entity type there seems to be no more elegant way

private static boolean isIdField(java.lang.reflect.Field field, String idFieldName) {
return idFieldName.equals(field.getName());
}
private boolean isInIgnoreFields(ElasticsearchPersistentProperty property, Field parentFieldAnnotation) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Annotate nullable parameters with @Nullable.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
public class MappingBuilderTests {
public class MappingBuilderTests extends MappingContextBaseTests {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using JSON matchers/JSON extensions to verify JSON payload? (e.g. JSONAssert)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed all the JSON comparisons to JSONAssert, simplified some tests

/**
* @author Peter-Josef Meisch
*/
public class FieldNameEntity {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's see whether we can keep these as little visible as possible. Visibility in tests often leads to usage in other tests and this caused coupling.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, but I kept to the existing package structure, where all the entities are in one package, and the tests in the packages that match the classes to test. I move the FieldNameEntity as a nested class in the test itself, but that would make the test class even larger.

Or we could move the MappingBuilder, the tests and test entities to a separate package; org.springframework.data.elasticsearch.core.mapping wouldn't be appropriate as this is not the spring data mapping, but the Elasticsearch mapping definition, or do you think this package would do?

/**
* @author Peter-Josef Meisch
*/
public abstract class MappingContextBaseTests {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep this class package private.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:elasticsearch-rest-template-test.xml")
public class ElasticsearchRestTemplateTests extends ElasticsearchTemplateTests {

@Before
public void before() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this to the test base class ElasticsearchTemplateTests

@sothawo sothawo force-pushed the issue/DATAES-568 branch from cb9fed8 to 7c47b14 Compare May 3, 2019 19:59
@Override
public boolean isEntity() {

TypeInformation<?> typeInformation = getTypeInformation();
Copy link
Member

@mp911de mp911de May 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is exactly what AbstractPersistentProperty.isEntity() is doing. See https://github.com/spring-projects/spring-data-commons/blob/48c9297118e18273a0a3dfe3cf2f9a8ffd8fdca7/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java#L88-L91 and https://github.com/spring-projects/spring-data-commons/blob/48c9297118e18273a0a3dfe3cf2f9a8ffd8fdca7/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java#L247.

My previous comment should indicate to just use isEntity() so you can get rid of the code duplication.

SimpleTypeHolder is configurable so registered converters are considered (for e.g. date/time types and custom types that are handled using a converter).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aargh, I only looked at the base implementation in AbstractPersistentProperty but forgot to check the implementation of the lazy get(); therefore I thought it was different.

@sothawo sothawo force-pushed the issue/DATAES-568 branch 2 times, most recently from 384c978 to 1fcecc0 Compare May 4, 2019 16:41
@sothawo sothawo force-pushed the issue/DATAES-568 branch from 1fcecc0 to 12edf1f Compare May 4, 2019 16:53
@mp911de
Copy link
Member

mp911de commented May 6, 2019

That's merged and polished now.

@mp911de mp911de closed this May 6, 2019
mp911de pushed a commit that referenced this pull request May 6, 2019
mp911de added a commit that referenced this pull request May 6, 2019
Add package-info and nullability annotations to org.springframework.data.elasticsearch.core.mapping.
Extract method to avoid excessive nesting.

Add ticket references/convert old references to test methods. Move test models to inner classes. Use static imports for JSON Assert. Formatting.

Original pull request: #281.
@mp911de
Copy link
Member

mp911de commented May 6, 2019

After upgrading to ES 6.7, we're getting lots of test errors like:

build	06-May-2019 14:04:00		Suppressed: org.elasticsearch.client.ResponseException: method [PUT], host [http://127.0.0.1:9200], URI [/test-index-sample/_mapping/test-type?master_timeout=30s&include_type_name=true&timeout=30s], status line [HTTP/1.1 400 Bad Request]
build	06-May-2019 14:04:00	Warnings: [[types removal] Specifying types in put mapping requests is deprecated. To be compatible with 7.0, the mapping definition should not be nested under the type name, and the parameter include_type_name must be provided and set to false.]
build	06-May-2019 14:04:00	{"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"Mapper for [message] conflicts with existing mapping in other types:\n[mapper [message] has different [store] values]"}],"type":"illegal_argument_exception","reason":"Mapper for [message] conflicts with existing mapping in other types:\n[mapper [message] has different [store] values]"},"status":400}

See e700ae6 and https://build.spring.io/download/SPRINGDATAES-DATAES-JOB1/build_logs/SPRINGDATAES-DATAES-JOB1-2522.log.

@mp911de
Copy link
Member

mp911de commented May 6, 2019

Reverted master to git to 01cda35.

@sothawo sothawo deleted the issue/DATAES-568 branch May 6, 2019 16:40
mp911de added a commit that referenced this pull request May 6, 2019
Add package-info and nullability annotations to org.springframework.data.elasticsearch.core.mapping.
Extract method to avoid excessive nesting.

Add ticket references/convert old references to test methods. Move test models to inner classes. Use static imports for JSON Assert. Formatting.

Original pull request: #281.
@mp911de
Copy link
Member

mp911de commented May 6, 2019

Seems the test issues above are just a consequence of adding tests/test reordering. I'll retry 6.7.2 upgrade tomorrow. See DATAES-576 for further details about test failures.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants