Skip to content

Commit 6512fc0

Browse files
authored
To support jdk 16, add converters and module-info. (#1167)
To support jdk 16, add converters and module-info. Closes #1057.
1 parent 351370b commit 6512fc0

File tree

10 files changed

+335
-18
lines changed

10 files changed

+335
-18
lines changed

pom.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,17 @@
265265
</execution>
266266
</executions>
267267
</plugin>
268+
<plugin>
269+
<groupId>org.apache.maven.plugins</groupId>
270+
<artifactId>maven-jar-plugin</artifactId>
271+
<configuration>
272+
<archive>
273+
<manifestEntries>
274+
<Automatic-Module-Name>${java-module-name}</Automatic-Module-Name>
275+
</manifestEntries>
276+
</archive>
277+
</configuration>
278+
</plugin>
268279
<plugin>
269280
<groupId>org.apache.maven.plugins</groupId>
270281
<artifactId>maven-assembly-plugin</artifactId>

src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplateSupport.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public long getCas(final Object entity) {
133133

134134
long cas = 0;
135135
if (versionProperty != null) {
136-
Object casObject = (Number) accessor.getProperty(versionProperty);
136+
Object casObject = accessor.getProperty(versionProperty);
137137
if (casObject instanceof Number) {
138138
cas = ((Number) casObject).longValue();
139139
}

src/main/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplateSupport.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public Long getCas(final Object entity) {
140140

141141
long cas = 0;
142142
if (versionProperty != null) {
143-
Object casObject = (Number) accessor.getProperty(versionProperty);
143+
Object casObject = accessor.getProperty(versionProperty);
144144
if (casObject instanceof Number) {
145145
cas = ((Number) casObject).longValue();
146146
}

src/main/java/org/springframework/data/couchbase/core/convert/CouchbaseCustomConversions.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2020 the original author or authors.
2+
* Copyright 2017-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -50,6 +50,7 @@ public class CouchbaseCustomConversions extends org.springframework.data.convert
5050

5151
converters.addAll(DateConverters.getConvertersToRegister());
5252
converters.addAll(CouchbaseJsr310Converters.getConvertersToRegister());
53+
converters.addAll(OtherConverters.getConvertersToRegister());
5354

5455
STORE_CONVERTERS = Collections.unmodifiableList(converters);
5556
STORE_CONVERSIONS = StoreConversions.of(SimpleTypeHolder.DEFAULT, STORE_CONVERTERS);

src/main/java/org/springframework/data/couchbase/core/convert/MappingCouchbaseConverter.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors
2+
* Copyright 2012-2021 the original author or authors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
3535
import org.springframework.core.convert.ConversionService;
3636
import org.springframework.core.convert.support.DefaultConversionService;
3737
import org.springframework.data.annotation.Transient;
38+
import org.springframework.data.convert.CustomConversions;
3839
import org.springframework.data.convert.EntityInstantiator;
3940
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
4041
import org.springframework.data.couchbase.core.mapping.CouchbaseList;
@@ -117,11 +118,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter implem
117118
private @Nullable EntityCallbacks entityCallbacks;
118119

119120
public MappingCouchbaseConverter() {
120-
super(new DefaultConversionService());
121-
122-
this.typeMapper = new DefaultCouchbaseTypeMapper(TYPEKEY_DEFAULT);
123-
this.mappingContext = new CouchbaseMappingContext();
124-
this.spELContext = new SpELContext(CouchbaseDocumentPropertyAccessor.INSTANCE);
121+
this(new CouchbaseMappingContext(), null);
125122
}
126123

127124
/**
@@ -131,7 +128,7 @@ public MappingCouchbaseConverter() {
131128
*/
132129
public MappingCouchbaseConverter(
133130
final MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> mappingContext) {
134-
this(mappingContext, TYPEKEY_DEFAULT);
131+
this(mappingContext, null);
135132
}
136133

137134
/**
@@ -145,8 +142,14 @@ public MappingCouchbaseConverter(
145142
final MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> mappingContext,
146143
final String typeKey) {
147144
super(new DefaultConversionService());
148-
149145
this.mappingContext = mappingContext;
146+
// this is how the MappingCouchbaseConverter gets the custom conversions.
147+
// the conversions Service gets them in afterPropertiesSet()
148+
CustomConversions customConversions = new CouchbaseCustomConversions(Collections.emptyList());
149+
this.setCustomConversions(customConversions);
150+
// if the mappingContext does not have the SimpleTypes, it will not know that they have converters, then it will
151+
// try to access the fields of the type and (maybe) fail with InaccessibleObjectException
152+
((CouchbaseMappingContext) mappingContext).setSimpleTypeHolder(customConversions.getSimpleTypeHolder());
150153
typeMapper = new DefaultCouchbaseTypeMapper(typeKey != null ? typeKey : TYPEKEY_DEFAULT);
151154
spELContext = new SpELContext(CouchbaseDocumentPropertyAccessor.INSTANCE);
152155
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright 2021 the original author or authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.data.couchbase.core.convert;
18+
19+
import java.math.BigInteger;
20+
import java.util.ArrayList;
21+
import java.util.Collection;
22+
import java.util.List;
23+
import java.util.UUID;
24+
25+
import org.springframework.core.convert.converter.Converter;
26+
import org.springframework.data.convert.ReadingConverter;
27+
import org.springframework.data.convert.WritingConverter;
28+
29+
/**
30+
* Out of the box conversions for java dates and calendars.
31+
*
32+
* @author Michael Reiche
33+
*/
34+
public final class OtherConverters {
35+
36+
private OtherConverters() {}
37+
38+
/**
39+
* Returns all converters by this class that can be registered.
40+
*
41+
* @return the list of converters to register.
42+
*/
43+
public static Collection<Converter<?, ?>> getConvertersToRegister() {
44+
List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
45+
46+
converters.add(UuidToString.INSTANCE);
47+
converters.add(StringToUuid.INSTANCE);
48+
converters.add(BigIntegerToString.INSTANCE);
49+
converters.add(StringToBigInteger.INSTANCE);
50+
51+
return converters;
52+
}
53+
54+
@WritingConverter
55+
public enum UuidToString implements Converter<UUID, String> {
56+
INSTANCE;
57+
58+
@Override
59+
public String convert(UUID source) {
60+
return source == null ? null : source.toString();
61+
}
62+
}
63+
64+
@ReadingConverter
65+
public enum StringToUuid implements Converter<String, UUID> {
66+
INSTANCE;
67+
68+
@Override
69+
public UUID convert(String source) {
70+
return source == null ? null : UUID.fromString(source);
71+
}
72+
}
73+
74+
@WritingConverter
75+
public enum BigIntegerToString implements Converter<BigInteger, String> {
76+
INSTANCE;
77+
78+
@Override
79+
public String convert(BigInteger source) {
80+
return source == null ? null : source.toString();
81+
}
82+
}
83+
84+
@ReadingConverter
85+
public enum StringToBigInteger implements Converter<String, BigInteger> {
86+
INSTANCE;
87+
88+
@Override
89+
public BigInteger convert(String source) {
90+
return source == null ? null : new BigInteger(source);
91+
}
92+
}
93+
}

src/main/java/org/springframework/data/couchbase/core/mapping/CouchbaseMappingContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public void setAutoIndexCreation(boolean autoCreateIndexes) {
131131
/**
132132
* override method from AbstractMappingContext as that method will not publishEvent() if it finds the entity has
133133
* already been cached
134-
*
134+
*
135135
* @param typeInformation - entity type
136136
*/
137137
@Override
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2014-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.couchbase.repository.cdi;
17+
18+
import java.lang.annotation.Annotation;
19+
import java.util.Optional;
20+
import java.util.Set;
21+
22+
import javax.enterprise.context.spi.CreationalContext;
23+
import javax.enterprise.inject.spi.Bean;
24+
import javax.enterprise.inject.spi.BeanManager;
25+
26+
import org.springframework.data.couchbase.core.CouchbaseOperations;
27+
import org.springframework.data.couchbase.repository.config.RepositoryOperationsMapping;
28+
import org.springframework.data.couchbase.repository.support.CouchbaseRepositoryFactory;
29+
import org.springframework.data.repository.cdi.CdiRepositoryBean;
30+
import org.springframework.data.repository.config.CustomRepositoryImplementationDetector;
31+
import org.springframework.util.Assert;
32+
33+
/**
34+
* A bean which represents a Couchbase repository.
35+
*
36+
* @author Mark Paluch
37+
*/
38+
public class CouchbaseRepositoryBean<T> extends CdiRepositoryBean<T> {
39+
40+
private final Bean<CouchbaseOperations> couchbaseOperationsBean;
41+
42+
/**
43+
* Creates a new {@link CouchbaseRepositoryBean}.
44+
*
45+
* @param operations must not be {@literal null}.
46+
* @param qualifiers must not be {@literal null}.
47+
* @param repositoryType must not be {@literal null}.
48+
* @param beanManager must not be {@literal null}.
49+
* @param detector detector for the custom {@link org.springframework.data.repository.Repository} implementations
50+
* {@link org.springframework.data.repository.config.CustomRepositoryImplementationDetector}, can be
51+
* {@literal null}.
52+
*/
53+
public CouchbaseRepositoryBean(Bean<CouchbaseOperations> operations, Set<Annotation> qualifiers,
54+
Class<T> repositoryType, BeanManager beanManager, CustomRepositoryImplementationDetector detector) {
55+
super(qualifiers, repositoryType, beanManager, Optional.of(detector));
56+
57+
Assert.notNull(operations, "Cannot create repository with 'null' for CouchbaseOperations.");
58+
this.couchbaseOperationsBean = operations;
59+
}
60+
61+
/*
62+
* (non-Javadoc)
63+
* @see org.springframework.data.repository.cdi.CdiRepositoryBean#create(javax.enterprise.context.spi.CreationalContext, java.lang.Class)
64+
*/
65+
@Override
66+
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType) {
67+
68+
CouchbaseOperations couchbaseOperations = getDependencyInstance(couchbaseOperationsBean, CouchbaseOperations.class);
69+
RepositoryOperationsMapping couchbaseOperationsMapping = new RepositoryOperationsMapping(couchbaseOperations);
70+
71+
return create(() -> new CouchbaseRepositoryFactory(couchbaseOperationsMapping), repositoryType);
72+
}
73+
74+
@Override
75+
public Class<? extends Annotation> getScope() {
76+
return couchbaseOperationsBean.getScope();
77+
}
78+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright 2014-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.data.couchbase.repository.cdi;
18+
19+
import java.lang.annotation.Annotation;
20+
import java.lang.reflect.Type;
21+
import java.util.HashMap;
22+
import java.util.Map;
23+
import java.util.Set;
24+
25+
import javax.enterprise.event.Observes;
26+
import javax.enterprise.inject.UnsatisfiedResolutionException;
27+
import javax.enterprise.inject.spi.AfterBeanDiscovery;
28+
import javax.enterprise.inject.spi.Bean;
29+
import javax.enterprise.inject.spi.BeanManager;
30+
import javax.enterprise.inject.spi.ProcessBean;
31+
32+
import org.springframework.data.couchbase.core.CouchbaseOperations;
33+
import org.springframework.data.repository.cdi.CdiRepositoryBean;
34+
import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
35+
36+
/**
37+
* A portable CDI extension which registers beans for Spring Data Couchbase repositories.
38+
*
39+
* @author Mark Paluch
40+
*/
41+
public class CouchbaseRepositoryExtension extends CdiRepositoryExtensionSupport {
42+
43+
private final Map<Set<Annotation>, Bean<CouchbaseOperations>> couchbaseOperationsMap = new HashMap<Set<Annotation>, Bean<CouchbaseOperations>>();
44+
45+
/**
46+
* Implementation of a an observer which checks for CouchbaseOperations beans and stores them in
47+
* {@link #couchbaseOperationsMap} for later association with corresponding repository beans.
48+
*
49+
* @param <T> The type.
50+
* @param processBean The annotated type as defined by CDI.
51+
*/
52+
@SuppressWarnings("unchecked")
53+
<T> void processBean(@Observes ProcessBean<T> processBean) {
54+
Bean<T> bean = processBean.getBean();
55+
for (Type type : bean.getTypes()) {
56+
if (type instanceof Class<?> && CouchbaseOperations.class.isAssignableFrom((Class<?>) type)) {
57+
couchbaseOperationsMap.put(bean.getQualifiers(), ((Bean<CouchbaseOperations>) bean));
58+
}
59+
}
60+
}
61+
62+
/**
63+
* Implementation of a an observer which registers beans to the CDI container for the detected Spring Data
64+
* repositories.
65+
* <p>
66+
* The repository beans are associated to the CouchbaseOperations using their qualifiers.
67+
*
68+
* @param beanManager The BeanManager instance.
69+
*/
70+
void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) {
71+
for (Map.Entry<Class<?>, Set<Annotation>> entry : getRepositoryTypes()) {
72+
73+
Class<?> repositoryType = entry.getKey();
74+
Set<Annotation> qualifiers = entry.getValue();
75+
76+
CdiRepositoryBean<?> repositoryBean = createRepositoryBean(repositoryType, qualifiers, beanManager);
77+
afterBeanDiscovery.addBean(repositoryBean);
78+
registerBean(repositoryBean);
79+
}
80+
}
81+
82+
/**
83+
* Creates a {@link Bean}.
84+
*
85+
* @param <T> The type of the repository.
86+
* @param repositoryType The class representing the repository.
87+
* @param beanManager The BeanManager instance.
88+
* @return The bean.
89+
*/
90+
private <T> CdiRepositoryBean<T> createRepositoryBean(Class<T> repositoryType, Set<Annotation> qualifiers,
91+
BeanManager beanManager) {
92+
93+
Bean<CouchbaseOperations> couchbaseOperationsBean = this.couchbaseOperationsMap.get(qualifiers);
94+
95+
if (couchbaseOperationsBean == null) {
96+
throw new UnsatisfiedResolutionException(String.format("Unable to resolve a bean for '%s' with qualifiers %s.",
97+
CouchbaseOperations.class.getName(), qualifiers));
98+
}
99+
100+
return new CouchbaseRepositoryBean<T>(couchbaseOperationsBean, qualifiers, repositoryType, beanManager,
101+
getCustomImplementationDetector());
102+
}
103+
}

0 commit comments

Comments
 (0)