Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d8f3193

Browse files
HV-2004 Create observer to track basic lifecycle factory events
Signed-off-by: marko-bekhta <marko.prykladna@gmail.com>
1 parent 13233a8 commit d8f3193

File tree

8 files changed

+247
-9
lines changed

8 files changed

+247
-9
lines changed

‎engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.hibernate.validator.cfg.ConstraintMapping;
2424
import org.hibernate.validator.constraints.ParameterScriptAssert;
2525
import org.hibernate.validator.constraints.ScriptAssert;
26+
import org.hibernate.validator.constraintvalidation.HibernateValidatorFactoryObserver;
2627
import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel;
2728
import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer;
2829
import org.hibernate.validator.spi.messageinterpolation.LocaleResolver;
@@ -40,7 +41,6 @@
4041
* {@link PredefinedScopeHibernateValidatorConfiguration}.
4142
*
4243
* @param <S> The actual type of the configuration.
43-
*
4444
* @author Emmanuel Bernard
4545
* @author Gunnar Morling
4646
* @author Kevin Pollet &lt;kevin.pollet@serli.com&gt; (C) 2011 SERLI
@@ -179,6 +179,15 @@ public interface BaseHibernateValidatorConfiguration<S extends BaseHibernateVali
179179
@Incubating
180180
String FAIL_FAST_ON_PROPERTY_VIOLATION = "hibernate.validator.fail_fast_on_property_violation";
181181

182+
/**
183+
* Property for configuring the validator factory observers.
184+
* A comma separated list of fully qualified names of classes implementing {@link HibernateValidatorFactoryObserver} is expected as a value.
185+
*
186+
* @since 9.1
187+
*/
188+
@Incubating
189+
String HIBERNATE_VALIDATOR_FACTORY_OBSERVER = "hibernate.validator.factory_observer";
190+
182191
/**
183192
* <p>
184193
* Returns the {@link ResourceBundleLocator} used by the
@@ -522,4 +531,15 @@ default S locales(Locale... locales) {
522531
*/
523532
@Incubating
524533
S processedBeansTrackingVoter(ProcessedBeansTrackingVoter processedBeanTrackingVoter);
534+
535+
/**
536+
* Allows adding validator factory observers tracking basic lifecycle factory events.
537+
*
538+
* @param observer An observer to register.
539+
* @return {@code this} following the chaining method pattern
540+
*
541+
* @since 9.1
542+
*/
543+
@Incubating
544+
S addHibernateValidatorFactoryObserver(HibernateValidatorFactoryObserver observer);
525545
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.validator.constraintvalidation;
6+
7+
import org.hibernate.validator.HibernateValidatorFactory;
8+
import org.hibernate.validator.Incubating;
9+
10+
/**
11+
* Allows observing the basic validator factory lifecycle events.
12+
* <p>
13+
* Observers are required to handle exceptions internally and must <b>not</b> propagate them.
14+
*
15+
* @see org.hibernate.validator.HibernateValidatorConfiguration#addHibernateValidatorFactoryObserver(HibernateValidatorFactoryObserver)
16+
* @since 9.1.0
17+
*/
18+
@Incubating
19+
public interface HibernateValidatorFactoryObserver {
20+
/**
21+
* A callback invoked upon the successful creation of a factory.
22+
*
23+
* @param factory The fully initialized factory.
24+
*/
25+
default void factoryCreated(HibernateValidatorFactory factory) {
26+
}
27+
28+
/**
29+
* A callback invoked just before the factory is shut down.
30+
*
31+
* @param factory The factory that is about to be closed.
32+
*/
33+
default void factoryClosing(HibernateValidatorFactory factory) {
34+
}
35+
36+
/**
37+
* A callback invoked after the factory has been successfully shut down.
38+
*
39+
* @param factory The closed factory.
40+
*/
41+
default void factoryClosed(HibernateValidatorFactory factory) {
42+
}
43+
}

‎engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.io.InputStream;
1313
import java.lang.invoke.MethodHandles;
1414
import java.time.Duration;
15+
import java.util.ArrayList;
1516
import java.util.Collections;
1617
import java.util.HashMap;
1718
import java.util.List;
@@ -35,6 +36,7 @@
3536

