I have a configuration entity defined as follows:
@Entity
class ConfigEntity() : PanacheEntity() {
companion object : PanacheCompanion<ConfigEntity> {
fun findByKey(key: String): ConfigEntity? {
return find("stringKey", key).firstResult()
}
}
lateinit var stringKey: String
lateinit var stringValue: String
}
I would like to be able to let users dynamically set constraints within OptaPlanner, and I have a ConstraintsProvider
defined like:
class TimeTableConstraintProvider : ConstraintProvider {
override fun defineConstraints(constraintFactory: ConstraintFactory): Array<Constraint> {
val constraints = mutableListOf<Constraint>()
if (ConfigEntity.findByKey("room")?.stringValue == "ENABLED") constraints.add(roomConflict(constraintFactory))
if (ConfigEntity.findByKey("teacher")?.stringValue == "ENABLED") constraints.add(teacherConflict(constraintFactory))
return constraints.toTypedArray()
}
//... definitions of roomConflict and teacherConflict below
}
Receiving this error when trying to access entities using Hibernate Panache ORM
(Quarkus Main Thread) Failed to start application (with profile dev): javax.enterprise.context.ContextNotActiveException: Cannot use the EntityManager/Session because neither a transaction nor a CDI request context is active. Consider adding @Transactional to your method to automatically activate a transaction, or @ActivateRequestContext if you have valid reasons not to use transactions.
I have tried the recommended solution of adding @Transactional around the defineConstriants
function, but it hasn't had any effect.
Dynamically turning constraints off/on like this is error-prone, because ConstraintProvider.defineConstraints()
can be called once at bootstrap and cached forever, or can be called in parallel all the time. Giving it a dynamic output like this will cause race conditions, sooner or later.
To dynamically turn constraints off/on, use penalizeConfigurable()
and a @ConstraintConfiguration
with @ConstraintWeight
s of zero/non-zero. Those weights are part of the dataset (the @PlanningSolution
), and therefore one dataset might activate constraint A and another dataset might not - and still they can solve in parallel. This approach is thread-safe and doesn't need a CDI request context. See OptaPlanner docs.
That being said, there's an open RFE to allow defaulting constraints weights on application.properties
with no need for a bunch of boilerplate code.