-
Notifications
You must be signed in to change notification settings - Fork 0
Ab 237 type ids #4
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
Merged
Merged
Changes from 6 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
1a801a1
wip
SirCotare b9cb44c
add full support for custom types
SirCotare d243cef
replace old vulnerable lib with new version
SirCotare cb40ddf
add swagger customizers
SirCotare a8bb5cf
move swagger modifications to a dedicated annotation and rename the c…
SirCotare 215b271
replace deprecated classscanner
SirCotare f50e118
add testing and fix bugs
SirCotare 6eb2762
move things around and some minor improvements
SirCotare 84702e8
remove comment
SirCotare File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
.../java/it/aboutbits/springboot/toolbox/boot/persistence/AbstractCustomTypeContributor.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| package it.aboutbits.springboot.toolbox.boot.persistence; | ||
|
|
||
| import it.aboutbits.springboot.toolbox.reflection.util.ClassScannerUtil; | ||
| import lombok.SneakyThrows; | ||
| import org.hibernate.boot.model.TypeContributions; | ||
| import org.hibernate.boot.model.TypeContributor; | ||
| import org.hibernate.service.ServiceRegistry; | ||
| import org.hibernate.type.descriptor.java.JavaType; | ||
|
|
||
| import java.lang.reflect.InvocationTargetException; | ||
| import java.util.Set; | ||
|
|
||
| public abstract class AbstractCustomTypeContributor implements TypeContributor { | ||
| private final ClassScannerUtil.ClassScanner classScanner; | ||
|
|
||
| protected AbstractCustomTypeContributor(String... packageNames) { | ||
| classScanner = ClassScannerUtil.getScannerForPackages(packageNames); | ||
| } | ||
|
|
||
| @SneakyThrows({InstantiationException.class, IllegalAccessException.class, InvocationTargetException.class}) | ||
| @Override | ||
| public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { | ||
| var types = findAllRelevantTypes(); | ||
|
|
||
| for (var type : types) { | ||
| typeContributions.contributeJavaType( | ||
| (JavaType<?>) type.getConstructors()[0].newInstance() | ||
| ); | ||
| } | ||
|
|
||
| classScanner.close(); | ||
| } | ||
|
|
||
| @SuppressWarnings("rawtypes") | ||
| private Set<Class<? extends AutoRegisteredJavaType>> findAllRelevantTypes() { | ||
| return classScanner.getSubTypesOf(AutoRegisteredJavaType.class); | ||
| } | ||
| } | ||
6 changes: 6 additions & 0 deletions
6
src/main/java/it/aboutbits/springboot/toolbox/boot/persistence/AutoRegisteredJavaType.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package it.aboutbits.springboot.toolbox.boot.persistence; | ||
|
|
||
| import org.hibernate.type.descriptor.java.JavaType; | ||
|
|
||
| public interface AutoRegisteredJavaType<T> extends JavaType<T> { | ||
| } |
7 changes: 7 additions & 0 deletions
7
src/main/java/it/aboutbits/springboot/toolbox/boot/persistence/CustomTypeContributor.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package it.aboutbits.springboot.toolbox.boot.persistence; | ||
|
|
||
| public final class CustomTypeContributor extends AbstractCustomTypeContributor { | ||
| public CustomTypeContributor() { | ||
| super("it.aboutbits.springboot.toolbox"); | ||
|
mmalfertheiner marked this conversation as resolved.
|
||
| } | ||
| } | ||
78 changes: 78 additions & 0 deletions
78
src/main/java/it/aboutbits/springboot/toolbox/boot/type/CustomTypeConfiguration.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| package it.aboutbits.springboot.toolbox.boot.type; | ||
|
|
||
| import it.aboutbits.springboot.toolbox.reflection.util.ClassScannerUtil; | ||
| import it.aboutbits.springboot.toolbox.type.CustomType; | ||
| import it.aboutbits.springboot.toolbox.type.jackson.CustomTypeDeserializer; | ||
| import it.aboutbits.springboot.toolbox.type.jackson.CustomTypeSerializer; | ||
| import it.aboutbits.springboot.toolbox.type.mvc.CustomTypePropertyEditor; | ||
| import jakarta.annotation.PostConstruct; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
| import org.springframework.web.bind.WebDataBinder; | ||
| import org.springframework.web.bind.annotation.ControllerAdvice; | ||
| import org.springframework.web.bind.annotation.InitBinder; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.Set; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| @Slf4j | ||
| @Configuration | ||
| public class CustomTypeConfiguration { | ||
| public static final String LIBRARY_BASE_PACKAGE_NAME = "it.aboutbits.springboot.toolbox"; | ||
|
|
||
| private String[] packageNamesToScan; | ||
| private ClassScannerUtil.ClassScanner classScanner; | ||
|
|
||
| public void setAdditionalTypePackages(String[] additionalTypePackages) { | ||
| var tmp = new ArrayList<String>(); | ||
| tmp.add(LIBRARY_BASE_PACKAGE_NAME); | ||
| tmp.addAll(Arrays.asList(additionalTypePackages)); | ||
|
|
||
| this.packageNamesToScan = tmp.toArray(new String[0]); | ||
|
|
||
| classScanner = ClassScannerUtil.getScannerForPackages(packageNamesToScan); | ||
| } | ||
|
|
||
| @PostConstruct | ||
| public void init() { | ||
| log.info("CustomTypeConfiguration enabled. Scanning: {}", Arrays.toString(packageNamesToScan)); | ||
| } | ||
|
SirCotare marked this conversation as resolved.
Outdated
|
||
|
|
||
| @ControllerAdvice | ||
| public class CustomTypePropertyBinder { | ||
| @InitBinder | ||
| public void initBinder(WebDataBinder binder) { | ||
| var types = findAllCustomTypeRecords(); | ||
| for (var clazz : types) { | ||
| binder.registerCustomEditor(clazz, new CustomTypePropertyEditor<>(clazz)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Bean | ||
| public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { | ||
| var types = findAllCustomTypeRecords(); | ||
|
|
||
| var deserializers = types.stream() | ||
| .map(CustomTypeDeserializer::new) | ||
| .toList() | ||
| .toArray(new CustomTypeDeserializer[types.size()]); | ||
|
|
||
| classScanner.close(); | ||
|
|
||
| return builder -> builder | ||
| .serializers(new CustomTypeSerializer()) | ||
| .deserializers(deserializers); | ||
| } | ||
|
|
||
| @SuppressWarnings("rawtypes") | ||
| private Set<Class<? extends CustomType>> findAllCustomTypeRecords() { | ||
| return classScanner.getSubTypesOf(CustomType.class).stream() | ||
| .filter(Record.class::isAssignableFrom) | ||
| .collect(Collectors.toSet()); | ||
| } | ||
| } | ||
28 changes: 28 additions & 0 deletions
28
...main/java/it/aboutbits/springboot/toolbox/boot/type/CustomTypeConfigurationRegistrar.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package it.aboutbits.springboot.toolbox.boot.type; | ||
|
|
||
| import org.springframework.beans.factory.support.BeanDefinitionBuilder; | ||
| import org.springframework.beans.factory.support.BeanDefinitionRegistry; | ||
| import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; | ||
| import org.springframework.core.annotation.AnnotationAttributes; | ||
| import org.springframework.core.type.AnnotationMetadata; | ||
|
|
||
| import java.util.Objects; | ||
|
|
||
| public class CustomTypeConfigurationRegistrar implements ImportBeanDefinitionRegistrar { | ||
|
|
||
| @Override | ||
| public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { | ||
|
SirCotare marked this conversation as resolved.
|
||
| var attributes = new AnnotationAttributes( | ||
| Objects.requireNonNull( | ||
| metadata.getAnnotationAttributes( | ||
| RegisterCustomTypes.class.getName() | ||
| ) | ||
| ) | ||
| ); | ||
| var value = attributes.getStringArray("additionalTypePackages"); | ||
|
|
||
| var builder = BeanDefinitionBuilder.genericBeanDefinition(CustomTypeConfiguration.class); | ||
| builder.addPropertyValue("additionalTypePackages", value); | ||
| registry.registerBeanDefinition("CustomTypeConfiguration", builder.getBeanDefinition()); | ||
| } | ||
| } | ||
15 changes: 15 additions & 0 deletions
15
src/main/java/it/aboutbits/springboot/toolbox/boot/type/RegisterCustomTypes.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package it.aboutbits.springboot.toolbox.boot.type; | ||
|
|
||
| import org.springframework.context.annotation.Import; | ||
|
|
||
| import java.lang.annotation.ElementType; | ||
| import java.lang.annotation.Retention; | ||
| import java.lang.annotation.RetentionPolicy; | ||
| import java.lang.annotation.Target; | ||
|
|
||
| @Target({ElementType.TYPE}) | ||
| @Retention(RetentionPolicy.RUNTIME) | ||
| @Import(CustomTypeConfigurationRegistrar.class) | ||
| public @interface RegisterCustomTypes { | ||
|
SirCotare marked this conversation as resolved.
Outdated
|
||
| String[] additionalTypePackages() default ""; | ||
| } | ||
57 changes: 57 additions & 0 deletions
57
...main/java/it/aboutbits/springboot/toolbox/boot/type/swagger/CustomTypeModelConverter.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| package it.aboutbits.springboot.toolbox.boot.type.swagger; | ||
|
|
||
| import io.swagger.v3.core.converter.AnnotatedType; | ||
| import io.swagger.v3.core.converter.ModelConverter; | ||
| import io.swagger.v3.core.converter.ModelConverterContext; | ||
| import io.swagger.v3.oas.models.media.Schema; | ||
| import it.aboutbits.springboot.toolbox.persistence.identity.EntityId; | ||
| import it.aboutbits.springboot.toolbox.reflection.util.RecordReflectionUtil; | ||
| import it.aboutbits.springboot.toolbox.type.CustomType; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| import java.math.BigDecimal; | ||
| import java.util.Iterator; | ||
|
|
||
| @Component | ||
| public class CustomTypeModelConverter implements ModelConverter { | ||
|
|
||
| @Override | ||
| public Schema<?> resolve( | ||
| AnnotatedType annotatedType, | ||
| ModelConverterContext context, | ||
| Iterator<ModelConverter> chain | ||
| ) { | ||
|
|
||
| var type = annotatedType.getType(); | ||
|
|
||
| if (type instanceof Class<?> clazz && CustomType.class.isAssignableFrom(clazz) && !EntityId.class.isAssignableFrom( | ||
| clazz)) { | ||
| var constructor = RecordReflectionUtil.getCanonicalConstructor(clazz); | ||
| var wrappedType = constructor.getParameters()[0].getType(); | ||
|
|
||
| if (Short.class.isAssignableFrom(wrappedType)) { | ||
| return context.resolve(new AnnotatedType(Short.TYPE)); | ||
| } | ||
| if (Integer.class.isAssignableFrom(wrappedType)) { | ||
| return context.resolve(new AnnotatedType(Integer.TYPE)); | ||
| } | ||
| if (Long.class.isAssignableFrom(wrappedType)) { | ||
| return context.resolve(new AnnotatedType(Long.TYPE)); | ||
| } | ||
| if (Float.class.isAssignableFrom(wrappedType)) { | ||
| return context.resolve(new AnnotatedType(Float.TYPE)); | ||
| } | ||
| if (Double.class.isAssignableFrom(wrappedType)) { | ||
| return context.resolve(new AnnotatedType(Double.TYPE)); | ||
| } | ||
| if (BigDecimal.class.isAssignableFrom(wrappedType)) { | ||
| return context.resolve(new AnnotatedType(Double.TYPE)); | ||
| } | ||
| if (String.class.isAssignableFrom(wrappedType)) { | ||
| return context.resolve(new AnnotatedType(String.class)); | ||
| } | ||
| } | ||
|
|
||
| return chain.hasNext() ? chain.next().resolve(annotatedType, context, chain) : null; | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.