3637
import org.hibernate.validator.BaseHibernateValidatorConfiguration;
3738
import org.hibernate.validator.cfg.ConstraintMapping;
39+
import org.hibernate.validator.constraintvalidation.HibernateValidatorFactoryObserver;
3840
import org.hibernate.validator.constraintvalidation.spi.DefaultConstraintValidatorFactory;
3941
import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping;
4042
import org.hibernate.validator.internal.engine.constraintvalidation.HibernateConstraintValidatorInitializationSharedServiceManager;
@@ -134,6 +136,7 @@ public abstract class AbstractConfigurationImpl<T extends BaseHibernateValidator
134136
private ExpressionLanguageFeatureLevel customViolationExpressionLanguageFeatureLevel;
135137
private ProcessedBeansTrackingVoter processedBeansTrackingVoter;
136138
private boolean showValidatedValuesInTraceLogs;
139+
private List<HibernateValidatorFactoryObserver> hibernateValidatorFactoryObservers;
137140

138141
protected AbstractConfigurationImpl(BootstrapState state) {
139142
this();
@@ -711,14 +714,28 @@ public T processedBeansTrackingVoter(ProcessedBeansTrackingVoter processedBeansT
711714
return thisAsT();
712715
}
713716

714-
public ProcessedBeansTrackingVoter getProcessedBeansTrackingVoter() {
717+
@Override
718+
public T addHibernateValidatorFactoryObserver(HibernateValidatorFactoryObserver observer) {
719+
Contracts.assertNotNull( observer, MESSAGES.parameterMustNotBeNull( "observer" ) );
720+
if ( hibernateValidatorFactoryObservers == null ) {
721+
hibernateValidatorFactoryObservers = new ArrayList<>();
722+
}
723+
hibernateValidatorFactoryObservers.add( observer );
724+
return thisAsT();
725+
}
726+
727+
public final ProcessedBeansTrackingVoter getProcessedBeansTrackingVoter() {
715728
return processedBeansTrackingVoter;
716729
}
717730

718731
public final Set<DefaultConstraintMapping> getProgrammaticMappings() {
719732
return programmaticMappings;
720733
}
721734

735+
public final List<HibernateValidatorFactoryObserver> getHibernateValidatorFactoryObservers() {
736+
return hibernateValidatorFactoryObservers == null ? List.of() : hibernateValidatorFactoryObservers;
737+
}
738+
722739
private boolean isSpecificProvider() {
723740
return validationBootstrapParameters.getProvider() != null;
724741
}

‎engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
*/
55
package org.hibernate.validator.internal.engine;
66

7+
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.OBSERVE_FACTORY_CLOSED;
8+
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.OBSERVE_FACTORY_CLOSING;
9+
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.OBSERVE_FACTORY_CREATED;
710
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowMultipleCascadedValidationOnReturnValues;
811
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowOverridingMethodAlterParameterConstraint;
912
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowParallelMethodsDefineParameterConstraints;
@@ -16,13 +19,15 @@
1619
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineExternalClassLoader;
1720
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineFailFast;
1821
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineFailFastOnPropertyViolation;
22+
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineHibernateValidatorFactoryObservers;
1923
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineScriptEvaluatorFactory;
2024
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineServiceLoadedConstraintMappings;
2125
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineShowValidatedValuesInTraceLogs;
2226
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineTemporalValidationTolerance;
2327
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineTraversableResolverResultCacheEnabled;
2428
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.logValidatorFactoryScopedConfiguration;
2529
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.registerCustomConstraintValidators;
30+
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.safeObserve;
2631
import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList;
2732

2833
import java.lang.invoke.MethodHandles;
@@ -45,6 +50,7 @@
4550
import org.hibernate.validator.HibernateValidatorContext;
4651
import org.hibernate.validator.HibernateValidatorFactory;
4752
import org.hibernate.validator.PredefinedScopeHibernateValidatorFactory;
53+
import org.hibernate.validator.constraintvalidation.HibernateValidatorFactoryObserver;
4854
import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping;
4955
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager;
5056
import org.hibernate.validator.internal.engine.constraintvalidation.HibernateConstraintValidatorInitializationContextImpl;
@@ -104,6 +110,8 @@ public class PredefinedScopeValidatorFactoryImpl implements PredefinedScopeHiber
104110

105111
private final ValidationOrderGenerator validationOrderGenerator;
106112

113+
private final List<HibernateValidatorFactoryObserver> hibernateValidatorFactoryObservers;
114+
107115
public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState) {
108116
Contracts.assertTrue( configurationState instanceof PredefinedScopeConfigurationImpl, "Only PredefinedScopeConfigurationImpl is supported." );
109117

@@ -254,9 +262,13 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState
254262
// at this point all constraints had to be initialized, so we can clear up the pattern cache:
255263
patternConstraintInitializer.close();
256264

265+
this.hibernateValidatorFactoryObservers = determineHibernateValidatorFactoryObservers( configurationState, properties, externalClassLoader );
266+
safeObserve( hibernateValidatorFactoryObservers, this, OBSERVE_FACTORY_CREATED );
267+
257268
if ( LOG.isDebugEnabled() ) {
258269
logValidatorFactoryScopedConfiguration( validatorFactoryScopedContext );
259270
}
271+
260272
}
261273

262274
@Override
@@ -342,10 +354,14 @@ public HibernateValidatorContext usingContext() {
342354

343355
@Override
344356
public void close() {
357+
safeObserve( hibernateValidatorFactoryObservers, this, OBSERVE_FACTORY_CLOSING );
358+
345359
constraintValidatorManager.clear();
346360
beanMetaDataManager.clear();
347361
validatorFactoryScopedContext.getScriptEvaluatorFactory().clear();
348362
valueExtractorManager.clear();
363+
364+
safeObserve( hibernateValidatorFactoryObservers, this, OBSERVE_FACTORY_CLOSED );
349365
}
350366

351367
public ValidatorFactoryScopedContext getValidatorFactoryScopedContext() {

‎engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java‎

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@
1414
import java.util.List;
1515
import java.util.Map;
1616
import java.util.Set;
17+
import java.util.function.BiConsumer;
1718

1819
import jakarta.validation.spi.ConfigurationState;
1920

2021
import org.hibernate.validator.HibernateValidatorConfiguration;
22+
import org.hibernate.validator.HibernateValidatorFactory;
2123
import org.hibernate.validator.cfg.ConstraintMapping;
24+
import org.hibernate.validator.constraintvalidation.HibernateValidatorFactoryObserver;
2225
import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping;
2326
import org.hibernate.validator.internal.engine.constraintdefinition.ConstraintDefinitionContribution;
2427
import org.hibernate.validator.internal.engine.constraintvalidation.HibernateConstraintValidatorInitializationSharedServiceManager;
@@ -48,6 +51,10 @@ final class ValidatorFactoryConfigurationHelper {
4851

4952
private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
5053

54+
static final BiConsumer<HibernateValidatorFactoryObserver, HibernateValidatorFactory> OBSERVE_FACTORY_CLOSING = HibernateValidatorFactoryObserver::factoryClosing;
55+
static final BiConsumer<HibernateValidatorFactoryObserver, HibernateValidatorFactory> OBSERVE_FACTORY_CLOSED = HibernateValidatorFactoryObserver::factoryClosed;
56+
static final BiConsumer<HibernateValidatorFactoryObserver, HibernateValidatorFactory> OBSERVE_FACTORY_CREATED = HibernateValidatorFactoryObserver::factoryCreated;
57+
5158
private ValidatorFactoryConfigurationHelper() {
5259
}
5360

@@ -61,9 +68,7 @@ static Set<DefaultConstraintMapping> determineConstraintMappings(TypeResolutionH
6168
ConfigurationState configurationState, JavaBeanHelper javaBeanHelper, ClassLoader externalClassLoader) {
6269
Set<DefaultConstraintMapping> constraintMappings = newHashSet();
6370

64-
if ( configurationState instanceof AbstractConfigurationImpl ) {
65-
AbstractConfigurationImpl<?> hibernateConfiguration = (AbstractConfigurationImpl<?>) configurationState;
66-
71+
if ( configurationState instanceof AbstractConfigurationImpl<?> hibernateConfiguration ) {
6772
// programmatic config
6873
/* We add these first so that constraint mapping created through DefaultConstraintMappingBuilder will take
6974
* these programmatically defined mappings into account when checking for constraint definition uniqueness
@@ -204,8 +209,7 @@ static boolean determineFailFastOnPropertyViolation(AbstractConfigurationImpl<?>
204209

205210
static ScriptEvaluatorFactory determineScriptEvaluatorFactory(ConfigurationState configurationState, Map<String, String> properties,
206211
ClassLoader externalClassLoader) {
207-
if ( configurationState instanceof AbstractConfigurationImpl ) {
208-
AbstractConfigurationImpl<?> hibernateSpecificConfig = (AbstractConfigurationImpl<?>) configurationState;
212+
if ( configurationState instanceof AbstractConfigurationImpl<?> hibernateSpecificConfig ) {
209213
if ( hibernateSpecificConfig.getScriptEvaluatorFactory() != null ) {
210214
LOG.usingScriptEvaluatorFactory( hibernateSpecificConfig.getScriptEvaluatorFactory().getClass() );
211215
return hibernateSpecificConfig.getScriptEvaluatorFactory();
@@ -231,8 +235,7 @@ static ScriptEvaluatorFactory determineScriptEvaluatorFactory(ConfigurationState
231235
}
232236

233237
static Duration determineTemporalValidationTolerance(ConfigurationState configurationState, Map<String, String> properties) {
234-
if ( configurationState instanceof AbstractConfigurationImpl ) {
235-
AbstractConfigurationImpl<?> hibernateSpecificConfig = (AbstractConfigurationImpl<?>) configurationState;
238+
if ( configurationState instanceof AbstractConfigurationImpl<?> hibernateSpecificConfig ) {
236239
if ( hibernateSpecificConfig.getTemporalValidationTolerance() != null ) {
237240
LOG.logTemporalValidationTolerance( hibernateSpecificConfig.getTemporalValidationTolerance() );
238241
return hibernateSpecificConfig.getTemporalValidationTolerance();
@@ -453,6 +456,42 @@ static boolean determineShowValidatedValuesInTraceLogs(AbstractConfigurationImpl
453456
return tmpShowValidatedValuesInTraceLogging;
454457
}
455458

459+
static List<HibernateValidatorFactoryObserver> determineHibernateValidatorFactoryObservers(ConfigurationState configurationState, Map<String, String> properties, ClassLoader externalClassLoader) {
460+
List<HibernateValidatorFactoryObserver> observers = newArrayList();
461+
if ( configurationState instanceof AbstractConfigurationImpl<?> hibernateSpecificConfig ) {
462+
observers.addAll( hibernateSpecificConfig.getHibernateValidatorFactoryObservers() );
463+
}
464+
465+
String[] observerFqcn = properties.getOrDefault( HibernateValidatorConfiguration.HIBERNATE_VALIDATOR_FACTORY_OBSERVER, "" ).split( "," );
466+
for ( String fqcn : observerFqcn ) {
467+
if ( fqcn == null || fqcn.isBlank() ) {
468+
continue;
469+
}
470+
try {
471+
@SuppressWarnings("unchecked")
472+
Class<? extends HibernateValidatorFactoryObserver> clazz = (Class<? extends HibernateValidatorFactoryObserver>) LoadClass.action( fqcn, externalClassLoader );
473+
HibernateValidatorFactoryObserver observer = NewInstance.action( clazz, "Hibernate Validator factory observer class" );
474+
observers.add( observer );
475+
}
476+
catch (Exception e) {
477+
throw LOG.getUnableToInstantiateFactoryObserverClassException( fqcn, e );
478+
}
479+
}
480+
return observers;
481+
}
482+
483+
static void safeObserve(List<HibernateValidatorFactoryObserver> hibernateValidatorFactoryObservers, HibernateValidatorFactory factory,
484+
BiConsumer<HibernateValidatorFactoryObserver, HibernateValidatorFactory> action) {
485+
for ( HibernateValidatorFactoryObserver observer : hibernateValidatorFactoryObservers ) {
486+
try {
487+
action.accept( observer, factory );
488+
}
489+
catch (Exception e) {
490+
LOG.unexpectedObserverException( observer, e );
491+
}
492+
}
493+
}
494+
456495
static void logValidatorFactoryScopedConfiguration(ValidatorFactoryScopedContext context) {
457496
LOG.logValidatorFactoryScopedConfiguration( context.getMessageInterpolator().getClass(), "message interpolator" );
458497
LOG.logValidatorFactoryScopedConfiguration( context.getTraversableResolver().getClass(), "traversable resolver" );

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /