Skip to content
This repository was archived by the owner on Jan 9, 2025. It is now read-only.

Commit a976b30

Browse files
committed
Refactor Spring Boot integration bean handling
Now it uses safe type variances instead of raw types
1 parent ec2608d commit a976b30

File tree

10 files changed

+82
-64
lines changed

10 files changed

+82
-64
lines changed

integrations/spring-boot/src/main/java/one/microstream/integrations/spring/boot/types/MultipleStorageBeanException.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,21 @@
2828

2929
public class MultipleStorageBeanException extends BeansException
3030
{
31-
public MultipleStorageBeanException(final Map<String, List<Class>> classes)
31+
public MultipleStorageBeanException(final Map<String, ? extends List<? extends Class<?>>> classes)
3232
{
3333
super(String.format("Multiple beans are annotated with @Storage and the same qualifier: %s",
3434
defineInfo(classes)));
3535
}
3636

37-
private static String defineInfo(final Map<String, List<Class>> classes)
37+
private static String defineInfo(final Map<String, ? extends List<? extends Class<?>>> classes)
3838
{
3939
return classes.entrySet()
4040
.stream()
4141
.map(entry -> String.format("%s -> %s", entry.getKey(), listClassNames(entry.getValue())))
4242
.collect(Collectors.joining(" / "));
4343
}
4444

45-
private static String listClassNames(List<Class> classes)
45+
private static String listClassNames(List<? extends Class<?>> classes)
4646
{
4747
return classes.stream()
4848
.map(Class::getName)

integrations/spring-boot/src/main/java/one/microstream/integrations/spring/boot/types/config/StorageManagerProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ private boolean hasRootDefined(final String qualifier)
171171
return false;
172172
}
173173

174-
Optional<StorageClassData> storageClassData = this.storageMetaData.get()
174+
Optional<StorageClassData<?>> storageClassData = this.storageMetaData.get()
175175
.getStorageClassData()
176176
.stream()
177177
.filter(scd -> scd.getQualifier()

integrations/spring-boot/src/main/java/one/microstream/integrations/spring/boot/types/storage/StorageBeanFactory.java

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,14 @@ public class StorageBeanFactory implements ApplicationContextAware, BeanDefiniti
5656

5757
private ApplicationContext applicationContext;
5858

59-
private final List<StorageClassData> storageClasses = new ArrayList<>();
59+
private final List<StorageClassData<?>> storageClasses = new ArrayList<>();
6060

61-
public Object createRootObject(final String qualifier)
61+
public <T> T createRootObject(final StorageClassData<T> storageClass)
6262
{
6363
LOGGER.debug("Creating Spring bean for @Storage annotated class");
6464

65+
final String qualifier = storageClass.getQualifier();
66+
6567
final StorageManager storageManager;
6668
if (StorageManagerProvider.PRIMARY_QUALIFIER.equals(qualifier))
6769
{
@@ -87,19 +89,23 @@ public Object createRootObject(final String qualifier)
8789
storageManager.setRoot(root);
8890
storageManager.storeRoot();
8991
}
92+
if (!root.getClass().equals(storageClass.getClazz()))
93+
{
94+
LOGGER.warn("Root class doesn't match bean class \"{}\"! This is likely a bug!", storageClass.getClazz());
95+
}
9096

9197
this.applicationContext
9298
.getAutowireCapableBeanFactory()
9399
.autowireBean(root);
94100

95101
this.processInitializers(storageManager, qualifier);
96102

97-
return root;
103+
//noinspection unchecked
104+
return (T) root;
98105
}
99106

100-
private Class findRootClass(final String qualifier)
107+
private Class<?> findRootClass(final String qualifier)
101108
{
102-
103109
return storageClasses.stream()
104110
.filter(scd -> scd.getQualifier()
105111
.equals(qualifier))
@@ -150,11 +156,11 @@ public void postProcessBeanDefinitionRegistry(final BeanDefinitionRegistry beanD
150156
classLoader = this.getClass().getClassLoader();
151157

152158
// Don't use generics as that will not work with the Supplier that provides the Root object further in this method
153-
final Class clazz = classLoader.loadClass(beanDefinition.getBeanClassName());
154-
final Storage storageAnnotation = (Storage) clazz.getAnnotation(Storage.class);
159+
final Class<?> clazz = classLoader.loadClass(beanDefinition.getBeanClassName());
160+
final Storage storageAnnotation = clazz.getAnnotation(Storage.class);
155161
if (storageAnnotation != null)
156162
{
157-
this.storageClasses.add(new StorageClassData(clazz));
163+
this.storageClasses.add(new StorageClassData<>(clazz));
158164

159165
// Remove the original definition
160166
beanDefinitionRegistry.removeBeanDefinition(definitionName);
@@ -167,16 +173,19 @@ public void postProcessBeanDefinitionRegistry(final BeanDefinitionRegistry beanD
167173
}
168174

169175
}
170-
final Map<String, List<Class>> storageClassByQualifier = storageClasses.stream()
171-
.collect(Collectors.groupingBy(StorageClassData::getQualifier
172-
, Collectors.mapping(StorageClassData::getClazz, Collectors.toList())));
176+
final Map<String, ? extends List<? extends Class<?>>> storageClassByQualifier = storageClasses.stream()
177+
.collect(
178+
Collectors.groupingBy(StorageClassData::getQualifier,
179+
Collectors.mapping(StorageClassData::getClazz,
180+
Collectors.toUnmodifiableList())
181+
)
182+
);
173183

174-
final Map<String, List<Class>> multipleStorageClassByQualifier =
184+
final Map<String, ? extends List<? extends Class<?>>> multipleStorageClassByQualifier =
175185
storageClassByQualifier.entrySet()
176186
.stream()
177-
.filter(entry -> entry.getValue()
178-
.size() > 1)
179-
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
187+
.filter(entry -> entry.getValue().size() > 1)
188+
.collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, Map.Entry::getValue));
180189

181190
if (multipleStorageClassByQualifier.size() > 1)
182191
{
@@ -189,7 +198,7 @@ public void postProcessBeanDefinitionRegistry(final BeanDefinitionRegistry beanD
189198

190199
// Add a definition for each class annotated with @Storage
191200
// Add a new definition based on the createRootObject 'factory method'
192-
for (final StorageClassData storageClass : this.storageClasses)
201+
for (final StorageClassData<?> storageClass : this.storageClasses)
193202
{
194203

195204
beanDefinitionRegistry
@@ -201,24 +210,24 @@ public void postProcessBeanDefinitionRegistry(final BeanDefinitionRegistry beanD
201210

202211
}
203212

204-
private static String defineBeanName(StorageClassData storageClass)
213+
private static String defineBeanName(StorageClassData<?> storageClass)
205214
{
206215

207216
// Bean name must be the qualifier name!
208217
String result = storageClass.getQualifier();
209218
if (StorageManagerProvider.PRIMARY_QUALIFIER.equals(result))
210219
{
211-
// Unless no Qualifier, than it must be the class name
220+
// Unless no Qualifier, then it must be the class name
212221
result = storageClass.getClazz()
213222
.getName();
214223
}
215224
return result;
216225
}
217226

218-
private BeanDefinition createBeanDefinition(final StorageClassData storageClass)
227+
private <T> BeanDefinition createBeanDefinition(final StorageClassData<T> storageClass)
219228
{
220229
return BeanDefinitionBuilder.genericBeanDefinition(storageClass.getClazz(),
221-
() -> createRootObject(storageClass.getQualifier()))
230+
() -> createRootObject(storageClass))
222231
//.addConstructorArgValue(storageClass.getQualifier())
223232
.getBeanDefinition();
224233
}

integrations/spring-boot/src/main/java/one/microstream/integrations/spring/boot/types/storage/StorageClassData.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@
2323
import one.microstream.integrations.spring.boot.types.config.StorageManagerProvider;
2424
import org.springframework.beans.factory.annotation.Qualifier;
2525

26-
public class StorageClassData
26+
public class StorageClassData<T>
2727
{
2828

29-
private final Class<?> clazz; // The Root class
29+
private final Class<T> clazz; // The Root class
3030

3131
private final String qualifier; // The qualifier
3232

33-
public StorageClassData(final Class<?> clazz)
33+
public StorageClassData(final Class<T> clazz)
3434
{
3535
this.clazz = clazz;
3636
this.qualifier = findQualifier(clazz);
@@ -47,7 +47,7 @@ private String findQualifier(final Class<?> clazz)
4747
return StorageManagerProvider.PRIMARY_QUALIFIER;
4848
}
4949

50-
public Class getClazz()
50+
public Class<T> getClazz()
5151
{
5252
return this.clazz;
5353
}
@@ -69,7 +69,7 @@ public boolean equals(final Object o)
6969
return false;
7070
}
7171

72-
StorageClassData that = (StorageClassData) o;
72+
StorageClassData<?> that = (StorageClassData<?>) o;
7373

7474
if (!this.clazz.equals(that.clazz))
7575
{

integrations/spring-boot/src/main/java/one/microstream/integrations/spring/boot/types/storage/StorageMetaData.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@
2828
*/
2929
public class StorageMetaData
3030
{
31-
private final List<StorageClassData> storageClassData;
31+
private final List<StorageClassData<?>> storageClassData;
3232

33-
public StorageMetaData(final List<StorageClassData> storageClassData)
33+
public StorageMetaData(final List<StorageClassData<?>> storageClassData)
3434
{
3535
this.storageClassData = storageClassData;
3636
}
3737

38-
public List<StorageClassData> getStorageClassData()
38+
public List<StorageClassData<?>> getStorageClassData()
3939
{
4040
return this.storageClassData;
4141
}

integrations/spring-boot3/src/main/java/one/microstream/integrations/spring/boot/types/MultipleStorageBeanException.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,21 @@
2828

2929
public class MultipleStorageBeanException extends BeansException
3030
{
31-
public MultipleStorageBeanException(final Map<String, List<Class>> classes)
31+
public MultipleStorageBeanException(final Map<String, ? extends List<? extends Class<?>>> classes)
3232
{
3333
super(String.format("Multiple beans are annotated with @Storage and the same qualifier: %s",
3434
defineInfo(classes)));
3535
}
3636

37-
private static String defineInfo(final Map<String, List<Class>> classes)
37+
private static String defineInfo(final Map<String, ? extends List<? extends Class<?>>> classes)
3838
{
3939
return classes.entrySet()
4040
.stream()
4141
.map(entry -> String.format("%s -> %s", entry.getKey(), listClassNames(entry.getValue())))
4242
.collect(Collectors.joining(" / "));
4343
}
4444

45-
private static String listClassNames(List<Class> classes)
45+
private static String listClassNames(List<? extends Class<?>> classes)
4646
{
4747
return classes.stream()
4848
.map(Class::getName)

integrations/spring-boot3/src/main/java/one/microstream/integrations/spring/boot/types/config/StorageManagerProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ private boolean hasRootDefined(final String qualifier)
171171
return false;
172172
}
173173

174-
Optional<StorageClassData> storageClassData = this.storageMetaData.get()
174+
Optional<StorageClassData<?>> storageClassData = this.storageMetaData.get()
175175
.getStorageClassData()
176176
.stream()
177177
.filter(scd -> scd.getQualifier()

integrations/spring-boot3/src/main/java/one/microstream/integrations/spring/boot/types/storage/StorageBeanFactory.java

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,14 @@ public class StorageBeanFactory implements ApplicationContextAware, BeanDefiniti
5656

5757
private ApplicationContext applicationContext;
5858

59-
private final List<StorageClassData> storageClasses = new ArrayList<>();
59+
private final List<StorageClassData<?>> storageClasses = new ArrayList<>();
6060

61-
public Object createRootObject(final String qualifier)
61+
public <T> T createRootObject(final StorageClassData<T> storageClass)
6262
{
6363
LOGGER.debug("Creating Spring bean for @Storage annotated class");
6464

65+
final String qualifier = storageClass.getQualifier();
66+
6567
final StorageManager storageManager;
6668
if (StorageManagerProvider.PRIMARY_QUALIFIER.equals(qualifier))
6769
{
@@ -87,19 +89,23 @@ public Object createRootObject(final String qualifier)
8789
storageManager.setRoot(root);
8890
storageManager.storeRoot();
8991
}
92+
if (!root.getClass().equals(storageClass.getClazz()))
93+
{
94+
LOGGER.warn("Root class doesn't match bean class \"{}\"! This is likely a bug!", storageClass.getClazz());
95+
}
9096

9197
this.applicationContext
9298
.getAutowireCapableBeanFactory()
9399
.autowireBean(root);
94100

95101
this.processInitializers(storageManager, qualifier);
96102

97-
return root;
103+
//noinspection unchecked
104+
return (T) root;
98105
}
99106

100-
private Class findRootClass(final String qualifier)
107+
private Class<?> findRootClass(final String qualifier)
101108
{
102-
103109
return storageClasses.stream()
104110
.filter(scd -> scd.getQualifier()
105111
.equals(qualifier))
@@ -150,11 +156,11 @@ public void postProcessBeanDefinitionRegistry(final BeanDefinitionRegistry beanD
150156
classLoader = this.getClass().getClassLoader();
151157

152158
// Don't use generics as that will not work with the Supplier that provides the Root object further in this method
153-
final Class clazz = classLoader.loadClass(beanDefinition.getBeanClassName());
154-
final Storage storageAnnotation = (Storage) clazz.getAnnotation(Storage.class);
159+
final Class<?> clazz = classLoader.loadClass(beanDefinition.getBeanClassName());
160+
final Storage storageAnnotation = clazz.getAnnotation(Storage.class);
155161
if (storageAnnotation != null)
156162
{
157-
this.storageClasses.add(new StorageClassData(clazz));
163+
this.storageClasses.add(new StorageClassData<>(clazz));
158164

159165
// Remove the original definition
160166
beanDefinitionRegistry.removeBeanDefinition(definitionName);
@@ -167,16 +173,19 @@ public void postProcessBeanDefinitionRegistry(final BeanDefinitionRegistry beanD
167173
}
168174

169175
}
170-
final Map<String, List<Class>> storageClassByQualifier = storageClasses.stream()
171-
.collect(Collectors.groupingBy(StorageClassData::getQualifier
172-
, Collectors.mapping(StorageClassData::getClazz, Collectors.toList())));
176+
final Map<String, ? extends List<? extends Class<?>>> storageClassByQualifier = storageClasses.stream()
177+
.collect(
178+
Collectors.groupingBy(StorageClassData::getQualifier,
179+
Collectors.mapping(StorageClassData::getClazz,
180+
Collectors.toUnmodifiableList())
181+
)
182+
);
173183

174-
final Map<String, List<Class>> multipleStorageClassByQualifier =
184+
final Map<String, ? extends List<? extends Class<?>>> multipleStorageClassByQualifier =
175185
storageClassByQualifier.entrySet()
176186
.stream()
177-
.filter(entry -> entry.getValue()
178-
.size() > 1)
179-
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
187+
.filter(entry -> entry.getValue().size() > 1)
188+
.collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, Map.Entry::getValue));
180189

181190
if (multipleStorageClassByQualifier.size() > 1)
182191
{
@@ -189,7 +198,7 @@ public void postProcessBeanDefinitionRegistry(final BeanDefinitionRegistry beanD
189198

190199
// Add a definition for each class annotated with @Storage
191200
// Add a new definition based on the createRootObject 'factory method'
192-
for (final StorageClassData storageClass : this.storageClasses)
201+
for (final StorageClassData<?> storageClass : this.storageClasses)
193202
{
194203

195204
beanDefinitionRegistry
@@ -201,24 +210,24 @@ public void postProcessBeanDefinitionRegistry(final BeanDefinitionRegistry beanD
201210

202211
}
203212

204-
private static String defineBeanName(StorageClassData storageClass)
213+
private static String defineBeanName(StorageClassData<?> storageClass)
205214
{
206215

207216
// Bean name must be the qualifier name!
208217
String result = storageClass.getQualifier();
209218
if (StorageManagerProvider.PRIMARY_QUALIFIER.equals(result))
210219
{
211-
// Unless no Qualifier, than it must be the class name
220+
// Unless no Qualifier, then it must be the class name
212221
result = storageClass.getClazz()
213222
.getName();
214223
}
215224
return result;
216225
}
217226

218-
private BeanDefinition createBeanDefinition(final StorageClassData storageClass)
227+
private <T> BeanDefinition createBeanDefinition(final StorageClassData<T> storageClass)
219228
{
220229
return BeanDefinitionBuilder.genericBeanDefinition(storageClass.getClazz(),
221-
() -> createRootObject(storageClass.getQualifier()))
230+
() -> createRootObject(storageClass))
222231
//.addConstructorArgValue(storageClass.getQualifier())
223232
.getBeanDefinition();
224233
}

0 commit comments

Comments
 (0)