in optaplanner-quarkus-integration/optaplanner-quarkus/deployment/src/main/java/org/optaplanner/quarkus/deployment/OptaPlannerProcessor.java [229:331]
SolverConfigBuildItem recordAndRegisterBeans(OptaPlannerRecorder recorder, RecorderContext recorderContext,
DetermineIfNativeBuildItem determineIfNative, CombinedIndexBuildItem combinedIndex,
BuildProducer<ReflectiveHierarchyBuildItem> reflectiveHierarchyClass,
BuildProducer<SyntheticBeanBuildItem> syntheticBeanBuildItemBuildProducer,
BuildProducer<AdditionalBeanBuildItem> additionalBeans,
BuildProducer<UnremovableBeanBuildItem> unremovableBeans,
BuildProducer<GeneratedBeanBuildItem> generatedBeans,
BuildProducer<GeneratedClassBuildItem> generatedClasses,
BuildProducer<BytecodeTransformerBuildItem> transformers) {
IndexView indexView = combinedIndex.getIndex();
// Only skip this extension if everything is missing. Otherwise, if some parts are missing, fail fast later.
if (indexView.getAnnotations(DotNames.PLANNING_SOLUTION).isEmpty()
&& indexView.getAnnotations(DotNames.PLANNING_ENTITY).isEmpty()) {
log.warn("Skipping OptaPlanner extension because there are no @" + PlanningSolution.class.getSimpleName()
+ " or @" + PlanningEntity.class.getSimpleName() + " annotated classes."
+ "\nIf your domain classes are located in a dependency of this project, maybe try generating"
+ " the Jandex index by using the jandex-maven-plugin in that dependency, or by adding"
+ "application.properties entries (quarkus.index-dependency.<name>.group-id"
+ " and quarkus.index-dependency.<name>.artifact-id).");
additionalBeans.produce(new AdditionalBeanBuildItem(UnavailableOptaPlannerBeanProvider.class));
return new SolverConfigBuildItem(null);
}
// Quarkus extensions must always use getContextClassLoader()
// Internally, OptaPlanner defaults the ClassLoader to getContextClassLoader() too
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
SolverConfig solverConfig;
if (optaPlannerBuildTimeConfig.solverConfigXml.isPresent()) {
String solverConfigXML = optaPlannerBuildTimeConfig.solverConfigXml.get();
if (classLoader.getResource(solverConfigXML) == null) {
throw new ConfigurationException("Invalid quarkus.optaplanner.solverConfigXML property ("
+ solverConfigXML + "): that classpath resource does not exist.");
}
solverConfig = SolverConfig.createFromXmlResource(solverConfigXML);
} else if (classLoader.getResource(OptaPlannerBuildTimeConfig.DEFAULT_SOLVER_CONFIG_URL) != null) {
solverConfig = SolverConfig.createFromXmlResource(
OptaPlannerBuildTimeConfig.DEFAULT_SOLVER_CONFIG_URL);
} else {
solverConfig = new SolverConfig();
}
applySolverProperties(indexView, solverConfig);
assertNoMemberAnnotationWithoutClassAnnotation(indexView);
assertDrlDisabledInNative(solverConfig, determineIfNative);
if (solverConfig.getSolutionClass() != null) {
// Need to register even when using GIZMO so annotations are preserved
Type jandexType = Type.create(DotName.createSimple(solverConfig.getSolutionClass().getName()), Type.Kind.CLASS);
reflectiveHierarchyClass.produce(new ReflectiveHierarchyBuildItem.Builder()
.type(jandexType)
// Ignore only the packages from optaplanner-core
// (Can cause a hard to diagnose issue when creating a test/example
// in the package "org.optaplanner").
.ignoreTypePredicate(
dotName -> ReflectiveHierarchyBuildItem.DefaultIgnoreTypePredicate.INSTANCE.test(dotName)
|| dotName.toString().startsWith("org.optaplanner.api")
|| dotName.toString().startsWith("org.optaplanner.config")
|| dotName.toString().startsWith("org.optaplanner.impl"))
.build());
}
if (determineIfNative.isNative()) {
// DroolsAlphaNetworkCompilationEnabled is a three-state boolean (null, true, false); if it not
// null, ScoreDirectorFactoryFactory will throw an error if Drools isn't use (i.e. BAVET or Easy/Incremental)
if (solverConfig.getScoreDirectorFactoryConfig().getConstraintProviderClass() != null && solverConfig
.getScoreDirectorFactoryConfig().getConstraintStreamImplType() != ConstraintStreamImplType.BAVET) {
disableANC(solverConfig);
} else if (solverConfig.getScoreDirectorFactoryConfig().getScoreDrlList() != null
|| solverConfig.getScoreDirectorFactoryConfig().getScoreDrlFileList() == null) {
disableANC(solverConfig);
}
}
Set<Class<?>> reflectiveClassSet = new LinkedHashSet<>();
registerClassesFromAnnotations(indexView, reflectiveClassSet);
registerCustomClassesFromSolverConfig(solverConfig, reflectiveClassSet);
generateConstraintVerifier(solverConfig, syntheticBeanBuildItemBuildProducer);
GeneratedGizmoClasses generatedGizmoClasses = generateDomainAccessors(solverConfig, indexView, generatedBeans,
generatedClasses, transformers, reflectiveClassSet);
SolverManagerConfig solverManagerConfig = new SolverManagerConfig();
syntheticBeanBuildItemBuildProducer.produce(SyntheticBeanBuildItem.configure(SolverConfig.class)
.scope(Singleton.class)
.defaultBean()
.supplier(recorder.solverConfigSupplier(solverConfig,
GizmoMemberAccessorEntityEnhancer.getGeneratedGizmoMemberAccessorMap(recorderContext,
generatedGizmoClasses.generatedGizmoMemberAccessorClassSet),
GizmoMemberAccessorEntityEnhancer.getGeneratedSolutionClonerMap(recorderContext,
generatedGizmoClasses.generatedGizmoSolutionClonerClassSet)))
.done());
syntheticBeanBuildItemBuildProducer.produce(SyntheticBeanBuildItem.configure(SolverManagerConfig.class)
.scope(Singleton.class)
.defaultBean()
.supplier(recorder.solverManagerConfig(solverManagerConfig)).done());
additionalBeans.produce(new AdditionalBeanBuildItem(DefaultOptaPlannerBeanProvider.class));
unremovableBeans.produce(UnremovableBeanBuildItem.beanTypes(OptaPlannerRuntimeConfig.class));
return new SolverConfigBuildItem(solverConfig);
}